Initial curated RAGcore source from c16667f0c9397e2bfc8dd0255b114fba23c8d05e
This commit is contained in:
commit
7ca726caf2
659 files changed
+98171
No files matched your search
@@ -0,0 +1,73 @@
|
||||
"""TelemetryMiddleware: a real HTTP trace and request metric per request."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from opentelemetry.sdk.metrics import MeterProvider
|
||||
from opentelemetry.sdk.metrics.export import InMemoryMetricReader
|
||||
from opentelemetry.sdk.resources import Resource
|
||||
from opentelemetry.sdk.trace import TracerProvider
|
||||
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
|
||||
from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter
|
||||
|
||||
from ragcore.api.middleware import TelemetryMiddleware
|
||||
from ragcore.platform.logging import RequestCorrelationMiddleware
|
||||
from ragcore.platform.telemetry import TelemetryMetrics
|
||||
|
||||
|
||||
def _app() -> tuple[FastAPI, InMemorySpanExporter, InMemoryMetricReader]:
|
||||
span_exporter = InMemorySpanExporter()
|
||||
tracer_provider = TracerProvider(resource=Resource.create({"service.name": "test"}))
|
||||
tracer_provider.add_span_processor(SimpleSpanProcessor(span_exporter))
|
||||
|
||||
metric_reader = InMemoryMetricReader()
|
||||
meter_provider = MeterProvider(
|
||||
resource=Resource.create({"service.name": "test"}), metric_readers=[metric_reader]
|
||||
)
|
||||
metrics = TelemetryMetrics(meter_provider=meter_provider)
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@app.get("/ping")
|
||||
async def ping() -> dict[str, str]:
|
||||
return {"status": "ok"}
|
||||
|
||||
# Mirrors the real app's middleware order: TelemetryMiddleware must run
|
||||
# after RequestCorrelationMiddleware to read the request_id it attaches.
|
||||
app.add_middleware(TelemetryMiddleware, metrics=metrics, tracer_provider=tracer_provider)
|
||||
app.add_middleware(RequestCorrelationMiddleware)
|
||||
return app, span_exporter, metric_reader
|
||||
|
||||
|
||||
def _metric_names(reader: InMemoryMetricReader) -> set[str]:
|
||||
data = reader.get_metrics_data()
|
||||
if data is None:
|
||||
return set()
|
||||
return {
|
||||
metric.name
|
||||
for resource_metric in data.resource_metrics
|
||||
for scope_metric in resource_metric.scope_metrics
|
||||
for metric in scope_metric.metrics
|
||||
}
|
||||
|
||||
|
||||
def test_a_request_produces_one_correlated_http_trace_span() -> None:
|
||||
app, span_exporter, _ = _app()
|
||||
with TestClient(app) as client:
|
||||
response = client.get("/ping", headers={"X-Request-ID": "req-telemetry-1"})
|
||||
|
||||
assert response.status_code == 200
|
||||
spans = span_exporter.get_finished_spans()
|
||||
assert len(spans) == 1
|
||||
assert spans[0].name == "http_request"
|
||||
assert spans[0].attributes["correlation_id"] == "req-telemetry-1"
|
||||
assert spans[0].attributes["http.path"] == "/ping"
|
||||
|
||||
|
||||
def test_a_request_produces_the_http_request_duration_metric() -> None:
|
||||
app, _, metric_reader = _app()
|
||||
with TestClient(app) as client:
|
||||
client.get("/ping")
|
||||
|
||||
assert "ragcore_request_duration_seconds" in _metric_names(metric_reader)
|
||||
Reference in new issue
Block a user