Skip to content

Commit

Permalink
add metrics ft case
Browse files Browse the repository at this point in the history
  • Loading branch information
hxy7yx committed Nov 17, 2023
1 parent a2d794d commit 8607d59
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 28 deletions.
19 changes: 13 additions & 6 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,17 @@ jobs:
container: ghcr.io/neugates/build:x86_64-main
strategy:
matrix:
plugin: [core, modbus]
plugin: [core, modbus, metrics]

steps:
- uses: actions/checkout@v4
with:
submodules: recursive


- name: setup dependencies
run: |
pip install -U pytest requests prometheus-client
- name: compile
run: |
git config --global --add safe.directory $(pwd)
Expand All @@ -143,10 +147,13 @@ jobs:
- name: function test
run: |
pip install -U pytest
pip install requests
pip install prometheus-client
pytest -s -v tests/ft
if [ "${{ matrix.plugin }}" = "core" ]; then
pytest -s -v tests/ft --ignore=tests/ft/test_modbus.py --ignore=tests/ft/test_metrics.py
elif [ "${{ matrix.plugin }}" = "modbus" ]; then
pytest -s -v tests/ft/driver/"test_modbus.py"
else
pytest -s -v tests/ft/metrics/"test_metrics.py"
fi
- name: create cov report
run: |
Expand Down
2 changes: 1 addition & 1 deletion create_cov_report.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ case $1 in
lcov -c -d build/plugins/modbus/CMakeFiles/plugin-modbus-tcp.dir -o cov_report/cov-modbus-tcp.info
cd cov_report
lcov -a cov-modbus-rtu.info -a cov-modbus-tcp.info -o cov-modbus.info;;
(core)
(core|metrics)
lcov -c -d build/CMakeFiles/neuron-base.dir/src -o cov_report/cov-neuron-base.info
lcov -c -d build/CMakeFiles/neuron.dir/src -o cov_report/cov-neuron.info
lcov -c -d build/CMakeFiles/neuron.dir/plugins/restful -o cov_report/cov-restful.info
Expand Down
140 changes: 119 additions & 21 deletions tests/ft/metrics/test_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,126 @@
from neuron.error import *
from prometheus_client.parser import text_string_to_metric_families

def assert_metrics(resp_content, expected_metrics):
metrics_found = {metric: False for metric in expected_metrics}

for family in text_string_to_metric_families(resp_content):
for sample in family.samples:
metric_name = sample.name
expected_value, extra_labels = expected_metrics.get(metric_name, (None, {}))
if all(sample.labels.get(k) == v for k, v in extra_labels.items()):
assert sample.value == expected_value, f"Metric {metric_name} expected {expected_value} but got {sample.value}"
metrics_found[metric_name] = True

missing_metrics = [name for name, found in metrics_found.items() if not found]
assert not missing_metrics, f"Missing metrics: {', '.join(missing_metrics)}"

def assert_global_metrics(resp_content, expected_metrics):
found_metrics = set()
labels_found = {metric: set() for metric in expected_metrics if expected_metrics[metric]}

for family in text_string_to_metric_families(resp_content):
for sample in family.samples:
metric_name = sample.name
found_metrics.add(metric_name)
if expected_metrics.get(metric_name):
labels_found[metric_name].update(sample.labels.keys())

missing_metrics = set(expected_metrics.keys()) - found_metrics
print(f"Missing metrics: {missing_metrics}")
assert not missing_metrics, f"Missing metrics: {', '.join(missing_metrics)}"

if 'os_info' in expected_metrics and expected_metrics['os_info']:
missing_labels = set(expected_metrics['os_info']) - labels_found['os_info']
print(f"Missing labels for os_info: {missing_labels}")
assert not missing_labels, f"Missing labels for os_info: {', '.join(missing_labels)}"

