#wip: Bash done. Python base done. Building SQL Server base.

This commit is contained in:
KyMAN 2026-03-02 06:59:40 +01:00
parent 53662c1b38
commit c178dbd9b2
9 changed files with 1569 additions and 1 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
/Data
/Public/data
__pycache__
*.[Ss]ecrets.*
*.[Ss]ecret.*
/Python/pyodbc.py

View File

@ -0,0 +1,2 @@
#!/bin/bash
nohup ./tu_script.sh > /dev/null 2>&1 &

View File

@ -0,0 +1,160 @@
#!/bin/bash
# Settings.
key="kyman_9750h"
candle_seconds=10
candle_sleep_seconds=1
execute_sleep_seconds=0
show_json=true
send_json=true
url_server="http://192.168.1.131:13000/debian"
# Settings.
function get_net_data(){
echo $(cat /proc/net/dev|tail -n +3|awk '{
interface = $1;
gsub(/:/, "", interface);
array = "[\"" interface "\"," $2 "," $3 "," $4 "," $10 "," $11 "," $12 "]";
json = json == "" ? array : json "," array;
}END{
print "[" json "]";
}')
}
function execute(){
local domain=$(hostname -d)
local ips=$(ip -o addr|awk '{
is_ipv6 = $3 == "inet6" ? "true" : "false";
split($1, i, ":");
split($4, ip, "/");
array = "[" i[1] ",\"" $2 "\"," is_ipv6 ",\"" ip[1] "\"," ip[2] "]";
json = json == "" ? array : json "," array;
}END{
print "[" json "]";
}')
local hostnames=$(hostname -A|awk '{
json = json == "" ? "\"" $1 "\"" : json ",\"" $1 "\"";
}END{
print "[" json "]";
}')
local disks=$(lsblk -b -n -o name,size,fsavail,mountpoint|grep -E '└─|├─'|awk '{
device = $1;
total = $2;
available = $3 ~ /^\// || $3 == "" ? 0 : $3;
mountpoint = $4 != "" ? "\"" $4 "\"" : $3 ~ /^\// ? "null" : "\"" $3 "\"";
gsub(/├─|└─/, "", device);
array = "[\"" device "\"," total "," available "," mountpoint "]";
json = json == "" ? array : json "," array;
}END{
print "[" json "]";
}')
local iterations=0
local cpu_in=
local cpu_out=
local cpu_minimum=
local cpu_maximum=
local cpu_average=0
local memory_in=
local memory_out=
local memory_minimum=
local memory_maximum=
local memory_average=0
local memory_total=$(cat /proc/meminfo|grep MemTotal:|awk '{print $2 * 1024}')
local limit_seconds=$(($(date +%s) + $candle_seconds))
local json="["
local net_data="["
local candle_start=$(date +%s)
local candle_end=
net_data=$net_data$(get_net_data)
while true; do
cpu=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}')
# memory=$(cat /proc/meminfo|grep MemFree:|awk '{print $2 * 1024}')
memory=$(cat /proc/meminfo|grep MemAvailable:|awk '{print $2 * 1024}')
# cpu_average=$((cpu_average + cpu))
# memory_average=$((memory_average + memory))
cpu_average=$(echo "$cpu_average + $cpu"|bc -l)
memory_average=$(echo "$memory_average + $memory"|bc -l)
cpu=${cpu/,/.}
cpu_out=$cpu
memory_out=$memory
iterations=$((iterations + 1))
if [ -z "$cpu_in" ]; then
cpu_in=$cpu
memory_in=$memory
cpu_minimum=$cpu
cpu_maximum=$cpu
memory_minimum=$memory
memory_maximum=$memory
else
if [ "$(echo "$cpu < $cpu_minimum"|bc -l)" -eq 1 ];then cpu_minimum=$cpu;fi
if [ "$(echo "$cpu > $cpu_maximum"|bc -l)" -eq 1 ];then cpu_maximum=$cpu;fi
if [ "$(echo "$memory < $memory_minimum"|bc -l)" -eq 1 ];then memory_minimum=$memory;fi
if [ "$(echo "$memory > $memory_maximum"|bc -l)" -eq 1 ];then memory_maximum=$memory;fi
# cpu_minimum=$(echo -e "$cpu_minimum\n$cpu" | sort -n | head -1)
# cpu_maximum=$(echo -e "$cpu_maximum\n$cpu" | sort -n | tail -1)
# memory_minimum=$(echo -e "$memory_minimum\n$memory" | sort -n | head -1)
# memory_maximum=$(echo -e "$memory_maximum\n$memory" | sort -n | tail -1)
if [ $(date +%s) -ge $limit_seconds ]; then
break
fi
sleep 1
fi
done
if [ -z "$domain" ]; then
domain="null"
else
domain="\"$domain\""
fi
# cpu_average=$((cpu_average / iterations))
# memory_average=$((memory_average / iterations))
cpu_average=$(echo "scale=6; $cpu_average / $iterations"|bc|awk '{printf $1 + 0}')
memory_average=$(echo "scale=6; $memory_average / $iterations"|bc|awk '{printf $1 + 0}')
net_data="$net_data,$(get_net_data)]"
candle_end=$(date +%s)
json="$json$hostnames,$domain,$ips,$disks,$iterations"
json="$json,[$candle_start,$candle_end]"
json="$json,[${cpu_in//,/.},${cpu_out//,/.},${cpu_minimum//,/.},${cpu_maximum//,/.},$cpu_average]"
json="$json,[$memory_total,$memory_in,$memory_out,$memory_minimum,$memory_maximum,$memory_average]"
json="$json,$net_data"
json="$json]"
if [ "$show_json" = true ]; then echo "$json";fi
if [ "$send_json" = true ]; then
local response=$(echo "$json"|curl -s -X POST -H "Content-Type: application/json" -d @- "$url_server/$key")
fi
}
while true; do
execute
if [ $execute_sleep_seconds -gt 0 ]; then
sleep $execute_sleep_seconds
fi
done

1
Public/index.html Normal file
View File

@ -0,0 +1 @@
<h1>Funca</h1>

738
Python/NucelarMonitor.py Normal file
View File

