Telemetry event emission for SubAgent execution.
This module provides helpers for emitting telemetry events during SubAgent execution, enabling integration with observability tools like Prometheus, OpenTelemetry, and custom handlers.
Events
All events are prefixed with [:ptc_runner, :sub_agent].
| Event | Measurements | Metadata |
|---|---|---|
[:run, :start] | %{} | agent, context, span_id, parent_span_id |
[:run, :stop] | %{duration: native_time} | agent, step, status, span_id, parent_span_id |
[:run, :exception] | %{duration: native_time} | agent, kind, reason, stacktrace, span_id, parent_span_id |
[:turn, :start] | %{} | agent, turn, span_id, parent_span_id |
[:turn, :stop] | %{duration: native_time, tokens: n, input_tokens: n, output_tokens: n} | agent, turn, program, result_preview, prints, type, span_id, parent_span_id |
[:llm, :start] | %{} | agent, turn, messages, span_id, parent_span_id |
[:llm, :stop] | %{duration: native_time, tokens: n, input_tokens: n, output_tokens: n} | agent, turn, response, span_id, parent_span_id |
[:tool, :start] | %{} | agent, tool_name, args, span_id, parent_span_id |
[:tool, :stop] | %{duration: native_time} | agent, tool_name, result, span_id, parent_span_id |
[:tool, :exception] | %{duration: native_time} | agent, tool_name, kind, reason, stacktrace, span_id, parent_span_id |
Span Correlation
All events include span_id and parent_span_id for correlation:
span_id- 8-character hex string, unique per spanparent_span_id- The span_id of the parent span, ornilfor root spans
Nested spans maintain a parent-child hierarchy. For example, a tool call within a turn will have the turn's span_id as its parent_span_id.
Usage
Attach handlers using :telemetry.attach_many/4:
:telemetry.attach_many(
"my-handler",
[
[:ptc_runner, :sub_agent, :run, :stop],
[:ptc_runner, :sub_agent, :tool, :stop]
],
&MyApp.Telemetry.handle_event/4,
nil
)Duration
Duration measurements use native time units via System.monotonic_time/0.
Convert to milliseconds with System.convert_time_unit(duration, :native, :millisecond).
Summary
Functions
Returns the current span ID, or nil if not within a span.
Emit a telemetry event.
Returns the telemetry event prefix.
Sets the initial span stack for this process.
Execute a function within a telemetry span.
Functions
@spec current_span_id() :: String.t() | nil
Returns the current span ID, or nil if not within a span.
Emit a telemetry event.
Automatically includes span_id and parent_span_id from the current span context.
Parameters
event_suffix- List of atoms to append to the prefixmeasurements- Map of measurements (default:%{})metadata- Map of metadata
@spec prefix() :: [atom()]
Returns the telemetry event prefix.
Examples
iex> PtcRunner.SubAgent.Telemetry.prefix()
[:ptc_runner, :sub_agent]
@spec set_parent_span(String.t() | nil) :: :ok
Sets the initial span stack for this process.
Used for trace propagation across process boundaries. When spawning child processes, capture the parent's current span ID and call this function in the child to establish the parent-child span relationship.
Parameters
parent_span_id- The span ID from the parent process (or nil)
Example
# In parent process
parent_span = Telemetry.current_span_id()
Task.async(fn ->
Telemetry.set_parent_span(parent_span)
# New spans in this process will have parent_span as their parent_span_id
end)
Execute a function within a telemetry span.
Emits :start, :stop, and :exception events automatically.
The start metadata is passed as-is. The stop metadata receives
any additional measurements or metadata returned from the function.
All events include span_id and parent_span_id for correlation.
Parameters
event_suffix- List of atoms to append to the prefix (e.g.,[:run])start_meta- Metadata map for the start eventfun- Zero-arity function to execute. Should return one of:{result, stop_meta}- wherestop_metais merged into stop event metadata{result, extra_measurements, stop_meta}- whereextra_measurementsis merged into stop measurements andstop_metais merged into stop event metadata