for metric, expected_labels in expected_metrics.items():
if expected_labels and metric != 'os_info':
print(f"Incorrect labels for {metric}: {labels_found[metric]} vs {expected_labels}")
assert labels_found[metric] == set(expected_labels), f"Incorrect labels for {metric}: {labels_found[metric]} vs {expected_labels}"

class TestMetrics:
@description(given="neuron start", when="get global metrics", then="success")
def test_get_global_metrics(self):
@description(given="neuron is started",
when="get global metrics and the metrics conform to the Prometheus specification",
then="success")
def test_global_prometheus_specification(self):
resp = api.get_metrics(category="global")
assert 200 == resp.status_code
flag_version = False
flag_kernel = False
flag_machine = False
flag_clib = False
for family in text_string_to_metric_families(resp.content.decode('utf-8')):
for sample in family.samples:
if sample.name == "os_info" and "version" in sample.labels:
flag_version = True
if sample.name == "os_info" and "kernel" in sample.labels:
flag_kernel = True
if sample.name == "os_info" and "machine" in sample.labels:
flag_machine = True
if sample.name == "os_info" and "clib" in sample.labels:
flag_clib = True

assert flag_version
assert flag_kernel
assert flag_machine
assert flag_clib

expected_metrics = {
"os_info": ["version", "kernel", "machine", "clib"],
"cpu_percent": [],
"cpu_cores_total": [],
"mem_total_bytes_total": [],
"mem_used_bytes": [],
"mem_cache_bytes": [],
"rss_bytes": [],
"disk_size_gibibytes_total": [],
"disk_used_gibibytes": [],
"disk_avail_gibibytes": [],
"core_dumped": [],
"uptime_seconds_total": [],
"north_nodes_total": [],
"north_running_nodes_total": [],
"north_disconnected_nodes_total": [],
"south_nodes_total": [],
"south_running_nodes_total": [],
"south_disconnected_nodes_total": []
}

assert_global_metrics(resp.content.decode('utf-8'), expected_metrics)

@description(given="neuron is started",
when="a MQTT node is created and the metrics conform to the Prometheus specification",
then="success")
def test_app_prometheus_specification(self):
response = api.add_node(node='mqtt', plugin=PLUGIN_MQTT)
assert 200 == response.status_code

resp = api.get_metrics(category="app", node='mqtt')
assert 200 == resp.status_code

expected_metrics = {
"node_type": (2, {}),
"link_state": (0, {}),
"running_state": (1, {}),
"send_msgs_total": (0, {}),
"send_msg_errors_total": (0, {}),
"recv_msgs_total": (0, {}),
"cached_msgs": (0, {}),
}

assert_metrics(resp.content.decode('utf-8'), expected_metrics)

@description(given="neuron is started",
when="a Modbus node is created and the metrics conform to the Prometheus specification",
then="success")
def test_driver_prometheus_specification(self):
response = api.add_node(node='modbus', plugin=PLUGIN_MODBUS_TCP)
assert 200 == response.status_code

response = api.add_group(node='modbus', group='group')
assert 200 == response.status_code

resp = api.get_metrics(category="driver", node='modbus')
assert 200 == resp.status_code

expected_metrics = {
"node_type": (1, {}),
"link_state": (0, {}),
"running_state": (1, {}),
"last_rtt_ms": (9999, {}),
"send_bytes": (0, {}),
"recv_bytes": (0, {}),
"tag_reads_total": (0, {}),
"tag_read_errors_total": (0, {}),
"tags_total": (0, {}),
"group_tags_total": (0, {"group": "group", "node": "modbus"}),
"group_last_error_code": (0, {"group": "group", "node": "modbus"}),
"group_last_error_timestamp_ms": (0, {"group": "group", "node": "modbus"}),
"group_last_send_msgs": (0, {"group": "group", "node": "modbus"}),
"group_last_timer_ms": (0, {"group": "group", "node": "modbus"})
}

assert_metrics(resp.content.decode('utf-8'), expected_metrics)

0 comments on commit 8607d59

Please sign in to comment.