Skip to content

Commit 1e97bf4

Browse files
Sudan Landgewearyzen
authored andcommitted
feat(metrics)(net): add ci test to validate net metrics
Make sure there is no breaking change for NetDeviceMetrics. Add random number of net devices and validate that values of "net" are aggregate of all "net_{iface_id}". Note: this is part 11 of 12 commits to add per net device metrics. Signed-off-by: Sudan Landge <[email protected]>
1 parent 1c74e43 commit 1e97bf4

File tree

1 file changed

+135
-10
lines changed

1 file changed

+135
-10
lines changed

tests/integration_tests/functional/test_metrics.py

Lines changed: 135 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,15 @@
77
import platform
88

99

10-
def test_flush_metrics(test_microvm_with_api):
10+
def _validate_metrics(metrics):
1111
"""
12-
Check the `FlushMetrics` vmm action.
12+
This functions makes sure that all components
13+
of FirecrackerMetrics struct are present.
14+
In depth validation of metrics for each component
15+
should be implemented in its own test.
16+
e.g. validation of NetDeviceMetrics should implement
17+
_validate_net_metrics() to check for breaking change etc.
1318
"""
14-
microvm = test_microvm_with_api
15-
microvm.spawn()
16-
microvm.basic_config()
17-
microvm.start()
18-
19-
metrics = microvm.flush_metrics()
20-
2119
exp_keys = [
2220
"utc_timestamp_ms",
2321
"api_server",
@@ -44,7 +42,7 @@ def test_flush_metrics(test_microvm_with_api):
4442
if platform.machine() == "aarch64":
4543
exp_keys.append("rtc")
4644

47-
assert set(metrics.keys()) == set(exp_keys)
45+
assert set(exp_keys).issubset(metrics.keys())
4846

4947
utc_time = datetime.datetime.now(datetime.timezone.utc)
5048
utc_timestamp_ms = math.floor(utc_time.timestamp() * 1000)
@@ -54,3 +52,130 @@ def test_flush_metrics(test_microvm_with_api):
5452
# Epoch.Regression test for:
5553
# https://github.com/firecracker-microvm/firecracker/issues/2639
5654
assert abs(utc_timestamp_ms - metrics["utc_timestamp_ms"]) < 1000
55+
56+
57+
class FcDeviceMetrics:
58+
"""
59+
Provides functions to validate breaking change and
60+
aggregation of metrics
61+
"""
62+
63+
def __init__(self, name, validate_fn, num_dev):
64+
self.dev_name = name
65+
self.validate_dev_metrics = validate_fn
66+
self.num_dev = num_dev
67+
68+
def validate(self, microvm):
69+
"""
70+
validate breaking change of device metrics
71+
"""
72+
fc_metrics = microvm.flush_metrics()
73+
74+
# make sure all items of FirecrackerMetrics are as expected
75+
_validate_metrics(fc_metrics)
76+
77+
# check for breaking change in device specific metrics
78+
self.validate_dev_metrics(fc_metrics[self.dev_name])
79+
80+
# make sure "{self.name}" is aggregate of "{self.name}_*"
81+
# and that there are only {num_dev} entries of "{self.name}_*"
82+
self.validate_aggregation(fc_metrics)
83+
print(f"\nsuccessfully validated aggregate of {self.dev_name} metrics")
84+
85+
def validate_aggregation(self, fc_metrics):
86+
"""
87+
validate aggregation of device metrics
88+
"""
89+
metrics_aggregate = fc_metrics[self.dev_name]
90+
metrics_calculated = {}
91+
actual_num_devices = 0
92+
print(f"In aggregation of {self.dev_name} expected {self.num_dev=}")
93+
for component_metric_names, component_metric_values in fc_metrics.items():
94+
if f"{self.dev_name}_" in component_metric_names:
95+
print(f"found {component_metric_names} during aggr of {self.dev_name}")
96+
actual_num_devices += 1
97+
for metrics_name, metric_value in component_metric_values.items():
98+
if metrics_name not in metrics_calculated:
99+
metrics_calculated[metrics_name] = 0
100+
metrics_calculated[metrics_name] += metric_value
101+
assert metrics_aggregate == metrics_calculated
102+
assert self.num_dev == actual_num_devices
103+
104+
105+
def test_flush_metrics(test_microvm_with_api):
106+
"""
107+
Check the `FlushMetrics` vmm action.
108+
"""
109+
microvm = test_microvm_with_api
110+
microvm.spawn()
111+
microvm.basic_config()
112+
microvm.start()
113+
114+
metrics = microvm.flush_metrics()
115+
_validate_metrics(metrics)
116+
117+
118+
def _validate_net_metrics(net_metrics):
119+
exp_keys = [
120+
"activate_fails",
121+
"cfg_fails",
122+
"mac_address_updates",
123+
"no_rx_avail_buffer",
124+
"no_tx_avail_buffer",
125+
"event_fails",
126+
"rx_queue_event_count",
127+
"rx_event_rate_limiter_count",
128+
"rx_partial_writes",
129+
"rx_rate_limiter_throttled",
130+
"rx_tap_event_count",
131+
"rx_bytes_count",
132+
"rx_packets_count",
133+
"rx_fails",
134+
"rx_count",
135+
"tap_read_fails",
136+
"tap_write_fails",
137+
"tx_bytes_count",
138+
"tx_malformed_frames",
139+
"tx_fails",
140+
"tx_count",
141+
"tx_packets_count",
142+
"tx_partial_reads",
143+
"tx_queue_event_count",
144+
"tx_rate_limiter_event_count",
145+
"tx_rate_limiter_throttled",
146+
"tx_spoofed_mac_count",
147+
]
148+
assert set(net_metrics.keys()) == set(exp_keys)
149+
150+
151+
def test_net_metrics(test_microvm_with_api):
152+
"""
153+
Validate that NetDeviceMetrics doesn't have a breaking change
154+
and "net" is aggregate of all "net_*" in the json object.
155+
"""
156+
test_microvm = test_microvm_with_api
157+
test_microvm.spawn()
158+
159+
# Set up a basic microVM.
160+
test_microvm.basic_config()
161+
162+
# randomly selected 10 as the number of net devices to test
163+
num_net_devices = 10
164+
165+
net_metrics = FcDeviceMetrics("net", _validate_net_metrics, num_net_devices)
166+
167+
# create more than 1 net devices to test aggregation
168+
for _ in range(num_net_devices):
169+
test_microvm.add_net_iface()
170+
test_microvm.start()
171+
172+
# check that the started microvm has "net" and "NUM_NET_DEVICES" number of "net_" metrics
173+
net_metrics.validate(test_microvm)
174+
175+
for i in range(num_net_devices):
176+
# Test that network devices attached are operational.
177+
# Verify if guest can run commands.
178+
exit_code, _, _ = test_microvm.ssh_iface(i).run("sync")
179+
# test that we get metrics while interacting with different interfaces
180+
net_metrics.validate(test_microvm)
181+
assert exit_code == 0

0 commit comments

Comments
 (0)