lacing.otel#
Optional OpenTelemetry instrumentation for the lacing server.
OTel is the “cherry on top” of the op-log architecture (BACK-DOC §4.7). The op-log captures what happened; OTel publishes spans so downstream distributed-tracing infra (Jaeger, Tempo, Honeycomb, …) can correlate those mutations with calls from upstream services.
Design rules:
Optional.
opentelemetry-*packages are heavy. This module imports cleanly without them — every helper falls back to a no-op when OTel isn’t installed.Auto-detect. If
opentelemetry.apiis importable AND aTracerProviderhas been configured (via the standard env varsOTEL_EXPORTER_*or programmatic setup), spans are emitted. Otherwise everything is a no-op and there’s no perf cost.No globals. Callers pass tracers around explicitly.
Usage:
from lacing.otel import get_tracer, traced
tracer = get_tracer("lacing.server")
@traced(tracer, "my_operation", record_args=True)
def my_op(x, y):
return x + y
In Phase 2.0+, the FastAPI middleware (lacing.server.otel_middleware,
opt-in) wraps every request in a span and tags it with the Lamport clock
returned by the op-log. The ASGI middleware is added to the app via
instrument_app() only when explicitly called — we don’t auto-mount
it because that would change behavior depending on whether opentelemetry
happened to be installed.
Functions
|
Return a tracer or a no-op fallback. |
|
Add OpenTelemetry instrumentation to a FastAPI app. |
Quick check: is OTel installed AND a TracerProvider configured? |
|
|
Open a span on |
|
Decorator: wrap a function in a span on |
- lacing.otel.get_tracer(name='lacing', version=None)[source]#
Return a tracer or a no-op fallback.
- Parameters:
- Return type:
- Returns:
opentelemetry.trace.Tracerif OTel is installed, else a no-op object whosestart_as_current_span()is a context manager yielding a no-op span.
- lacing.otel.instrument_app(app, *, tracer_name='lacing.server')[source]#
Add OpenTelemetry instrumentation to a FastAPI app.
Wraps every request in a span; tags the span with the response’s
X-Lacing-Clockheader value (when present) aslacing.clock.No-op when OTel isn’t installed — the app is returned unchanged.
- Parameters:
app (
Any) – The FastAPI app (fromlacing.server.create_app()).tracer_name (
str) – Name passed toget_tracer().
- Return type:
- Returns:
The same app, with middleware installed if OTel is available.
- lacing.otel.is_otel_active()[source]#
Quick check: is OTel installed AND a TracerProvider configured?
- Return type:
- lacing.otel.maybe_span(tracer, name, **attributes)[source]#
Open a span on
tracer, attachingattributesif supported.Works with both real OTel tracers and the no-op fallback.
- lacing.otel.traced(tracer, span_name=None, *, record_args=False)[source]#
Decorator: wrap a function in a span on
tracer.- Parameters:
tracer (
Any) – Fromget_tracer().span_name (
str|None) – Override the span name. Default:func.__qualname__.record_args (
bool) – If True, attach (str-coerced) positional + keyword args as span attributesarg.<n>/kwarg.<name>. Off by default — args may contain large or sensitive data.