ClaudeWrapper.Telemetry (ClaudeWrapper v0.7.0)

Copy Markdown View Source

:telemetry events emitted by ClaudeWrapper.

Wraps the core exec paths with :telemetry.span/3 so downstream applications can subscribe once via :telemetry.attach_many/4 and observe query, stream, and session-turn lifecycle.

Events

  • [:claude_wrapper, :exec, :start | :stop | :exception] -- emitted around ClaudeWrapper.Query.execute/2 (one-shot, synchronous query).

  • [:claude_wrapper, :stream, :start | :stop | :exception] -- emitted around ClaudeWrapper.Query.stream/2. The :stop event fires when the returned stream is fully consumed or closed; :start fires when the stream is first reduced.

  • [:claude_wrapper, :session, :turn, :start | :stop | :exception] -- emitted around ClaudeWrapper.Session.send/3 (a single turn of a multi-turn session).

Measurements

Automatically populated by :telemetry.span/3:

  • :start -- %{monotonic_time: integer(), system_time: integer()}
  • :stop -- %{monotonic_time: integer(), duration: integer()}
  • :exception -- %{monotonic_time: integer(), duration: integer()}

Metadata

Every event carries at least:

  • :command -- atom identifying the call site, e.g. :query (one-shot execute), :stream, or :session_turn.
  • :session_id -- present when known (a resumed session, or the session_id returned by the CLI in the result).
  • :model -- from ClaudeWrapper.Query.model/2 or session query_opts.
  • :resume? -- boolean, whether this invocation threads a previously established session_id.

:stop events additionally include:

  • :cost_usd -- parsed from the final NDJSON result, when available.
  • :exit_code -- 0 on success, non-zero when the CLI exited with an error that still produced output, nil for other errors.

:exception events follow the standard :telemetry.span/3 shape and add :kind, :reason, and :stacktrace.

Example

:telemetry.attach_many(
  "my-handler",
  [
    [:claude_wrapper, :exec, :stop],
    [:claude_wrapper, :stream, :stop],
    [:claude_wrapper, :session, :turn, :stop]
  ],
  fn event, measurements, metadata, _config ->
    Logger.info(fn ->
      "#{inspect(event)} duration=#{measurements.duration} cost=#{inspect(metadata.cost_usd)}"
    end)
  end,
  nil
)

Summary

Functions

Wrap a one-shot query execution in a [:claude_wrapper, :exec, _] span.

Wrap a session turn in a [:claude_wrapper, :session, :turn, _] span.

Wrap a streaming query in a [:claude_wrapper, :stream, _] span.

Types

metadata()

@type metadata() :: %{optional(atom()) => term()}

Functions

span_exec(query, fun)

@spec span_exec(ClaudeWrapper.Query.t(), (-> {:ok, ClaudeWrapper.Result.t()}
                                       | {:error, term()})) ::
  {:ok, ClaudeWrapper.Result.t()} | {:error, term()}

Wrap a one-shot query execution in a [:claude_wrapper, :exec, _] span.

fun must return {:ok, %Result{}} | {:error, term()}. Stop metadata is derived from the return value.

span_session_turn(session, query, fun)

@spec span_session_turn(
  map(),
  ClaudeWrapper.Query.t(),
  (-> {:ok, map(), ClaudeWrapper.Result.t()} | {:error, term()})
) :: {:ok, map(), ClaudeWrapper.Result.t()} | {:error, term()}

Wrap a session turn in a [:claude_wrapper, :session, :turn, _] span.

fun must return {:ok, updated_session, %Result{}} | {:error, term()}.

span_stream(query, stream_fun)

@spec span_stream(ClaudeWrapper.Query.t(), (-> Enumerable.t())) :: Enumerable.t()

Wrap a streaming query in a [:claude_wrapper, :stream, _] span.

stream_fun must return an Enumerable.t() of %StreamEvent{}. The span's :start fires on first reduce, :stop fires when the consumer halts or the producer is exhausted. :stop metadata captures cost_usd / session_id from the terminal result stream event, when observed.