Expand description
§cognee-observability
OpenTelemetry tracing pipeline for Cognee-Rust. Bridges the existing
tracing instrumentation (60+ #[tracing::instrument] sites across
the workspace) into an OTLP exporter so spans flow to a collector.
This crate is the single home for OTEL configuration, OTLP exporter
construction, the tracing-opentelemetry bridge layer, and the RAII
TelemetryGuard that flushes pending spans on drop.
§Activation
Tracing is activated when either of:
Settings.cognee_tracing_enabled == true(env:COGNEE_TRACING_ENABLED=true)Settings.otel_exporter_otlp_endpointis non-empty (env:OTEL_EXPORTER_OTLP_ENDPOINT=https://...)
Either path triggers the same provider setup. This mirrors Python’s
is_tracing_enabled() lazy-init semantics in
cognee/modules/observability/trace_context.py.
§Programmatic init
Drive init_telemetry from a SettingsView implementation. The
EnvSettingsView adapter reads the standard env vars directly, so
callers that don’t want to depend on cognee-lib can still bring up
the pipeline:
use cognee_observability::{init_telemetry, EnvSettingsView, TelemetryGuard};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Registry};
let settings = EnvSettingsView::from_env();
let (otel_layer, guard): (_, TelemetryGuard) =
init_telemetry::<Registry>(&settings).expect("telemetry init");
Registry::default()
.with(otel_layer)
.with(tracing_subscriber::EnvFilter::from_default_env())
.with(tracing_subscriber::fmt::layer())
.init();
// Hold `guard` for the lifetime of your process; dropping it
// calls `force_flush()` then `shutdown()` on the OTEL provider.
drop(guard);Embedders that already use cognee_lib::config::Settings can pass it
directly — Settings implements SettingsView.
§Configuration
See docs/observability/opentelemetry.md
for the full env-var reference and deployment recipes (Tempo, Honeycomb,
Dash0, in-cluster Collector).
§Feature flags
telemetry(off by default) — pulls inopentelemetry,opentelemetry_sdk,opentelemetry-otlp,opentelemetry-semantic-conventions,tracing-opentelemetry, plustonicandhttpfor gRPC metadata construction. When enabled,init_telemetrybuilds a realSdkTracerProvider, installs it globally, and returns a guard that flushes on drop. When disabled,init_telemetrystill compiles but returns an identity tracing layer plus a noop guard, so embedders can call it unconditionally.
§Feature-state contract
init_telemetry returns Ok((noop_layer, TelemetryGuard::noop()))
whenever the process is not configured to export spans — specifically
when either (1) the telemetry cargo feature is off at compile
time, or (2) is_tracing_enabled returns false at runtime
(COGNEE_TRACING_ENABLED is not truthy and
OTEL_EXPORTER_OTLP_ENDPOINT is empty). On both paths the returned
layer is a boxed tracing_subscriber::layer::Identity that observes
nothing, and the guard’s Drop runs no code. TelemetryGuard::noop
is publicly constructible for tests and embedders that want the same
shape without going through init_telemetry. This mirrors parent
decision 6
(implicit activation: an endpoint alone is enough to opt in).
Structs§
- EnvSettings
View - Snapshot of OTEL-relevant env vars usable as a
SettingsView. - Telemetry
Guard - RAII handle that flushes and shuts down the global tracer provider on drop.
Enums§
- Telemetry
Init Error - Stub
TelemetryInitErrorexposed when thetelemetryfeature is off so that the public signature ofinit_telemetrydoes not change shape between builds. The variant is unreachable in practice — the noop path always returnsOk.
Traits§
- Settings
View - Borrow-only adapter over the OTEL fields of cognee
Settings.
Functions§
- already_
instrumented - Has this crate already installed an OTEL tracer provider in the current process?
- init_
telemetry - Build the OTEL
tracinglayer and an RAII guard. - is_
tracing_ enabled - Python-parity check: should we initialize and emit OTEL spans?
- parse_
otlp_ headers - Parse
"k1=v1,k2=v2"into a list of(key, value)pairs.
Type Aliases§
- Boxed
Telemetry Layer - Type-erased layer compatible with any
tracingregistry that supportsLookupSpan. Boxing is what lets the disabled and enabled paths return the same shape — the caller composes it onto a subscriber via.with(layer)without seeing the underlying generic parameters.