iii-observability worker
turns that information into OpenTelemetry traces, metrics, and logs. Do not declare it in either
config.yaml or worker-compose.yaml.
This page is a quick tour. For the complete configuration and the full list of query functions,
see the iii-observability worker docs.
OpenTelemetry support
iii-observability is OpenTelemetry-based: it produces distributed traces across worker hops,
metrics, and structured logs, and it can export them to any OTel-compatible backend or keep them
in-memory for local development. Sampling, retention, and exporter targets are configured on the
worker; see the worker docs for the full set of options.
Logging
Worker code emits structured logs through theLogger from the observability SDK, which routes them
into the same OpenTelemetry pipeline (so log lines correlate with the trace they happened in) rather
than to raw stdout.
- Node / TypeScript
- Python
- Rust
Traces
A trace captures the spans of a call as it moves across workers, the headline view for debugging a request end to end. Traces come from worker function invocations: a worker records a span each time it handles a call. Built-inengine::* functions are not traced by default (set
III_OTEL_TRACE_BUILTINS=true to include them), so call a worker function first to produce a trace.
The sandbox worker’s sandbox::run is an easy one to start with:
worker-compose.yaml
iii compose --up before calling the sandbox function. iii-sandbox is an
engine-owned exception, so it belongs under the top-level engine.workers, not under containers.
engine::traces::tree needs a real trace_id and traces export on a short delay. If
engine::traces::list still reports 0 or the call above to get a trace_id resolves to null
and fails then wait a few seconds and try again.React to logs and spans
The observability worker hosts two event sources you can observe:observability::on-log, one event per log record, and observability::on-span, the ids of the
traces that recorded spans in each window of about 300 ms. They replace the log and trace
trigger types, which keep working.
engine::log::* when the call passes no
trace_id.
Activity outside that trace is bounded by depth. A span the engine records for a call made inside a
chain of observers carries an iii.observe_depth attribute (set when the depth is above 0). These
events take that depth, so a target that logs or makes calls on every event stops at
observers.max_observe_depth.
Observers have their own metrics (iii.observer.activations.total, iii.observer.dropped.total,
iii.observers, and more), and calls a worker makes to its own functions are counted in
iii.invocations.total with dispatch="local". See Engine-collected
metrics.
Health and clearing
Check engine health, or clear stored observability data while developing:Logs populate quickly. It is possible to call
engine::logs::clear immediately followed by
engine::logs::list and still see new logs that were generated in between the two calls.