Current section

Files

Jump to
puck lib puck telemetry.ex
Raw

lib/puck/telemetry.ex

if Code.ensure_loaded?(:telemetry) do
defmodule Puck.Telemetry do
@moduledoc """
Telemetry integration for observability.
Puck automatically emits telemetry events when the `:telemetry` dependency
is installed. No configuration is required.
## Events
### Call Start
`[:puck, :call, :start]` - Executed before the LLM call.
#### Measurements
* `:system_time` - The system time in native units.
#### Metadata
* `:client` - The `Puck.Client` struct.
* `:prompt` - The prompt content.
* `:context` - The `Puck.Context` struct.
### Call Stop
`[:puck, :call, :stop]` - Executed after a successful LLM call.
#### Measurements
* `:duration` - Time taken in native units.
#### Metadata
* `:client` - The `Puck.Client` struct.
* `:response` - The `Puck.Response` struct.
* `:context` - The `Puck.Context` struct.
### Call Exception
`[:puck, :call, :exception]` - Executed when the call fails.
#### Measurements
* `:duration` - Time taken before failure in native units.
#### Metadata
* `:client` - The `Puck.Client` struct.
* `:context` - The `Puck.Context` struct.
* `:kind` - The exception type (`:error`, `:exit`, or `:throw`).
* `:reason` - The error reason.
* `:stacktrace` - The stacktrace (may be empty).
### Stream Start
`[:puck, :stream, :start]` - Executed before streaming begins.
#### Measurements
* `:system_time` - The system time in native units.
#### Metadata
* `:client` - The `Puck.Client` struct.
* `:prompt` - The prompt content.
* `:context` - The `Puck.Context` struct.
### Stream Chunk
`[:puck, :stream, :chunk]` - Executed for each streamed chunk.
#### Measurements
No measurements.
#### Metadata
* `:client` - The `Puck.Client` struct.
* `:chunk` - The chunk data.
* `:context` - The `Puck.Context` struct.
### Stream Stop
`[:puck, :stream, :stop]` - Executed after streaming completes.
#### Measurements
* `:duration` - Time taken in native units.
#### Metadata
* `:client` - The `Puck.Client` struct.
* `:context` - The `Puck.Context` struct.
### Stream Exception
`[:puck, :stream, :exception]` - Executed when streaming initialization fails.
#### Measurements
* `:duration` - Time taken before failure in native units.
#### Metadata
* `:client` - The `Puck.Client` struct.
* `:context` - The `Puck.Context` struct.
* `:kind` - The exception type (`:error`, `:exit`, or `:throw`).
* `:reason` - The error reason.
* `:stacktrace` - The stacktrace (may be empty).
### Backend Request
`[:puck, :backend, :request]` - Executed before the backend request.
#### Measurements
* `:system_time` - The system time in native units.
#### Metadata
* `:config` - The backend configuration.
* `:messages` - The messages being sent.
### Backend Response
`[:puck, :backend, :response]` - Executed after the backend response.
#### Measurements
* `:system_time` - The system time in native units.
#### Metadata
* `:config` - The backend configuration.
* `:response` - The backend response.
### Backend BAML Error
`[:puck, :backend, :baml, :error]` — Emitted when the BAML backend returns
an error. Includes the raw LLM response from the collector so callers can
inspect what the model actually returned.
#### Measurements
No measurements.
#### Metadata
* `:function` - The BAML function name.
* `:reason` - The error reason (string from the NIF).
* `:raw_llm_response` - The raw LLM response string, or `nil` if unavailable.
> The `:raw_llm_response` value is the unredacted model output. If the
> prompt contained sensitive data, the response may echo it back. Redact
> before logging in production.
### Compaction Start
`[:puck, :compaction, :start]` - Executed before context compaction.
#### Measurements
* `:system_time` - The system time in native units.
#### Metadata
* `:context` - The `Puck.Context` struct before compaction.
* `:strategy` - The compaction strategy module.
* `:config` - The compaction configuration.
### Compaction Stop
`[:puck, :compaction, :stop]` - Executed after successful compaction.
#### Measurements
* `:duration` - Time taken in native units.
* `:messages_before` - Message count before compaction.
* `:messages_after` - Message count after compaction.
#### Metadata
* `:context` - The `Puck.Context` struct after compaction.
* `:strategy` - The compaction strategy module.
### Compaction Error
`[:puck, :compaction, :error]` - Executed when compaction fails.
#### Measurements
* `:duration` - Time taken before failure in native units.
#### Metadata
* `:context` - The `Puck.Context` struct.
* `:strategy` - The compaction strategy module.
* `:reason` - The error reason.
### LiveView Stream Start
`[:puck, :live_view, :stream, :start]` — Emitted when a LiveView stream
begins.
#### Measurements
* `:system_time` - The system time in native units.
#### Metadata
* `:stream_id` - The stream identifier.
* `:client` - The `Puck.Client` struct.
### LiveView Stream Stop
`[:puck, :live_view, :stream, :stop]` — Emitted when a LiveView stream
completes.
#### Measurements
* `:duration` - Time taken in native units.
#### Metadata
* `:stream_id` - The stream identifier.
* `:response` - The `Puck.Response` struct.
### LiveView Stream Error
`[:puck, :live_view, :stream, :error]` — Emitted when a LiveView stream
fails.
#### Measurements
No measurements.
#### Metadata
* `:stream_id` - The stream identifier.
* `:reason` - The error reason.
### LiveView Stream Cancel
`[:puck, :live_view, :stream, :cancel]` — Emitted when a LiveView stream
is cancelled.
#### Measurements
No measurements.
#### Metadata
* `:stream_id` - The stream identifier.
* `:content` - The accumulated content at cancellation.
### LiveView Stream Handler Error
`[:puck, :live_view, :stream, :handler_error]` — Emitted when a
`Puck.LiveView.Handler` callback raises.
#### Measurements
No measurements.
#### Metadata
* `:stream_id` - The stream identifier.
* `:handler` - The handler module.
* `:callback` - The callback that raised (e.g. `:on_chunk`, `:on_done`).
* `:reason` - The exception.
## Attaching Handlers
:telemetry.attach_many("my-handler", Puck.Telemetry.event_names(), &handler/4, nil)
# Or use the default logger
Puck.Telemetry.attach_default_logger()
"""
@doc """
Returns all telemetry event names that can be emitted.
Useful for attaching handlers to all events.
## Example
:telemetry.attach_many("my-handler", Puck.Telemetry.event_names(), &handler/4, nil)
"""
def event_names do
[
[:puck, :call, :start],
[:puck, :call, :stop],
[:puck, :call, :exception],
[:puck, :stream, :start],
[:puck, :stream, :chunk],
[:puck, :stream, :stop],
[:puck, :stream, :exception],
[:puck, :backend, :request],
[:puck, :backend, :response],
[:puck, :backend, :baml, :error],
[:puck, :compaction, :start],
[:puck, :compaction, :stop],
[:puck, :compaction, :error],
[:puck, :live_view, :stream, :start],
[:puck, :live_view, :stream, :stop],
[:puck, :live_view, :stream, :error],
[:puck, :live_view, :stream, :cancel],
[:puck, :live_view, :stream, :handler_error]
]
end
@doc """
Attaches a default logging handler to all Puck telemetry events.
This is a convenience function for quick debugging. For production use,
you should implement your own handler with appropriate log levels and formatting.
## Options
- `:level` - Log level to use (default: `:debug`)
## Example
Puck.Telemetry.attach_default_logger()
Puck.Telemetry.attach_default_logger(level: :info)
"""
def attach_default_logger(opts \\ []) do
level = Keyword.get(opts, :level, :debug)
:telemetry.attach_many(
"puck-telemetry-default-logger",
event_names(),
&__MODULE__.log_event/4,
%{level: level}
)
end
@doc """
Detaches the default logging handler.
"""
def detach_default_logger do
:telemetry.detach("puck-telemetry-default-logger")
end
@doc false
def log_event(event, measurements, metadata, config) do
require Logger
level = Map.get(config, :level, :debug)
event_name = Enum.join(event, ".")
Logger.log(level, fn ->
"[#{event_name}] #{inspect(measurements)} #{inspect(metadata, limit: 3)}"
end)
end
end
end