122 lines
4.1 KiB
Python
122 lines
4.1 KiB
Python
import importlib
|
|
|
|
from app.config import ObservabilityConfig
|
|
|
|
|
|
def _reload_metrics_module():
|
|
metrics_module = importlib.import_module("app.runtime.metrics")
|
|
return importlib.reload(metrics_module)
|
|
|
|
|
|
def _make_observability_config(**overrides) -> ObservabilityConfig:
|
|
payload = {
|
|
"enabled": True,
|
|
"service_name": "g2s-aggregator",
|
|
"otlp_endpoint": "http://collector:4317",
|
|
"otlp_insecure": True,
|
|
}
|
|
payload.update(overrides)
|
|
return ObservabilityConfig(**payload)
|
|
|
|
|
|
def test_configure_metrics_skips_bootstrap_when_disabled(monkeypatch) -> None:
|
|
metrics_module = _reload_metrics_module()
|
|
calls: list[object] = []
|
|
monkeypatch.setattr(
|
|
metrics_module,
|
|
"_build_meter_provider",
|
|
lambda observability: calls.append(observability),
|
|
)
|
|
|
|
metrics_module.configure_metrics(_make_observability_config(enabled=False))
|
|
|
|
assert calls == []
|
|
|
|
|
|
def test_build_meter_provider_uses_otlp_exporter_and_service_name(monkeypatch) -> None:
|
|
metrics_module = _reload_metrics_module()
|
|
created: dict[str, object] = {}
|
|
|
|
class FakeExporter:
|
|
def __init__(self, *, endpoint: str, insecure: bool) -> None:
|
|
created["endpoint"] = endpoint
|
|
created["insecure"] = insecure
|
|
|
|
class FakeReader:
|
|
def __init__(self, exporter: object) -> None:
|
|
created["exporter"] = exporter
|
|
|
|
class FakeMeterProvider:
|
|
def __init__(self, *, resource, metric_readers: list[object]) -> None:
|
|
self.resource = resource
|
|
self.metric_readers = metric_readers
|
|
|
|
monkeypatch.setattr(metrics_module, "OTLPMetricExporter", FakeExporter)
|
|
monkeypatch.setattr(metrics_module, "PeriodicExportingMetricReader", FakeReader)
|
|
monkeypatch.setattr(metrics_module, "MeterProvider", FakeMeterProvider)
|
|
|
|
provider = metrics_module._build_meter_provider(
|
|
_make_observability_config(
|
|
otlp_endpoint="http://metrics-backend:4317",
|
|
otlp_insecure=False,
|
|
)
|
|
)
|
|
|
|
assert created["endpoint"] == "http://metrics-backend:4317"
|
|
assert created["insecure"] is False
|
|
assert provider.resource.attributes["service.name"] == "g2s-aggregator"
|
|
assert len(provider.metric_readers) == 1
|
|
assert created["exporter"] is not None
|
|
|
|
|
|
def test_cache_metrics_create_and_record_expected_instruments(monkeypatch) -> None:
|
|
metrics_module = _reload_metrics_module()
|
|
created: dict[str, object] = {}
|
|
|
|
class FakeInstrument:
|
|
def __init__(self, name: str) -> None:
|
|
self.name = name
|
|
self.records: list[tuple[float, dict[str, str] | None]] = []
|
|
|
|
def add(self, value: float, attributes: dict[str, str]) -> None:
|
|
self.records.append((value, attributes))
|
|
|
|
def record(
|
|
self, value: float, attributes: dict[str, str] | None = None
|
|
) -> None:
|
|
self.records.append((value, attributes))
|
|
|
|
class FakeMeter:
|
|
def create_counter(self, name: str, **kwargs) -> FakeInstrument:
|
|
del kwargs
|
|
instrument = FakeInstrument(name)
|
|
created[name] = instrument
|
|
return instrument
|
|
|
|
def create_histogram(self, name: str, **kwargs) -> FakeInstrument:
|
|
del kwargs
|
|
instrument = FakeInstrument(name)
|
|
created[name] = instrument
|
|
return instrument
|
|
|
|
monkeypatch.setattr(metrics_module.metrics, "get_meter", lambda _name: FakeMeter())
|
|
|
|
cache_metrics = metrics_module.CacheMetrics()
|
|
cache_metrics.record_request(operation="get", outcome="hit")
|
|
cache_metrics.record_error(operation="set", error_type="ConnectionError")
|
|
cache_metrics.record_hit(hit=True)
|
|
cache_metrics.record_hit(hit=False)
|
|
|
|
assert set(created) == {
|
|
"cache_requests_total",
|
|
"cache_errors_total",
|
|
"cache_hit_ratio",
|
|
}
|
|
assert created["cache_requests_total"].records == [
|
|
(1, {"operation": "get", "outcome": "hit"})
|
|
]
|
|
assert created["cache_errors_total"].records == [
|
|
(1, {"operation": "set", "error.type": "ConnectionError"})
|
|
]
|
|
assert created["cache_hit_ratio"].records == [(1.0, None), (0.0, None)]
|