@ -0,0 +1,738 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import datetime
from typing import Any, Optional, Sequence, Self, Callable
from re import compile as re_compile, Pattern as REPattern, Match as REMatch, IGNORECASE as RE_IGNORE_CASE
from pyodbc import connect as pyodbc_connect
from socket import socket as Socket, AF_INET as ADDRESS_FAMILY_IPV4, SOCK_STREAM as SOCKET_STREAM, SOL_SOCKET as SOCKET_LAYER, SO_REUSEADDR as SOCKET_REUSE_ADDRESS
from inspect import stack as get_stack, FrameInfo
from traceback import format_stack as trace_format_stack, extract_tb as extract_traceback
from threading import Thread
from os.path import exists as path_exists, dirname as directory_name, abspath as absolute_path
from json import loads as json_decode, dumps as json_encode
from mimetypes import guess_type as get_mime_by_extension
class NucelarMonitor:
DEFAULT_SETTINGS:dict[str, Any|None] = {
"autostart" : True,
"print_format" : "[{type}] {yyyy}{mm}{dd} {hh}{ii}{ss} [{line}]{file}({method}): {message}",
"exception_format" : " '[{line}]{file}({method})'{lines}\n\n{exception_message}",
"print_types" : [
["unkn", "unknown"],
["info", "information"],
["warn", "warning"],
["erro", "error", "wrong", "failure", "fail", "no"],
["exce", "exception", "except"],
[" ok ", "ok", "success", "succeed", "yes"],
["test", "debug"]
],
"http_host" : "0.0.0.0",
"http_port" : 13000,
"http_cache_size" : 1024,
"http_maximum_connections" : 5,
"http_header_response" : (
"{http_protocol}/{http_version} {http_code} {http_message}\r\n" +
"Content-Type: {mime}\r\n" +
"Content-Length: {length}\r\n" +
"\r\n"
),
"http_protocol" : "HTTP",
"http_version" : "1.1",
"http_code" : 200,
"http_message" : "OK",
"http_encoder" : "utf-8",
"index_files" : ("index.html", "index.htm"),
"sql_host" : "127.0.0.1",
"sql_port" : 1433,
"sql_user" : "sa",
"sql_password" : "password",
"sql_database" : "NucelarMonitor",
"default_controllers" : {
"get" : {
"/" : "/Public"
},
"post" : {
"/debian/{key}" : "debian"
}
},
"default_connections" : {}
}
DEFAULT_I18N:dict[str, dict[str, str|Sequence[str]]] = {
"english" : {}
}
ROOT:str = directory_name(absolute_path(__file__))
SLASH:str = "/" if "/" in ROOT else "\\\\"
SPECIAL_REGULAR_EXPRESSION_CHARACTERS:dict[str, str] = {
"\r" : "r",
"\n" : "n",
"\t" : "t"
}
RE_KEY:REPattern = re_compile(r'^[a-z_][a-z0-9_]*$', RE_IGNORE_CASE)
RE_STRING_VARIABLE:REPattern = re_compile(r'\{([a-z_][a-z0-9_]*)\}', RE_IGNORE_CASE)
RE_EXCEPTION:REPattern = re_compile(r'^\s*File "([^"]+)", line ([0-9]+), in ([^\n]+)(.*|[\r\n]*)*$')
RE_NEW_LINE:REPattern = re_compile(r'\r\n|[\r\n]')
RE_TO_SNAKE:REPattern = re_compile(r'[^a-zA-Z0-9]*([A-Z][A-Z0-9]*)|[^a-z0-9]+')
RE_HTTP_REQUEST:REPattern = re_compile(r'^([^\s]+)\s([^\s\?\#]+)(?:\?([^#]+))?(?:\#[^\s]+)?\s([^\/]+)\/([0-9\.]+)$')
RE_HEADER_LINE:REPattern = re_compile(r'^([^\:]+)\:(.+)$')
RE_HTTP_BLOCKS:REPattern = re_compile(r'((?:(?!(?:(?:\r\n){2}|\n{2}|\r{2}))(?:.|[\r\n]+))+)(?:(?:(?:\r\n){2}|\n{2}|\r{2})((?:.+|[\r\n]+)*))?')
RE_LAST_DIRECTORY:REPattern = re_compile(r'^(.*)[\/][^\/]*\/?$')
RE_SLASHES:REPattern = re_compile(r'[\\\/]+')
RE_TO_REGULAR_EXPRESSION:REPattern = re_compile(r'[\(\)\{\}\/\\\.\-\+\*\^\$\?\|\!\<\>\r\n\t]')
RE_ROUTE_KEY:REPattern = re_compile(r'\\\{([a-z_][a-z0-9_]*)\\\}', RE_IGNORE_CASE)
class Request:
def __init__(self:Self, data:bytes, encoder:str = "utf-8") -> None:
self.method:str
self.request:str
self.value_get:str|None
self.variables_get:dict[str, str]
self.variables_post:dict[str, str]
self.protocol:str
self.protocol_version:str
self.body:str
self.variables_uri:dict[str, str] = {}
header, body = (lambda header, body:(
NucelarMonitor.RE_NEW_LINE.split(str(header).strip()), body
))(*NucelarMonitor.RE_HTTP_BLOCKS.match(data.decode(encoder)).groups())
(
self.method,
self.request,
self.value_get,
self.variables_get,
self.protocol,
self.protocol_version
) = (lambda method, request, variables, protocol, protocol_version:(
str(method).lower(),
request,
variables,
self.parse_variables(variables),
protocol,
protocol_version
))(*NucelarMonitor.RE_HTTP_REQUEST.match(header[0]).groups())
self.body = body
self.variables_post = self.parse_variables(body)
def set_uri_variables(self:Self, keys:list[str], matches:REMatch) -> None:
i:int
value:str
for i, value in enumerate(matches.groups()):
self.variables_uri[keys[i]] = value
def get(self:Self, keys:str|Sequence[str], default:Optional[Any] = None) -> Any|None:
return NucelarMonitor.get_value(keys, (
self.variables_uri, self.variables_get, self.variables_post
), default)
@classmethod
def parse_variables(cls:type[Self], string:Optional[str]) -> dict[str, str]:
if not string:
return {}
variables:dict[str, str] = {}
pair:str
for pair in string.split("&"):
if "=" in pair:
key, value = pair.split("=", 1)
variables[cls.to_snake(key)] = value
else:
variables[cls.to_snake(pair)] = ""
return variables
@staticmethod
def to_snake(string:str) -> str:
def callback(matches:REMatch) -> str:
upper:str|None = matches.group(1)
return "_" + upper.lower() if upper else "_"
return NucelarMonitor.RE_TO_SNAKE.sub(callback, string).lower()
class Response:
def __init__(self:Self,
nucelar_monitor:type[Self],
response:Optional[Any] = None,
mime:Optional[str] = None,
code:Optional[int] = None,
message:Optional[str] = None
) -> None:
default_code:int
default_message:str
self.nucelar_monitor:NucelarMonitor = nucelar_monitor
default_code, default_message = self.nucelar_monitor.get_http_default_code()
self.body:bytes = b""
self.mime:str
self.code:str = code or default_code
self.message:str = default_message if message is None else message
self.set_data(response, mime)
def set_data(self:Self, data:Any|None, mime:Optional[str] = None) -> None:
if isinstance(data, bytes):
self.body = data
self.mime = mime or "application/octet-stream"
elif isinstance(data, str):
self.body = data.encode(self.nucelar_monitor.get_encoder())
self.mime = mime or "text/plain;charset=" + self.nucelar_monitor.get_encoder()
elif isinstance(data, (dict, tuple, list)):
self.body = json_encode(data).encode(self.nucelar_monitor.get_encoder())
self.mime = mime or "application/json;charset=" + self.nucelar_monitor.get_encoder()
else:
self.body = str(data).encode(self.nucelar_monitor.get_encoder())
self.mime = mime or "text/plain;charset=" + self.nucelar_monitor.get_encoder()
def get_parameters(self:Self) -> dict[str, Any|None]:
return {
"http_code" : self.code,
"http_message" : self.message,
"mime" : self.mime,
"length" : len(self.body)
}
def __init__(self:Self, inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None) -> None:
key:str
self.__inputs:dict[str, Any|None] = self.get_dictionary(inputs)
self.__sentences:dict[str, dict[str, str|Sequence[str]]] = self.DEFAULT_I18N
self.__language:str = self.get("language", None, "english")
self.__print_format:str = self.get("print_format")
self.__print_types:list[list[str]] = self.DEFAULT_SETTINGS["print_types"]
self.__exception_format:str = self.get("exception_format")
self.__controllers:dict[str, list[tuple[
REPattern,
tuple[tuple[str, ...]],
Callable[[NucelarMonitor.Request, NucelarMonitor.Response], None]|None,
str|None]
]] = {}
self.__http_host:str = self.get("http_host")
self.__http_port:int = self.get("http_port")
self.__http_server:Socket
self.__http_buffer_size:int = self.get("http_cache_size")
self.__http_header_response:str = self.get("http_header_response")
self.__http_protocol:str = self.get("http_protocol")
self.__http_version:str = self.get("http_version")
self.__http_code:int = self.get("http_code")
self.__http_message:str = self.get("http_message")
self.__http_encoder:str = self.get("http_encoder")
self.__index_files:tuple[str, ...] = tuple(self.get("index_files"))
self.__started:bool = False
self.__working:bool = False
self.__root_paths:list[str] = ["", self.ROOT]
for _ in range(2):
self.__root_paths.append(self.RE_LAST_DIRECTORY.sub(r'\1', self.__root_paths[-1]))
for key in ("default_controllers", "controllers"):
self.add_controllers(self.get(key))
self.get("autostart") and self.start()
def start(self:Self) -> None:
if self.__started:
return
self.__started = True
self.__http_server = Socket(ADDRESS_FAMILY_IPV4, SOCKET_STREAM)
self.__working = True
try:
self.__http_server.setsockopt(SOCKET_LAYER, SOCKET_REUSE_ADDRESS, 1)
self.__http_server.bind((self.__http_host, self.__http_port))
self.__http_server.listen(self.get("http_maximum_connections"))
Thread(target = self.__listen).start()
except Exception as exception:
self.exception(exception, "http_server_start_exception", {
"host" : self.__http_host,
"port" : self.__http_port,
})
self.close()
def close(self:Self) -> None:
if not self.__started:
return
self.__started = False
self.__working = False
try:
self.__http_server.close()
except Exception as exception:
self.exception(exception, "http_server_close_exception", {
"host" : self.__http_host,
"port" : self.__http_port,
})
def get_print_type(self:Self, _type:str) -> str:
group:list[str]
for group in self.__print_types:
if _type in group:
return group[0].upper()
return self.__print_types[0][0].upper()
def print(self:Self,
_type:str,
message:str|Sequence[str],
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None,
i:int = 0
) -> None:
date:datetime = datetime.datetime.now()
own:dict[str, Any|None] = {
"raw_type" : _type,
"type" : self.get_print_type(_type),
"i18n" : self.get_texts(message),
"message" : self.i18n(message, inputs),
**self.get_dictionary(inputs),
**self.get_action_data(i + 1)
}
for key in ("year", "month", "day", "hour", "minute", "second"):
k:str = "i" if key == "minute" else key[0]
own[k] = own[key] = getattr(date, key)
own[k + k] = ("00" + str(own[key]))[-2:]
own["yyyy"] = own["year"]
print(self.string_variables(self.__print_format, own) + (own["end"] if "end" in own else ""))
def exception(self:Self,
exception:Exception,
message:str|Sequence[str],
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None,
i:int = 0
) -> None:
lines:list[str] = extract_traceback(exception.__traceback__).format()
matches:REMatch = self.RE_EXCEPTION.match(lines[-1])
data:dict[str, Any|None] = {
**self.get_dictionary(inputs),
"lines" : "",
"exception_message" : str(exception),
"method" : matches.group(3),
"line" : matches.group(2),
"file" : matches.group(1)
}
block:str
j:int
for j, block in enumerate(trace_format_stack()[:-2] + lines):
if block:
data["lines"] += "\n " + str(j) + " - " + self.RE_NEW_LINE.split(block.strip())[0]
data["end"] = self.string_variables(self.__exception_format, data)
message and self.print("exception", message, data, i + 2)
@classmethod
def fix_path(cls:type[Self], path:str) -> str:
return cls.RE_SLASHES.sub(cls.SLASH, path)
def get_absolute_path(self:Self, path:str) -> str|None:
root:str
absolute:str
for root in self.__root_paths:
absolute = self.fix_path(root + '/' + path)
if path_exists(absolute):
return absolute
return None
def load_file(self:Self, path:str, mode:str = "r") -> str|bytes|None:
path:str = self.get_absolute_path(path)
if path:
with open(path, mode) as file:
return file.read()
return None
def load_json(self:Self, data:str|dict[str, Any|None]|list[Any|None]) -> dict[str, Any|None]|list[Any|None]|None:
if isinstance(data, str):
json:list[Any|None]|dict[str, Any|None]|None
try:
json = json_decode(data)
except Exception as exception:
self.exception(exception, "load_json_exception", {
"data" : data,
"length" : len(data)
})
if json:
return json
try:
return json_decode(self.load_file(data))
except Exception as exception:
self.exception(exception, "load_json_by_file_exception", {
"path" : data
})
return None
elif isinstance(data, (dict, list)):
return data
return None
def get_encoder(self:Self) -> str:
return self.__http_encoder
def get_http_default_code(self:Self) -> tuple[int, str]:
return self.__http_code, self.__http_message
def get(self:Self,
keys:str|Sequence[str],
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None,
default:Optional[Any] = None
) -> Any|None:
return self.get_value(keys, (inputs, self.__inputs, self.DEFAULT_SETTINGS), default)
def __get_text(self:Self, strings:str|Sequence[str]) -> str:
keys:list[str] = self.get_keys(strings := self.get_list(strings))
if len(keys):
language:str
used:list[str] = []
for language in [self.__language] + list(self.__sentences.keys()):
if language not in used and language in self.__sentences:
key:str
used.append(language)
for key in keys:
if key in self.__sentences[language]:
return self.__sentences[language][key]
return strings[0]
def i18n(self:Self,
strings:str|Sequence[str],
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None
) -> str:
return self.string_variables(self.__get_text(strings), inputs)
def add_controllers(self:Self,
inputs:str|dict[str, dict[str, str|Callable[[Request], None]]]|Sequence[Any|None]
) -> None:
if isinstance(inputs, dict):
method:str
controllers:dict[str, str|Callable[[NucelarMonitor.Request], None]]
for method, controllers in inputs.items():
if (method := method.lower()) not in self.__controllers:
self.__controllers[method] = []
if isinstance(controllers, dict):
request:str
target:str|Callable[[NucelarMonitor.Request], None]
for request, target in controllers.items():
controller:Callable[[NucelarMonitor.Request, NucelarMonitor.Response], None]|None = None
path:str|None = None
if isinstance(target, str) and (controller := getattr(self, target, None)) is None:
path = self.get_absolute_path(target)
if callable(controller) or path is not None:
variables:list[str] = []
def callback(matches:REMatch) -> str:
variables.append(matches.group(1))
return r'([^\/]+)'
self.__controllers[method].append((re_compile(r'^' + self.RE_ROUTE_KEY.sub(callback, self.to_regular_expression(
request[:-1] if request[-1] == "/" else request
)) + (r'' if path is None else r'(.*)') + r'\/?$'), tuple(variables), controller, path))
elif isinstance(inputs, (list, tuple)):
subinputs:Any|None
for subinputs in inputs:
self.add_controllers(subinputs)
elif isinstance(inputs, str):
self.add_controllers(self.load_json(inputs))
def __listen(self:Self) -> None:
while self.__working:
try:
client:Socket
address:str
port:int
client, (address, port) = self.__http_server.accept()
Thread(
target = self.__listen_client,
args = (client, address, port)
).start()
except Exception as exception:
self.exception(exception, "http_server_listen_exception", {
"host" : self.__http_host,
"port" : self.__http_port,
})
def __listen_client(self:Self, client:Socket, address:str, port:int) -> None:
data:bytes = b""
route:str = ""
method:str = "UNKN"
response:NucelarMonitor.Response = NucelarMonitor.Response(self)
try:
request:NucelarMonitor.Request
variables:tuple[str, ...]
controller:Callable[[NucelarMonitor.Request], Any|None]|None
path:str|None
response_data:Any|None = None
pattern:REPattern
done:bool = False
while True:
buffer:bytes = client.recv(self.__http_buffer_size)
if not buffer:
break
data += buffer
if len(buffer) != self.__http_buffer_size:
break
for pattern, variables, controller, path in self.__controllers[
method := (request := self.Request(data, self.__http_encoder)).method
]:
matches:REMatch = pattern.match(route := request.request)
if matches is not None:
request.set_uri_variables(variables, matches)
if done := path is not None:
for index in self.__index_files:
full_path = path + "/" + route + ("" if index == "" else "/" + index)
if done := (response_data := self.load_file(full_path, "rb")) is not None:
response.set_data(
response_data,
get_mime_by_extension(full_path)[0] or "application/octet-stream"
)
break
elif done := controller is not None:
controller(request, response)
if done:
break
if not done:
response.body = b"<h1>Not Found</h1>"
response.mime = "text/html;charset=" + self.__http_encoder
response.code = "404"
response.message = "Not Found"
client.sendall(self.string_variables(self.__http_header_response, {
"http_protocol" : self.__http_protocol,
"http_version" : self.__http_version,
**response.get_parameters()
}).encode(self.__http_encoder) + response.body)
client.close()
except Exception as exception:
self.exception(exception, "http_server_client_exception", {
"host" : self.__http_host,
"port" : self.__http_port,
"client_address" : address,
"client_port" : port,
"length" : len(data),
"method" : method,
"route" : route,
"response_length" : len(response.body)
})
def debian(self:Self, request:Request, response:Response) -> None:
key:str = request.get("key")
hostnames:list[str]
domain:str|None
interfaces:list[list[int, str, bool, str, int]]
disks:list[list[str, int, int, str|None]]
iterations:int
candle_times:list[int, int]
cpu:list[float, float, float, float, float]
memory:list[int, int, int, int, int, float]
net_use:list[list[list[str, int, int, int, int, int, int]]]
hostnames, domain, interfaces, disks, iterations, candle_times, cpu, memory, net_use = json_decode(request.body)
@classmethod
def get_dictionary(cls:type[Self], *items:Sequence[Any|None]) -> dict[str, Any|None]:
dictionary:dict[str, Any|None] = {}
item:Any|None
for item in items:
if isinstance(item, dict):
dictionary.update(item)
elif isinstance(item, (list, tuple)):
subitem:Any|None
for subitem in item:
dictionary.update(cls.get_dictionary(subitem))
return dictionary
@classmethod
def get_keys(cls:type[Self], *items:Sequence[Any|None]) -> list[str]:
keys:list[str] = []
item:Any|None
for item in items:
if isinstance(item, str):
cls.RE_KEY.match(item) and keys.append(item)
elif isinstance(item, (list, tuple)):
subitem:Any|None
for subitem in item:
keys.extend(cls.get_keys(subitem))
return keys
@classmethod
def get_dictionaries(cls:type[Self], *items:Sequence[Any|None]) -> list[dict[str, Any|None]]:
dictionaries:list[dict[str, Any|None]] = []
item:Any|None
for item in items:
if isinstance(item, dict):
dictionaries.append(item)
elif isinstance(item, (list, tuple)):
subitem:Any|None
for subitem in item:
dictionaries.extend(cls.get_dictionaries(subitem))
return dictionaries
@classmethod
def get_value(cls:type[Self],
keys:str|Sequence[str],
inputs:dict[str, Any|None]|Sequence[Any|None],
default:Optional[Any] = None
) -> Any|None:
if len(cls.get_keys(keys)):
dictionary:dict[str, Any|None]
for dictionary in cls.get_dictionaries(inputs):
key:str
for key in cls.get_keys(keys):
if key in dictionary:
return dictionary[key]
return default
@staticmethod
def get_list(item:Any|None) -> list[Any|None]:
return item if isinstance(item, (list, tuple)) else [item]
@classmethod
def string_variables(cls:type[Self],
string:str,
inputs:dict[str, Any|None]|Sequence[Any|None],
default:Optional[str] = None
) -> str:
variables:dict[str, Any|None] = cls.get_dictionary(inputs)
def callback(matches:REMatch) -> str:
key:str = matches.group(1)
return (
str(variables[key]) if key in variables else
default if default is not None else
matches.group(0))
return cls.RE_STRING_VARIABLE.sub(callback, string)
@staticmethod
def get_texts(*items:list[Any|None]) -> list[str]:
texts:list[str] = []
item:Any|None
for item in items:
if isinstance(item, str):
texts.append(item)
elif isinstance(item, (list, tuple)):
subitem:Any|None
for subitem in item:
texts.extend(NucelarMonitor.get_texts(subitem))
return texts
@staticmethod
def get_action_data(i:int = 0) -> dict[str, str|int]:
stack:FrameInfo = get_stack()[i]
return {
"file" : stack.filename,
"method" : stack.function,
"line" : stack.lineno
}
@classmethod
def to_regular_expression(cls:type[Self], string:str) -> str:
def callback(matches:REMatch) -> str:
character:str = matches.group(0)
return "\\" + (
cls.SPECIAL_REGULAR_EXPRESSION_CHARACTERS[character] if character in cls.SPECIAL_REGULAR_EXPRESSION_CHARACTERS else
character)
return cls.RE_TO_REGULAR_EXPRESSION.sub(callback, string)

