Compare commits

..

5 Commits

Author SHA1 Message Date
be3f8635b8 Merge pull request 'dev to main' (#8) from dev into main
Reviewed-on: #8
2026-01-20 13:12:41 +02:00
Anry Das
dce5a0ab85 Updated README.md 2026-01-20 13:11:26 +02:00
Anry Das
9727d660d1 Added REST API Binary Value metric 2026-01-20 13:07:00 +02:00
d828afdb53 Merge pull request 'Collect time procedure improved' (#7) from dev into main
Reviewed-on: #7
2025-05-31 08:35:31 +03:00
Anry Das
11d497b4e3 Collect time procedure improved 2025-05-31 08:31:41 +03:00
5 changed files with 113 additions and 15 deletions

View File

@@ -181,6 +181,10 @@ From version 2.0 the Application supports internal metrics to collect time. See
- `result_path` - path to result value in response JSON separated by `app_config.RESPONSE_PATH_SEPARATOR` character. Could be configured in [Application config](#AppConfig). - `result_path` - path to result value in response JSON separated by `app_config.RESPONSE_PATH_SEPARATOR` character. Could be configured in [Application config](#AppConfig).
- `timeout` - timeout to wait for response - `timeout` - timeout to wait for response
#### REST value Binary Metrics
**_Gets the responses value from http request to REST service_**
THe same as [REST value Metrics] but works with 'ON/OFF' and 'TRUE/FALSE' values
#### Shell value Metrics #### Shell value Metrics
**_Gets the shell command executed result value_** **_Gets the shell command executed result value_**
```json ```json

View File

@@ -1,6 +1,6 @@
import os import os
APP_VERSION="2.2" APP_VERSION="2.4"
SCRIPT_PATH = os.path.dirname(__file__) SCRIPT_PATH = os.path.dirname(__file__)
CONFIGS_DIR = SCRIPT_PATH + "/configs" CONFIGS_DIR = SCRIPT_PATH + "/configs"
CONFIG_FILE_NAME = CONFIGS_DIR + "/config.json" CONFIG_FILE_NAME = CONFIGS_DIR + "/config.json"

View File

@@ -49,6 +49,7 @@ def init_metric_entities(data):
M.IcmpMetric(data), M.IcmpMetric(data),
M.InterfaceMetric(data), M.InterfaceMetric(data),
M.RestValueMetric(data), M.RestValueMetric(data),
M.RestValueBMetric(data),
M.ShellValueMetric(data), M.ShellValueMetric(data),
M.UptimeMetric(app_config.UPTIME_UPDATE_SECONDS), M.UptimeMetric(app_config.UPTIME_UPDATE_SECONDS),
M.SystemMetric(app_config.SYSTEM_UPDATE_SECONDS) M.SystemMetric(app_config.SYSTEM_UPDATE_SECONDS)

View File

@@ -122,13 +122,16 @@ class HealthData(AbstractData):
self.e_state.labels(name=name, url=url, method=method, server=self.instance_prefix) self.e_state.labels(name=name, url=url, method=method, server=self.instance_prefix)
self.set_data(is_up) self.set_data(is_up)
def set_data(self, is_up): def set_data(self, is_up, working_time = None):
time_ms = get_time_millis() time_ms = get_time_millis()
self.is_up = is_up self.is_up = is_up
self.e_state.labels(name=self.name, url=self.url, method=self.method, server=self.instance_prefix).state(ENUM_UP_DN_STATES[0] if is_up else ENUM_UP_DN_STATES[1]) self.e_state.labels(name=self.name, url=self.url, method=self.method, server=self.instance_prefix).state(ENUM_UP_DN_STATES[0] if is_up else ENUM_UP_DN_STATES[1])
self.set_collect_time(get_time_millis() - time_ms)
self.set_update_time() self.set_update_time()
self.print_trigger_info() self.print_trigger_info()
if working_time:
self.set_collect_time(working_time)
else:
self.set_collect_time(get_time_millis() - time_ms)
class RestValueData(AbstractData): class RestValueData(AbstractData):
@@ -153,7 +156,7 @@ class RestValueData(AbstractData):
self.g_value.labels(name=name, url=url, method=method, server=self.instance_prefix) self.g_value.labels(name=name, url=url, method=method, server=self.instance_prefix)
self.set_data(value) self.set_data(value)
def set_data(self, value): def set_data(self, value, working_time = None):
time_ms = get_time_millis() time_ms = get_time_millis()
self.value = value self.value = value
try: try:
@@ -161,9 +164,50 @@ class RestValueData(AbstractData):
except: except:
self.g_value.labels(name=self.name, url=self.url, method=self.method, server=self.instance_prefix).set(0) self.g_value.labels(name=self.name, url=self.url, method=self.method, server=self.instance_prefix).set(0)
self.set_collect_time(get_time_millis() - time_ms)
self.set_update_time() self.set_update_time()
self.print_trigger_info() self.print_trigger_info()
if working_time:
self.set_collect_time(working_time)
else:
self.set_collect_time(get_time_millis() - time_ms)
class RestValueBData(AbstractData):
g_value: Gauge
def __init__(self, name, url, interval, timeout, value=None, method='GET', user=None, password=None, headers=None, prefix='',
result_type='single', result_path=''):
super().__init__(name, interval, prefix)
if headers is None:
headers = {}
self.url = url
self.timeout = timeout
self.method = method.upper()
self.user = user
self.password = password
self.headers = headers
self.value = value
self.type = result_type
self.path = result_path
self.g_value = get_gauge_metric('das_rest_value_b',
'Remote REST API [name, url, method, server] Binary Value',
['name', 'url', 'method', 'server'])
self.g_value.labels(name=name, url=url, method=method, server=self.instance_prefix)
self.set_data(value)
def set_data(self, value, working_time = None):
time_ms = get_time_millis()
self.value = value
try:
self.g_value.labels(name=self.name, url=self.url, method=self.method, server=self.instance_prefix).set(1 if str(value).upper() in ['ON', 'TRUE'] else 0)
except:
self.g_value.labels(name=self.name, url=self.url, method=self.method, server=self.instance_prefix).set(-1)
self.set_update_time()
self.print_trigger_info()
if working_time:
self.set_collect_time(working_time)
else:
self.set_collect_time(get_time_millis() - time_ms)
class ShellValueData(AbstractData): class ShellValueData(AbstractData):
@@ -181,7 +225,7 @@ class ShellValueData(AbstractData):
self.g_value.labels(name=name, command=command, server=self.instance_prefix) self.g_value.labels(name=name, command=command, server=self.instance_prefix)
self.set_data(value) self.set_data(value)
def set_data(self, value): def set_data(self, value, working_time = None):
time_ms = get_time_millis() time_ms = get_time_millis()
self.value = value self.value = value
try: try:
@@ -189,9 +233,12 @@ class ShellValueData(AbstractData):
except: except:
self.g_value.labels(name=self.name, command=self.command, server=self.instance_prefix).set(0) self.g_value.labels(name=self.name, command=self.command, server=self.instance_prefix).set(0)
self.set_collect_time(get_time_millis() - time_ms)
self.set_update_time() self.set_update_time()
self.print_trigger_info() self.print_trigger_info()
if working_time:
self.set_collect_time(working_time)
else:
self.set_collect_time(get_time_millis() - time_ms)
class IcmpData(AbstractData): class IcmpData(AbstractData):
@@ -207,13 +254,16 @@ class IcmpData(AbstractData):
self.e_state.labels(name=name, ip=ip, server=self.instance_prefix) self.e_state.labels(name=name, ip=ip, server=self.instance_prefix)
self.set_data(is_up) self.set_data(is_up)
def set_data(self, is_up): def set_data(self, is_up, working_time = None):
time_ms = get_time_millis() time_ms = get_time_millis()
self.is_up = is_up self.is_up = is_up
self.e_state.labels(name=self.name, ip=self.ip, server=self.instance_prefix).state(ENUM_UP_DN_STATES[0] if is_up else ENUM_UP_DN_STATES[1]) self.e_state.labels(name=self.name, ip=self.ip, server=self.instance_prefix).state(ENUM_UP_DN_STATES[0] if is_up else ENUM_UP_DN_STATES[1])
self.set_collect_time(get_time_millis() - time_ms)
self.set_update_time() self.set_update_time()
self.print_trigger_info() self.print_trigger_info()
if working_time:
self.set_collect_time(working_time)
else:
self.set_collect_time(get_time_millis() - time_ms)
class InterfaceData(AbstractData): class InterfaceData(AbstractData):

View File

@@ -12,7 +12,7 @@ import app_config
from threading import Thread from threading import Thread
from metrics.DataStructures import DiskData, HealthData, IcmpData, ENUM_UP_DN_STATES, InterfaceData, UptimeData, \ from metrics.DataStructures import DiskData, HealthData, IcmpData, ENUM_UP_DN_STATES, InterfaceData, UptimeData, \
SystemData, RestValueData, ShellValueData SystemData, RestValueData, ShellValueData, RestValueBData
class AbstractMetric: class AbstractMetric:
@@ -36,6 +36,7 @@ class AbstractMetric:
def is_health_check(url, timeout, method, user, pwd, headers, callback=None): def is_health_check(url, timeout, method, user, pwd, headers, callback=None):
time_ms = get_time_millis()
session = requests.Session() session = requests.Session()
if user and pwd: if user and pwd:
session.auth = (user, pwd) session.auth = (user, pwd)
@@ -48,13 +49,15 @@ def is_health_check(url, timeout, method, user, pwd, headers, callback=None):
) )
result = response.status_code == 200 result = response.status_code == 200
if callback is not None: if callback is not None:
callback(result) working_time = get_time_millis() - time_ms
callback(result, working_time)
else: else:
return result return result
except (requests.ConnectTimeout, requests.exceptions.ConnectionError) as e: except (requests.ConnectTimeout, requests.exceptions.ConnectionError) as e:
return False return False
def get_rest_value(url, timeout, method, user, pwd, headers, callback=None, result_type='single', path=''): def get_rest_value(url, timeout, method, user, pwd, headers, callback=None, result_type='single', path=''):
time_ms = get_time_millis()
session = requests.Session() session = requests.Session()
if user and pwd: if user and pwd:
session.auth = (user, pwd) session.auth = (user, pwd)
@@ -67,10 +70,11 @@ def get_rest_value(url, timeout, method, user, pwd, headers, callback=None, resu
) )
resp = json.loads(response.content.decode().replace("'", '"')) resp = json.loads(response.content.decode().replace("'", '"'))
result = parse_response(resp, path) result = parse_response(resp, path)
if not result.isalnum(): if not str(result).isalnum():
result = 0 result = 0
if callback is not None: if callback is not None:
callback(result) working_time = get_time_millis() - time_ms
callback(result, working_time)
else: else:
return result return result
except (requests.ConnectTimeout, requests.exceptions.ConnectionError) as e: except (requests.ConnectTimeout, requests.exceptions.ConnectionError) as e:
@@ -98,6 +102,7 @@ def parse_response(resp, path):
return '' return ''
def get_shell_value(command, args, callback=None): def get_shell_value(command, args, callback=None):
time_ms = get_time_millis()
cmd = [command, ' '.join(str(s) for s in args)] cmd = [command, ' '.join(str(s) for s in args)]
try: try:
output = subprocess.check_output(cmd) output = subprocess.check_output(cmd)
@@ -109,11 +114,13 @@ def get_shell_value(command, args, callback=None):
result = 0 result = 0
if callback is not None: if callback is not None:
callback(result) working_time = get_time_millis() - time_ms
callback(result, working_time)
else: else:
return result return result
def is_ping(ip, count, callback=None): def is_ping(ip, count, callback=None):
time_ms = get_time_millis()
param = '-n' if platform.system().lower() == 'windows' else '-c' param = '-n' if platform.system().lower() == 'windows' else '-c'
command = ['ping', param, str(count), ip] command = ['ping', param, str(count), ip]
try: try:
@@ -123,8 +130,10 @@ def is_ping(ip, count, callback=None):
'time out'.upper() not in str(output).upper()) 'time out'.upper() not in str(output).upper())
except: except:
result = False result = False
if callback is not None: if callback is not None:
callback(result) working_time = get_time_millis() - time_ms
callback(result, working_time)
else: else:
return result return result
@@ -134,6 +143,8 @@ def get_net_iface_stat(name):
def get_next_update_time(d): def get_next_update_time(d):
return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(d.updated_at + d.interval)) return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(d.updated_at + d.interval))
def get_time_millis():
return round(time.time() * 1000)
class DiskMetric(AbstractMetric): class DiskMetric(AbstractMetric):
def __init__(self, config): def __init__(self, config):
@@ -254,6 +265,38 @@ class RestValueMetric(AbstractMetric):
print(f'[DEBUG] (next update at {get_next_update_time(d)}) on {d.url}: by {d.method} in {d.path} got value="{d.value}"') print(f'[DEBUG] (next update at {get_next_update_time(d)}) on {d.url}: by {d.method} in {d.path} got value="{d.value}"')
class RestValueBMetric(AbstractMetric):
def __init__(self, config):
super().__init__('rest_value_b', config)
for d in self.config:
name, url, interval, timeout, method = d['name'], d['url'], d['interval'], d['timeout'], d['method']
if 'auth' in self.config:
user = d['auth']['user']
pwd = d['auth']['pass']
else:
user = ''
pwd = ''
if 'headers' in self.config:
headers = d['headers']
else:
headers = ''
result_type, result_path = d['result_type'], d['result_path']
result = get_rest_value(url=url, timeout=timeout, method=method, user=user, pwd=pwd, headers=headers,
result_type=result_type, path=result_path)
self.data_array.append(RestValueBData(name, url, interval, timeout, result, method, user, pwd, headers, self.prefix, result_type, result_path))
def proceed_metric(self):
for d in self.data_array:
if d.is_need_to_update():
thread = Thread(target=get_rest_value, args=(d.url, d.timeout, d.method, d.user, d.password, d.headers,
d.set_data, d.type, d.path))
thread.start()
def print_debug_info(self):
for d in self.data_array:
print(f'[DEBUG] (next update at {get_next_update_time(d)}) on {d.url}: by {d.method} in {d.path} got value="{d.value}"')
class ShellValueMetric(AbstractMetric): class ShellValueMetric(AbstractMetric):
def __init__(self, config): def __init__(self, config):
super().__init__('shell_value', config) super().__init__('shell_value', config)