Observability (ADR-12)¶
dag-ml emits structured tracing spans and events
from the control core. The core only emits through the tracing facade; it never
installs a subscriber, so it stays a no-op (and WASM-safe) until a binary or host
chooses a sink.
What is emitted¶
All telemetry is centralized in crates/dag-ml-core/src/observability.rs:
Site |
Kind |
Fields |
|---|---|---|
Each phase scope ( |
|
|
Each node invocation (nested under its phase span) |
|
|
Out-of-fold leakage refusal |
|
|
The parallel scheduler clones the phase span into each worker thread so node
spans nest correctly across thread::scope.
The category/code fields mirror the ADR-11 error taxonomy, so a log consumer
can alert on refusals without parsing human messages.
Privacy invariant¶
Telemetry carries identifiers and counts only — never feature matrices, targets, sample values or metadata contents. This extends the data-ABI boundary (the core never inspects raw data) to the telemetry layer.
Two guards enforce it:
The frozen
OBSERVABILITY_FIELD_ALLOWLISTconstant lists every permitted field.The CI lint
scripts/lint_tracing_fields.pyfails the build if anytracingusage appears outsideobservability.rs, or if any field name in that module matchesdata|features|targets|samples|metadata.
Adding a field requires updating the allowlist and ADR-12, and passes through the same review.
Consuming the stream¶
CLI¶
The CLI installs a JSON-logfmt subscriber to stderr, gated by RUST_LOG:
RUST_LOG=dag_ml=info cargo run -p dag-ml-cli -- run-mock-campaign … 2> events.jsonl
# only OOF refusals:
RUST_LOG=dag_ml=warn cargo run -p dag-ml-cli -- … 2> >(jq 'select(.fields.oof_refused == true)')
With RUST_LOG unset the CLI stays quiet (no subscriber is installed).
Hosts (Rust)¶
A host that links the crates installs its own subscriber (e.g.
tracing_subscriber::fmt().json().init(), or an OpenTelemetry layer) before
driving a run. nirs4all-studio’s backend reads the JSON-logfmt stream into its
existing telemetry widgets.
Hosts (C / non-Rust)¶
Call dagml_init_tracing(json_output) once near startup (the minimal C hook): it
installs a process-global subscriber to stderr, RUST_LOG-filtered (default
info), emitting JSON-logfmt when json_output != 0. It returns
VALIDATION_ERROR (no-op) if a subscriber is already installed.
Not yet implemented¶
The following ADR-12 items are deferred to a follow-up tranche and are not part of the current surface:
the
cache_hitspan field (prediction-cache instrumentation);the Prometheus metrics surface (
dagml_phase_duration_seconds, …);the optional OpenTelemetry OTLP exporter (
--features otel).