6
Python/run.py Normal file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from NucelarMonitor import NucelarMonitor
nucelar_monitor:NucelarMonitor = NucelarMonitor()

View File

@ -1,3 +1,48 @@
# NucelarMonitor
NucelarMonitor is a very single project for monitoring OS and their Hardware and services in Stream via Web from server.
NucelarMonitor is a very single project for monitoring OS and their Hardware and services in Stream via Web from server.
# Notes
Datos de envío Debian:
0. `list[str]`: Hostnames.
1. `str|None`: Domain.
2. `list[list[int, str, bool, str, int]]`: Interfaces de red. Por cada uno:
0. `int`: i. Identificador de posición.
1. `str`: Nombre.
2. `bool`: ¿Es IPv6?
3. `str`: IP.
4. `int`: Máscara.
3. `list[list[str, int, int, str|None]]`: Discos. Por cada uno:
0. `str`: Nombre.
1. `int`: Capacidad.
2. `int`: Espacio libre.
3. `str|None`: Punto de montaje.
4. `int`: Iteraciones o ciclos de conteo de las velas.
5. `list[int, int]`: Timestamp de inicio y de fin de las velas.
0. `int`: Timestamp de inicio.
1. `int`: Timestamp de fin.
6. `list[float, float, float, float, float]`: Vela de uso porcentual de la CPU:
0. `float`: Entrada.
1. `float`: Salida.
2. `float`: Mínimo.
3. `float`: Máximo.
4. `float`: Media.
7. `list[int, int, int, int, int, float]`: Vela de uso de la memoria RAM.
0. `int`: Total de memoria.
1. `int`: Entrada.
2. `int`: Salida.
3. `int`: Mínimo.
4. `int`: Máximo.
5. `float`: Media.
8. `list[list[list[str, int, int, int, int, int, int]]]`: Uso de Red. Está diseñado en un proceso de diferencia Entrada/Salida. Es una lista de dos listas, entrada y salida, el segundo nivel tiene una lista por cada interfaz de red, las cuales tienen:
0. `str`: Nombre. Identifica la interfaz de red.
1. `int`: Bytes recepcionados actualmente.
2. `int`: Paquetes recepcionados actualmente.
3. `int`: Errores en recepción actualmente.
4. `int`: Bytes enviados actualmente.
5. `int`: Paquetes enviados actualmente.
6. `int`: Errores en envío actualmente.
La idea es procesar el uso de red en Python.

