Moved context generation to base agent instead of system_metrics

This commit is contained in:
Niels Geens
2024-11-14 14:51:54 +01:00
parent 325870a81a
commit ede0a642d3
6 changed files with 139 additions and 209 deletions

View File

@@ -1,6 +1,5 @@
import unittest
import time
import xml.etree.ElementTree as ET
import psutil
import multiprocessing
import math
@@ -24,27 +23,23 @@ class SystemMetricsTest(unittest.TestCase):
def validate_timestamp(self, timestamp: str):
"""Validate timestamp format and reasonableness"""
try:
# Check format
self.assertRegex(
timestamp,
r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$'
)
# Check timestamp is recent (within last minute)
time_parts = timestamp[:-1].split('T') # Remove Z
time_str = f"{time_parts[0]} {time_parts[1]}"
timestamp_time = time.strptime(time_str, "%Y-%m-%d %H:%M:%S")
now = time.gmtime()
# Convert to seconds since epoch for comparison
timestamp_secs = time.mktime(timestamp_time)
now_secs = time.mktime(now)
self.assertLess(abs(now_secs - timestamp_secs), 60)
except Exception as e:
self.fail(f"Invalid timestamp format: {timestamp}")
# Check format
self.assertRegex(
timestamp,
r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$'
)
# Check timestamp is recent (within last minute)
time_parts = timestamp[:-1].split('T') # Remove Z
time_str = f"{time_parts[0]} {time_parts[1]}"
timestamp_time = time.strptime(time_str, "%Y-%m-%d %H:%M:%S")
now = time.gmtime()
# Convert to seconds since epoch for comparison
timestamp_secs = time.mktime(timestamp_time)
now_secs = time.mktime(now)
self.assertLess(abs(now_secs - timestamp_secs), 60)
def validate_memory_metrics(self, used: int, total: int):
"""Validate memory metrics are reasonable"""
@@ -61,7 +56,6 @@ class SystemMetricsTest(unittest.TestCase):
memory = psutil.virtual_memory()
self.assertEqual(total, memory.total)
# Used memory should be within 20% of current usage
# (allowing for normal fluctuation)
self.assertLess(abs(used - memory.used) / memory.total, 0.2)
def validate_disk_metrics(self, used: int, total: int):
@@ -94,84 +88,64 @@ class SystemMetricsTest(unittest.TestCase):
f"{name} above valid range: {value}"
)
def test_initial_context(self):
"""Test initial context generation"""
context = self.metrics.generate_context(0.5, 10)
# Verify it's an XML element
self.assertIsInstance(context, ET.Element)
self.assertEqual(context.tag, "context")
def test_initial_metrics(self):
"""Test initial metrics generation"""
metrics = self.metrics.get_metrics()
# Validate timestamp
self.validate_timestamp(context.get("time"))
self.validate_timestamp(metrics["timestamp"])
# Validate memory metrics
self.validate_memory_metrics(
int(context.get("memory_used")),
int(context.get("memory_total"))
metrics["memory_used"],
metrics["memory_total"]
)
# Validate disk metrics
self.validate_disk_metrics(
int(context.get("disk_used")),
int(context.get("disk_total"))
metrics["disk_used"],
metrics["disk_total"]
)
# Validate usage percentages
self.validate_usage_values([
("CPU", int(context.get("cpu"))),
("GPU", int(context.get("gpu"))),
("Context", int(context.get("context_usage")))
("CPU", metrics["cpu"]),
("GPU", metrics["gpu"])
])
# Validate stdin buffer size
self.assertEqual(context.get("stdin"), 10)
def test_multiple_context_generations(self):
"""Test multiple context generations have different timestamps"""
context1 = self.metrics.generate_context(0.5, 10)
def test_multiple_metric_readings(self):
"""Test multiple metric readings have different timestamps"""
metrics1 = self.metrics.get_metrics()
time.sleep(1)
context2 = self.metrics.generate_context(0.5, 10)
metrics2 = self.metrics.get_metrics()
self.assertNotEqual(
context1.get("time"),
context2.get("time")
metrics1["timestamp"],
metrics2["timestamp"]
)
def test_cpu_usage_detection(self):
"""Test CPU usage increases under load"""
# Get initial CPU usage - take average of multiple samples
initial_contexts = [self.metrics.generate_context(0.5) for _ in range(3)]
initial_cpu = min(int(ctx.get("cpu")) for ctx in initial_contexts)
# Generate CPU load in separate process
process = multiprocessing.Process(target=cpu_load_process)
process.start()
try:
# Wait for load to register and take multiple samples
time.sleep(1.0)
load_contexts = [self.metrics.generate_context(0.5) for _ in range(3)]
load_cpu = max(int(ctx.get("cpu")) for ctx in load_contexts)
def test_cpu_usage_detection(self):
"""Test CPU usage increases under load"""
# Get initial CPU usage - take average of multiple samples
initial_metrics = [self.metrics.get_metrics() for _ in range(3)]
initial_cpu = min(m["cpu"] for m in initial_metrics)
# Verify load increases CPU usage
self.assertGreater(load_cpu, initial_cpu,
f"CPU usage should increase under load. Initial: {initial_cpu}, Load: {load_cpu}")
finally:
process.terminate()
process.join()
def test_context_usage_reflection(self):
"""Test context usage parameter is reflected accurately"""
test_values = [0.0, 0.42, 0.8, 1.0]
# Generate CPU load in separate process
process = multiprocessing.Process(target=cpu_load_process)
process.start()
for value in test_values:
context = self.metrics.generate_context(value)
self.assertEqual(
int(context.get("context_usage")),
round(value * 100)
)
try:
# Wait for load to register and take multiple samples
time.sleep(1.0)
load_metrics = [self.metrics.get_metrics() for _ in range(3)]
load_cpu = max(m["cpu"] for m in load_metrics)
# Verify load increases CPU usage
self.assertGreater(load_cpu, initial_cpu)
finally:
process.terminate()
process.join()
def test_cleanup(self):
"""Test monitoring stops properly"""
@@ -180,6 +154,6 @@ def test_cpu_usage_detection(self):
# Monitor thread should finish
self.assertFalse(self.metrics._monitor_thread.is_alive())
# Should still generate valid context after stopping
context = self.metrics.generate_context(0.5)
self.assertIsInstance(context, ET.Element)
# Should still generate valid metrics after stopping
metrics = self.metrics.get_metrics()
self.assertIsInstance(metrics, dict)