Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

src/observability/

OpenTelemetry SDK setup, OTLP exporter wiring, structured-JSON logging with trace correlation, and span helpers built around the OTel GenAI semantic conventions. Wired once from src.api.main.lifespan so the rest of the codebase calls into a configured tracer / logger without orchestrating startup.

Key interfaces

  • tracing.setup_tracing() — creates the global TracerProvider, attaches a BatchSpanProcessor with the OTLP gRPC exporter (or ConsoleSpanExporter when OTEL_EXPORTER=console). Reads OTEL_SERVICE_NAME (default harness-python-react) and OTEL_EXPORTER_OTLP_ENDPOINT (default http://localhost:4317).
  • tracing.instrument_fastapi(app) + tracing.instrument_httpx() — auto-instrumentation hooks. Each FastAPI request and outbound httpx call gets a span with the standard semantic-convention attributes.
  • tracing.get_tracer(name) — retrieve a tracer by module name when manual instrumentation is needed.
  • logging.setup_logging(level=None) — configures stdlib logging to emit single-line JSON via _JSONFormatter. Reads LOG_LEVEL env when no argument is passed. Loops in LoggingInstrumentor so the otelTraceID / otelSpanID fields land on every record.
  • logging._JSONFormatter — the formatter; tested directly in tests/test_observability.py for the trace-correlation contract.
  • spans.agent_span(name, attributes=None) — context manager that opens a span, sets initial attributes from a Mapping, yields the live span for further mutation. Use this rather than calling tracer.start_as_current_span directly so the attribute-shape stays consistent.
  • spans.set_span_attributes(span, **kwargs) — set multiple attributes; None values are silently skipped.
  • spans.GENAI_* / DB_* constants — exported attribute-key constants for the OTel GenAI + database semantic conventions. Use these instead of raw strings so a typo is a NameError, not a silently-different attribute.

Conventions

  • Semconv keys only. The constants at the top of spans.py are the single source of attribute names. Adding a custom agent.foo attribute is a hard no — extend the semconv list (or wait for upstream OTel to bless one).
  • Provider-agnostic exporter. OTEL_EXPORTER_OTLP_ENDPOINT is the standard variable; docker-compose.yml sets it to http://jaeger:4317 in the compose network.
  • Lifespan-only setup. Don't call setup_tracing() from anywhere except src.api.main.lifespan — duplicate calls trigger OTel's "Overriding of current TracerProvider" warning, and tests rely on the test-fixture variant that attaches an in-memory exporter to whatever provider exists.