View File

@ -0,0 +1,609 @@
if (select top 1 0 from sys.databases where name = 'NucelarMonitor') is null create database NucelarMonitor collate Latin1_General_100_CI_AS_SC_UTF8
go
use NucelarMonitor
if object_id(N'dbo.tables_drop', N'P') is not null drop procedure dbo.tables_drop
go
create procedure dbo.tables_drop as begin
set nocount on
-- Level Plains.
-- Level 2.
if object_id(N'dbo.MachineInterfacesData', N'U') is not null drop table dbo.MachineInterfacesData
if object_id(N'dbo.MachineInterfacesTraffic', N'U') is not null drop table dbo.MachineInterfacesTraffic
if object_id(N'dbo.MachineDisksSpace', N'U') is not null drop table dbo.MachineDisksSpace
if object_id(N'dbo.Exceptions', N'U') is not null drop table dbo.Exceptions
-- Level 1.
if object_id(N'dbo.MachineInterfaces', N'U') is not null drop table dbo.MachineInterfaces
if object_id(N'dbo.MachineDisks', N'U') is not null drop table dbo.MachineDisks
if object_id(N'dbo.MachineRAM', N'U') is not null drop table dbo.MachineRAM
if object_id(N'dbo.MachineCPU', N'U') is not null drop table dbo.MachineCPU
if object_id(N'dbo.Procedures', N'U') is not null drop table dbo.Procedures
-- Level 0.
if object_id(N'dbo.CandlesTimes', N'U') is not null drop table dbo.CandlesTimes
if object_id(N'dbo.Interfaces', N'U') is not null drop table dbo.Interfaces
if object_id(N'dbo.Disks', N'U') is not null drop table dbo.Disks
if object_id(N'dbo.Hostnames', N'U') is not null drop table dbo.Hostnames
if object_id(N'dbo.Domains', N'U') is not null drop table dbo.Domains
if object_id(N'dbo.Machines', N'U') is not null drop table dbo.Machines
if object_id(N'dbo.Databases', N'U') is not null drop table dbo.Databases
if object_id(N'dbo.Messages', N'U') is not null drop table dbo.Messages
if object_id(N'dbo.BigData', N'U') is not null drop table dbo.BigData
end
go
if object_id(N'dbo.tables_create', N'P') is not null drop procedure dbo.tables_create
go
create procedure dbo.tables_create as begin
set nocount on
-- Level 0.
if object_id(N'dbo.Machines', N'U') is null create table dbo.Machines(
id integer not null identity(1, 1),
[key] varchar(32) not null,
[description] varchar(512),
date_in datetime not null constraint machines_df_date_in default getdate(),
date_out datetime,
constraint machines_pk primary key clustered (id),
constraint machines_uk_key unique ([key]),
constraint machines_ck_key check ([key] like '[a-zA-Z0-9][a-zA-Z0-9_]{0,31}') with (fillfactor = 90)
)
if object_id(N'dbo.Domains', N'U') is null create table dbo.Domains(
id integer not null identity(1, 1),
domain varchar(64) not null,
[description] varchar(512),
date_in datetime not null constraint domains_df_date_in default getdate(),
date_out datetime,
constraint domains_pk primary key clustered (id),
constraint domains_uk_domain unique nonclustered (domain asc) with (fillfactor = 90),
constraint domains_ck_domain check ([domain] like '[a-zA-Z0-9_-.]{1,64}') with (fillfactor = 90)
)
if object_id(N'dbo.Hostnames', N'U') is null create table dbo.Hostnames(
id integer not null identity(1, 1),
[name] varchar(32) not null,
[description] varchar(512),
date_in datetime not null constraint hostnames_df_date_in default getdate(),
date_out datetime,
constraint hostnames_pk primary key clustered (id),
constraint hostnames_uk_name unique nonclustered ([name] asc) with (fillfactor = 90),
constraint hostnames_ck_name check ([name] like '[a-zA-Z0-9_-]{1,32}') with (fillfactor = 90)
)
if object_id(N'dbo.Disks', N'U') is null create table dbo.Disks(
id integer not null identity(1, 1),
[name] varchar(32) not null,
[size] bigint not null,
mountpoint varchar(128) not null,
[description] varchar(512),
date_in datetime not null constraint disks_df_date_in default getdate(),
date_out datetime,
constraint disks_pk primary key clustered (id),
constraint disks_uk_name unique nonclustered ([name] asc, mountpoint asc) with (fillfactor = 90),
constraint disks_ck_name check (
[name] like '[a-zA-Z0-9_-]{1,32}' or
mountpoint like '[A-Z]:'
) with (fillfactor = 90),
constraint disks_ck_size check (size >= 0 and size < power(2, 53)) with (fillfactor = 90),
constraint disks_ck_mountpoint check (
mountpoint like '/%' or
mountpoint like '[a-zA-Z]:\%' or
mountpoint like '\\%'
) with (fillfactor = 90)
)
if object_id(N'dbo.Interfaces', N'U') is null create table dbo.Interfaces(
id integer not null identity(1, 1),
[name] varchar(32) not null,
[description] varchar(512),
date_in datetime not null constraint interfaces_df_date_in default getdate(),
date_out datetime,
constraint interfaces_pk primary key clustered (id),
constraint interfaces_uk_machine_name unique nonclustered (machine asc, [name] asc) with (fillfactor = 90),
constraint interfaces_ck_name check ([name] like '[a-zA-Z0-9_-]{1,32}') with (fillfactor = 90)
)
if object_id(N'dbo.CandlesTimes', N'U') is null create table dbo.CandlesTimes(
id integer not null identity(1, 1),
[from] datetime not null,
[to] datetime not null,
date_in datetime not null constraint candles_times_df_date_in default getdate(),
date_out datetime,
constraint candles_times_pk primary key clustered (id),
constraint candles_times_uk_from_to unique nonclustered ([from] asc, [to] asc) with (fillfactor = 90),
constraint candles_times_ck_from_to check ([from] < [to]) with (fillfactor = 90)
)
if object_id(N'dbo.BigData', N'U') is null create table dbo.BigData(
id integer not null identity(1, 1),
[hash] binary(64) not null,
[value] varchar(max) not null,
date_in datetime not null constraint big_data_df_date_in default getdate(),
date_out datetime,
constraint big_data_pk primary key clustered (id),
constraint big_data_uk_hash unique nonclustered ([hash] asc) with (fillfactor = 90)
)
if object_id(N'dbo.Messages', N'U') is null create table dbo.Messages(
id integer not null identity(1, 1),
[key] varchar(128) not null,
date_in datetime not null constraint messages_df_date_in default getdate(),
date_out datetime,
constraint messages_pk primary key clustered (id),
constraint messages_ck_key check ([key] like '[a-zA-Z_][a-zA-Z0-9_]{0,127}') with (fillfactor = 90)
)
if object_id(N'dbo.Databases', N'U') is null create table dbo.Databases(
id integer not null identity(1, 1),
[name] varchar(64) not null,
date_in datetime not null constraint databases_df_date_in default getdate(),
date_out datetime,
constraint databases_pk primary key clustered (id),
constraint databases_uk_name unique nonclustered ([name] asc) with (fillfactor = 90),
constraint databases_ck_name check ([name] like '[a-zA-Z_][a-zA-Z0-9_]{0,63}') with (fillfactor = 90)
)
-- Level 1.
if object_id(N'dbo.MachineCPU', N'U') is null create table dbo.MachineCPU(
id integer not null identity(1, 1),
machine integer not null,
candle_time integer not null,
[in] float not null,
[out] float not null,
minimum float not null,
maximum float not null,
average float not null,
date_in datetime not null constraint machine_cpu_df_date_in default getdate(),
date_out datetime,
constraint machine_cpu_pk primary key clustered (id),
constraint machine_cpu_fk_machine foreign key (machine) references dbo.Machines(id)
on update no action
on delete no action,
constraint machine_cpu_fk_candle_time foreign key (candle_time) references dbo.CandlesTimes(id)
on update no action
on delete no action,
constraint machine_cpu_ck_cpu_in check (
[in] between 0 and 100 and
[in] between minimum and maximum
) with (fillfactor = 90),
constraint machine_cpu_ck_cpu_out check (
[out] between 0 and 100 and
[out] between minimum and maximum
) with (fillfactor = 90),
constraint machine_cpu_ck_cpu_minimum check (
minimum between 0 and 100 and
minimum <= maximum
) with (fillfactor = 90),
constraint machine_cpu_ck_cpu_maximum check (
maximum between 0 and 100 and
maximum >= minimum
) with (fillfactor = 90),
constraint machine_cpu_ck_cpu_average check (
average between 0 and 100 and
average between minimum and maximum
) with (fillfactor = 90)
)
if object_id(N'dbo.MachineRAM', N'U') is null create table dbo.MachineRAM(
id integer not null identity(1, 1),
machine integer not null,
candle_time integer not null,
total bigint not null,
[in] bigint not null,
[out] bigint not null,
minimum bigint not null,
maximum bigint not null,
average bigint not null,
date_in datetime not null constraint machine_ram_df_date_in default getdate(),
date_out datetime,
constraint machine_ram_pk primary key clustered (id),
constraint machine_ram_fk_machine foreign key (machine) references dbo.Machines(id)
on update no action
on delete no action,
constraint machine_ram_fk_candle_time foreign key (candle_time) references dbo.CandlesTimes(id)
on update no action
on delete no action,
constraint machine_ram_ck_memory_total check (
total between 0 and power(2, 53) - 1
) with (fillfactor = 90),
constraint machine_ram_ck_memory_in check (
[in] between 0 and power(2, 53) - 1 and
[in] between minimum and maximum and
[in] <= total
) with (fillfactor = 90),
constraint machine_ram_ck_memory_out check (
[out] between 0 and power(2, 53) - 1 and
[out] between minimum and maximum and
[out] <= total
) with (fillfactor = 90),
constraint machine_ram_ck_memory_minimum check (
minimum between 0 and power(2, 53) - 1 and
minimum <= total and
minimum <= maximum
) with (fillfactor = 90),
constraint machine_ram_ck_memory_maximum check (
maximum between 0 and power(2, 53) - 1 and
maximum between total and minimum
) with (fillfactor = 90),
constraint machine_ram_ck_memory_average check (
average between 0 and power(2, 53) - 1 and
average between minimum and maximum and
average <= total
) with (fillfactor = 90)
)
if object_id(N'dbo.MachineDisks', N'U') is null create table dbo.MachineDisks(
id integer not null identity(1, 1),
machine integer not null,
[disk] integer not null,
belongs bit not null constraint machine_disks_df_belongs default 1,
mounted bit not null constraint machine_disks_df_mounted default 1,
date_in datetime not null constraint machine_disks_df_date_in default getdate(),
date_out datetime,
constraint machine_disks_pk primary key clustered (id),
constraint machine_disks_fk_machine foreign key (machine) references dbo.Machines(id)
on update no action
on delete no action,
constraint machine_disks_fk_disk foreign key ([disk]) references dbo.Disks(id)
on update no action
on delete no action
)
if object_id(N'dbo.MachineInterfaces', N'U') is null create table dbo.MachineInterfaces(
id integer not null identity(1, 1),
machine integer not null,
[interface] integer not null,
belongs bit not null constraint machine_interfaces_df_belongs default 1,
mounted bit not null constraint machine_interfaces_df_mounted default 1,
date_in datetime not null constraint machine_interfaces_df_date_in default getdate(),
date_out datetime,
constraint machine_interfaces_pk primary key clustered (id),
constraint machine_interfaces_fk_machine foreign key (machine) references dbo.Machines(id)
on update no action
on delete no action,
constraint machine_interfaces_fk_interface foreign key ([interface]) references dbo.Interfaces(id)
on update no action
on delete no action
)
if object_id(N'dbo.Procedures', N'U') is null create table dbo.Procedures(
id integer not null identity(1, 1),
[database] integer not null,
[name] varchar(64) not null,
date_in datetime not null constraint procedures_df_date_in default getdate(),
date_out datetime,
constraint procedures_pk primary key clustered (id),
constraint procedures_fk_database foreign key ([database]) references dbo.Databases(id)
on update no action
on delete no action,
constraint procedures_uk_name unique nonclustered ([database] asc, [name] asc) with (fillfactor = 90),
constraint procedures_ck_name check ([name] like '[a-zA-Z_][a-zA-Z0-9_]{0,63}') with (fillfactor = 90)
)
-- Level 2.
if object_id(N'dbo.MachineDisksSpace', N'U') is null create table dbo.MachineDisksSpace(
id integer not null identity(1, 1),
machine_disk integer not null,
candle_time integer not null,
free bigint not null,
date_in datetime not null constraint machine_disks_space_df_date_in default getdate(),
date_out datetime,
constraint machine_disks_space_pk primary key clustered (id),
constraint machine_disks_space_fk_machine_disk foreign key (machine_disk) references dbo.MachineDisks(id)
on update no action
on delete no action,
constraint machine_disks_space_fk_candle_time foreign key (candle_time) references dbo.CandlesTimes(id)
on update no action
on delete no action,
constraint machine_disks_space_ck_free check (
free between 0 and power(2, 53) - 1 and
free <= isnull((
select top 1 disks.[size]
from dbo.Disks disks
join dbo.MachineDisks machine_disks on machine_disks.[disk] = disks.id
where
disks.date_out is null and
machine_disks.date_out is null and
machine_disks.belongs = 1 and
machine_disks.id = machine_disk
), 0)
) with (fillfactor = 90)
)
if object_id(N'dbo.MachineInterfacesTraffic', N'U') is null create table dbo.MachineInterfacesTraffic(
id integer not null identity(1, 1),
machine_interface integer not null,
candle_time integer not null,
bytes bigint not null,
packages integer not null,
errors integer not null,
date_in datetime not null constraint machine_interfaces_traffic_df_date_in default getdate(),
date_out datetime,
constraint machine_interfaces_traffic_pk primary key clustered (id),
constraint machine_interfaces_traffic_fk_machine_interface foreign key (machine_interface) references dbo.MachineInterfaces(id)
on update no action
on delete no action,
constraint machine_interfaces_traffic_fk_candle_time foreign key (candle_time) references dbo.CandlesTimes(id)
on update no action
on delete no action,
constraint machine_interfaces_traffic_ck_bytes check (
bytes between 0 and power(2, 53) - 1
) with (fillfactor = 90),
constraint machine_interfaces_traffic_ck_packages check (
packages between 0 and power(2, 31) - 1
) with (fillfactor = 90),
constraint machine_interfaces_traffic_ck_errors check (
errors between 0 and power(2, 31) - 1
) with (fillfactor = 90)
)
if object_id(N'dbo.MachineInterfacesData', N'U') is null create table dbo.MachineInterfacesData(
id integer not null identity(1, 1),
machine_interface integer not null,
is_ipv6 bit not null constraint machine_interfaces_data_df_is_ipv6 default 0,
[address] varchar(45) not null,
mask tinyint not null,
date_in datetime not null constraint machine_interfaces_data_df_date_in default getdate(),
date_out datetime,
constraint machine_interfaces_data_pk primary key clustered (id),
constraint machine_interfaces_data_fk_machine_interface foreign key (machine_interface) references dbo.MachineInterfaces(id)
on update no action
on delete no action,
constraint machine_interfaces_data_ck_is_ipv6 check (
(is_ipv6 = 0 and [address] like '[0-9]%.%.%.%') or
(is_ipv6 = 1 and [address] like '%:%')
) with (fillfactor = 90),
constraint machine_interfaces_data_ck_address check (
([address] like '[0-9]%.%.%.%' and mask between 0 and 32) or
([address] like '%:%' and mask between 0 and 128)
) with (fillfactor = 90),
constraint machine_interfaces_data_ck_mask check (
(mask between 0 and (case when is_ipv6 = 1 then 128 else 32 end))
) with (fillfactor = 90)
)
if object_id(N'dbo.Exceptions', N'U') is null create table dbo.Exceptions(
id integer not null identity(1, 1),
[procedure] integer not null,
[message] integer not null,
parameters integer,
exception integer not null,
[status] varchar(16),
code integer,
date_in datetime not null constraint exceptions_df_date_in default getdate(),
date_out datetime,
constraint exceptions_pk primary key clustered (id),
constraint exceptions_fk_procedure foreign key ([procedure]) references dbo.Procedures(id)
on update no action
on delete no action,
constraint exceptions_fk_message foreign key ([message]) references dbo.Messages(id)
on update no action
on delete no action,
constraint exceptions_fk_parameters foreign key (parameters) references dbo.BigData(id)
on update no action
on delete no action,
constraint exceptions_fk_exception foreign key (exception) references dbo.BigData(id)
on update no action
on delete no action
)
-- Level Plains.
if object_id(N'dbo.MachineInterfacesPlain', N'U') is null create table dbo.MachineInterfacesPlain(
id integer not null identity(1, 1),
machine integer not null,
interface integer not null,
machine_interface integer not null,
candle_time integer not null,
bytes bigint not null,
packages integer not null,
errors integer not null,
is_ipv6 bit not null constraint machine_interfaces_data_df_is_ipv6 default 0,
[address] varchar(45) not null,
mask tinyint not null,
belongs bit not null constraint machine_interfaces_plain_df_belongs default 1,
date_in datetime not null constraint machine_interfaces_plain_df_date_in default getdate(),
date_out datetime,
constraint machine_interfaces_plain_pk primary key clustered (id),
constraint machine_interfaces_plain_fk_machine foreign key (machine) references dbo.Machines(id)
on update no action
on delete no action,
constraint machine_interfaces_plain_uk_machine_interface unique nonclustered (machine asc, [interface] asc) with (fillfactor = 90),
constraint machine_interfaces_plain_ck_interface check ([interface] like '[a-zA-Z0-9_-]{1,32}') with (fillfactor = 90)
)
end
go
if object_id(N'dbo.tables_update', N'P') is not null drop procedure dbo.tables_update
go
create procedure dbo.tables_update as begin
set nocount on
end
go
if object_id(N'dbo.tables_fill', N'P') is not null drop procedure dbo.tables_fill
go
create procedure dbo.tables_fill as begin
set nocount on
end
go
execute dbo.tables_drop
go
execute dbo.tables_create
go
execute dbo.tables_update
go
execute dbo.tables_fill
go
if object_id(N'dbo.hash_big_data', N'FN') is not null drop function dbo.hash_big_data
go
create function dbo.hash_big_data (@value varchar(max)) returns binary(64) as begin
return select top 1 convert(binary(64), hashbytes('SHA2_256', convert(nvarchar(max), @value)))
end
go
if object_id(N'dbo.get_procedure', N'P') is not null drop procedure dbo.get_procedure
go
create procedure dbo.get_procedure
@database varchar(64),
@procedure varchar(64),
@id integer output
as begin
declare @database_id integer = (
select top 1 id from dbo.Databases where
date_out is null and
[name] = @database
)
set nocount on
if @database_id is null begin
insert into dbo.Databases([name]) values (@database)
set @database_id = scope_identity()
end
set @id = (
select top 1 id from dbo.Procedures where
date_out is null and
[database] = @database_id and
[name] = @procedure
)
if @id is null begin
insert into dbo.Procedures([database], [name]) values (@database_id, @procedure)
set @id = scope_identity()
end
end
go
if object_id(N'dbo.get_big_data', N'P') is not null drop procedure dbo.get_big_data
go
create procedure dbo.get_big_data
@value varchar(max),
@id integer output
as begin
declare @hash binary(64) = dbo.hash_big_data(@value)
set nocount on
set @id = (
select top 1 id from dbo.BigData where
date_out is null and
[hash] = @hash
)
if @id is null begin
insert into dbo.BigData([hash], [value]) values (@hash, @value)
set @id = scope_identity()
end
end
go
if object_id(N'dbo.get_message', N'P') is not null drop procedure dbo.get_message
go
create procedure dbo.get_message
@message varchar(128),
@id integer output
as begin
set nocount on
set @id = (
select top 1 id from dbo.Messages where
date_out is null and
[key] = @message
)
if @id is null begin
insert into dbo.Messages([key]) values (@message)
set @id = scope_identity()
end
end
go
if object_id(N'dbo.set_exception', N'P') is not null drop procedure dbo.set_exception
go
create procedure dbo.set_exception
@database varchar(64),
@procedure varchar(64),
@message varchar(128),
@parameters varchar(max) = null
as begin
declare @procedure_id integer
declare @message_id integer
declare @exception_message varchar(max) = error_message()
declare @exception_message_id integer
declare @parameters_id integer
set nocount on
execute dbo.get_procedure @database, @procedure, @procedure_id output
execute dbo.get_big_data @exception_message, @exception_message_id output
execute dbo.get_big_data @parameters, @parameters_id output
execute dbo.get_message @message, @message_id output
insert into dbo.Exceptions([procedure], [message], [parameters], exception, [status], code) values
(@procedure_id, @message_id, @parameters_id, @exception_message_id, error_severity(), error_number())
end
go
if object_id(N'dbo.ProceduresView', N'V') is not null drop view dbo.ProceduresView
go
create view dbo.ProceduresView as select
procedures.id,
databases.[name] as [database],
procedures.[name] as [procedure],
procedures.date_in,
procedures.date_out
from dbo.Procedures procedures
join dbo.Databases databases on databases.id = procedures.[database]
where
procedures.date_out is null and
databases.date_out is null
go
if object_id(N'dbo.ExceptionsView', N'V') is not null drop view dbo.ExceptionsView
go
create view dbo.ExceptionsView as select
exceptions.id,
procedures.[database] as [database],
procedures.[procedure] as [procedure],
messages.[key] as [message],
parameters.[value] as [parameters],
exception.[value] as [exception],
exceptions.[status],
exceptions.code,
exceptions.date_in
from dbo.Exceptions exceptions
join dbo.ProceduresView procedures on procedures.id = exceptions.[procedure]
join dbo.Messages messages on messages.id = exceptions.[message]
join dbo.BigData parameters on parameters.id = exceptions.parameters
join dbo.BigData exception on exception.id = exceptions.exception
where
exceptions.date_out is null and
procedures.date_out is null and
messages.date_out is null and
parameters.date_out is null and
exception.date_out is null
go

1
version Normal file
View File

@ -0,0 +1 @@
0.0.1