ExAgent.Telemetry (ExAgent v0.3.0)

Copy Markdown View Source

:telemetry events emitted around every provider call.

A library whose job is calling billed APIs has to be measurable: latency, token spend, failure rate, and tool-loop depth are operational facts, not debugging trivia. Attaching a handler is the supported way to get them - nothing here logs on your behalf.

Events

EventMeasurementsMetadata
[:ex_agent, :chat, :start]:system_time:provider, :model, :message_count, :streaming?
[:ex_agent, :chat, :stop]:duration, plus :input_tokens, :output_tokens, :total_tokens when reported:provider, :model, :result, :streaming?
[:ex_agent, :chat, :exception]:duration:provider, :model, :kind, :reason, :stacktrace
[:ex_agent, :embed, :start]:system_time:provider, :input_count
[:ex_agent, :embed, :stop]:duration, :input_tokens, :total_tokens:provider, :model, :result
[:ex_agent, :tool, :stop]:duration:tool, :result

:result is :ok, :tool_calls, or :error. On :error the metadata also carries :error_type and :retryable? from ExAgent.Error, which is what a retry-rate dashboard is actually built on.

Example

:telemetry.attach(
  "ex-agent-cost",
  [:ex_agent, :chat, :stop],
  fn _event, measurements, metadata, _config ->
    MyApp.Metrics.record(metadata.model, measurements[:total_tokens] || 0)
  end,
  nil
)

:telemetry is a hard dependency but a tiny one, and emitting with no handler attached costs a single ETS lookup.

Summary

Functions

Runs fun, emitting :start/:stop/:exception events under [:ex_agent | name].

Functions

span(name, metadata, fun)

@spec span([atom()], map(), (-> result)) :: result when result: term()

Runs fun, emitting :start/:stop/:exception events under [:ex_agent | name].