Jido.Observe (Jido v2.0.0-rc.1)
View SourceUnified observability façade for Jido agents.
Wraps :telemetry events and Logger with a simple API for observing
agent execution, action invocations, and workflow iterations.
Features
- Automatic telemetry event emission (start/stop/exception)
- Duration measurement for all spans (nanoseconds)
- Automatic correlation ID enrichment from
Jido.Tracing.Context - Extension point for future OpenTelemetry integration via
Jido.Observe.Tracer - Threshold-based logging via
Jido.Observe.Log
Correlation Tracing Integration
When Jido.Tracing.Context has an active trace context (set via signal processing),
all spans automatically include correlation metadata:
:jido_trace_id- shared trace identifier across the call chain:jido_span_id- unique span identifier for the current signal:jido_parent_span_id- parent span that triggered this signal:jido_causation_id- signal ID that caused this signal
This connects timed telemetry spans with signal causation tracking automatically.
Configuration
config :jido, :observability,
log_level: :info,
tracer: Jido.Observe.NoopTracerUsage
Synchronous work
Jido.Observe.with_span([:jido, :agent, :action, :run], %{agent_id: id, action: "my_action"}, fn ->
# Your code here
{:ok, result}
end)Asynchronous work (Tasks)
span_ctx = Jido.Observe.start_span([:jido, :agent, :async, :request], %{agent_id: id})
Task.start(fn ->
try do
result = do_async_work()
Jido.Observe.finish_span(span_ctx, %{result_size: byte_size(result)})
result
rescue
e ->
Jido.Observe.finish_span_error(span_ctx, :error, e, __STACKTRACE__)
reraise e, __STACKTRACE__
end
end)Telemetry Events
All spans emit standard telemetry events:
event_prefix ++ [:start]- emitted when span startsevent_prefix ++ [:stop]- emitted on successful completionevent_prefix ++ [:exception]- emitted on error
Measurements include:
:system_time- start timestamp (nanoseconds):duration- elapsed time (nanoseconds, on stop/exception)- Any additional measurements passed to
finish_span/2
Metadata Best Practices
Metadata should be small, identifying data (IDs, step numbers, model names), not full
prompts/responses. For large payloads, include derived measurements (prompt_tokens,
prompt_size_bytes) rather than the raw content.
Summary
Functions
Checks if debug events are enabled in configuration.
Emits a debug event only if debug events are enabled in config.
Finishes a span successfully.
Finishes a span with an error.
Conditionally logs a message based on the observability threshold.
Redacts sensitive data based on configuration.
Starts an async span for work that will complete later.
Wraps synchronous work with telemetry span events.
Types
@type event_prefix() :: [atom()]
@type measurements() :: map()
@type metadata() :: map()
@type span_ctx() :: Jido.Observe.SpanCtx.t()
Functions
@spec debug_enabled?() :: boolean()
Checks if debug events are enabled in configuration.
Returns
true if :debug_events is :all or :minimal, false otherwise.
@spec emit_debug_event(event_prefix(), measurements(), metadata()) :: :ok
Emits a debug event only if debug events are enabled in config.
This helper checks the :debug_events config before emitting, ensuring
zero overhead when debugging is disabled (production default).
Configuration
# config/dev.exs
config :jido, :observability,
debug_events: :all # or :minimal, :off
# config/prod.exs
config :jido, :observability,
debug_events: :offParameters
event_prefix- Telemetry event namemeasurements- Map of measurements (durations, counts, etc.)metadata- Map of metadata (agent_id, iteration, etc.)
Example
Jido.Observe.emit_debug_event(
[:jido, :agent, :iteration, :stop],
%{duration: 1_234_567},
%{agent_id: agent.id, iteration: 3, status: :awaiting_tool}
)
@spec finish_span(span_ctx(), measurements()) :: :ok
Finishes a span successfully.
Parameters
span_ctx- The span context returned bystart_span/2extra_measurements- Additional measurements to include (e.g., token counts)
Example
Jido.Observe.finish_span(span_ctx, %{prompt_tokens: 100, completion_tokens: 50})
Finishes a span with an error.
Parameters
span_ctx- The span context returned bystart_span/2kind- The error kind (:error,:exit,:throw)reason- The error reason/exceptionstacktrace- The stacktrace
Example
rescue
e ->
Jido.Observe.finish_span_error(span_ctx, :error, e, __STACKTRACE__)
reraise e, __STACKTRACE__
@spec log(Logger.level(), Logger.message(), keyword()) :: :ok
Conditionally logs a message based on the observability threshold.
Delegates to Jido.Observe.Log.log/3.
Example
Jido.Observe.log(:debug, "Processing step", agent_id: agent.id)
Redacts sensitive data based on configuration.
When :redact_sensitive is true (production default), replaces the value
with "[REDACTED]". Otherwise returns the value unchanged.
Configuration
# config/prod.exs
config :jido, :observability,
redact_sensitive: true
# config/dev.exs
config :jido, :observability,
redact_sensitive: falseParameters
value- The value to potentially redactopts- Optional keyword list with:force_redactoverride
Examples
# In production (redact_sensitive: true)
redact("secret data")
# => "[REDACTED]"
# In development (redact_sensitive: false)
redact("secret data")
# => "secret data"
# Force redaction regardless of config
redact("secret data", force_redact: true)
# => "[REDACTED]"
@spec start_span(event_prefix(), metadata()) :: span_ctx()
Starts an async span for work that will complete later.
Use this for Task-based operations where you can't use with_span/3.
You must call finish_span/2 or finish_span_error/4 when the work completes.
Parameters
event_prefix- List of atoms for the telemetry event namemetadata- Map of metadata to include in all events
Returns
A span context struct to pass to finish_span/2 or finish_span_error/4.
Example
span_ctx = Jido.Observe.start_span([:jido, :ai, :llm, :request], %{model: "claude"})
Task.start(fn ->
result = do_work()
Jido.Observe.finish_span(span_ctx, %{output_bytes: byte_size(result)})
end)
@spec with_span(event_prefix(), metadata(), (-> result)) :: result when result: term()
Wraps synchronous work with telemetry span events.
Emits :start event before executing the function, then either :stop on
success or :exception if an error is raised. Duration is automatically measured.
Parameters
event_prefix- List of atoms for the telemetry event name (e.g.,[:jido, :ai, :react, :step])metadata- Map of metadata to include in all eventsfun- Zero-arity function to execute
Returns
The return value of fun.
Example
Jido.Observe.with_span([:jido, :ai, :tool, :invoke], %{tool: "search"}, fn ->
perform_search(query)
end)