Documentation
¶
Overview ¶
Package telemetry records the CLI's OpenTelemetry metrics - tool outcomes, token usage, and sessions - and exports them, with room to grow into traces and logs later (hence "telemetry", not "metrics").
There is one instrumentation path: events are recorded into OpenTelemetry SDK instruments named per the GenAI semantic conventions and infer-action's exporter, so they line up with the gateway's OTLP ingest and existing dashboards. The recorded data is then written by OTel exporters, unchanged:
- local (always, private): the SDK's stdout exporter appended to a per-session file under ~/.infer/telemetry/ - OTLP/semconv JSON as-is, no custom format.
- remote (opt-in): the OTLP/HTTP exporter, active only when an endpoint is set.
Both use delta temporality (what the gateway ingest requires, and what makes the local files trivially summable by `infer stats`).
Index ¶
- Constants
- Variables
- func Archive(dir string, cutoff time.Time)
- func NewToolService(inner domain.ToolService, rec *Recorder) domain.ToolService
- func ParseSince(s string) (time.Time, error)
- type CostFunc
- type ModelStat
- type Options
- type Recorder
- func (r *Recorder) Flush(ctx context.Context)
- func (r *Recorder) RecordSession(mode, outcome string, dur time.Duration)
- func (r *Recorder) RecordTool(tool, outcome, errType string, dur time.Duration)
- func (r *Recorder) RecordUsage(model string, prompt, completion int)
- func (r *Recorder) Shutdown(ctx context.Context)
- type SessionStat
- type Stats
- type ToolStat
Constants ¶
const ( ExecInteractive = "interactive" ExecHeadless = "headless" )
Execution modes (resource attribute infer.execution.mode).
const ( ToolSuccess = "success" ToolError = "error" ToolRejected = "rejected" ErrTypeTool = "tool_error" )
Tool outcomes (attribute infer.tool.outcome; error.type on non-success).
const ( RunSuccess = "success" RunFailed = "failed" RunStoppedEarly = "stopped_early" )
Session/run outcomes (attribute infer.run.outcome) - infer-action's enum.
Variables ¶
var ( Version = "dev" ExecutionMode = ExecHeadless )
Process-wide facts stamped onto every metric via the resource. Version is the build version; ExecutionMode distinguishes interactive chat from headless `infer agent`. cmd sets these before building the service container.
Functions ¶
func Archive ¶
Archive moves session files older than cutoff into an archive/ subdir instead of deleting them; Aggregate's non-recursive glob then skips them. Best-effort.
func NewToolService ¶
func NewToolService(inner domain.ToolService, rec *Recorder) domain.ToolService
NewToolService wraps inner so tool executions are recorded. The container only applies this when rec is non-nil, so the disabled tool path carries no decorator at all.
Types ¶
type CostFunc ¶
CostFunc returns the input, output, and total cost for a model's token counts (wraps domain.PricingService.CalculateCost). Pass nil to skip cost.
type ModelStat ¶
type ModelStat struct {
Model string `json:"model"`
Prompt int `json:"prompt"`
Completion int `json:"completion"`
Total int `json:"total"`
Cost float64 `json:"cost"`
}
ModelStat aggregates token usage and cost for one model.
type Options ¶
type Options struct {
Enabled bool
Dir string
SessionID string
OTLPEndpoint string
OTLPHeaders map[string]string
OTLPInterval time.Duration
Cost CostFunc
}
Options configures a Recorder. Dir + SessionID locate the per-process local file; OTLP* enable the optional remote export.
type Recorder ¶
type Recorder struct {
// contains filtered or unexported fields
}
Recorder maps recorded events onto OTel instruments. A nil *Recorder is a valid no-op, so callers guard hot paths with `if rec != nil` and the container skips wrapping when disabled.
func New ¶
New builds a Recorder, or nil when disabled or no sink could be created. The local file sink is always attempted; the OTLP sink is added when an endpoint is configured (or OTEL_EXPORTER_OTLP_ENDPOINT is set). Sink failures are logged and dropped so telemetry never breaks a run.
func (*Recorder) Flush ¶
Flush forces an immediate export of everything recorded so far, without tearing down (used by tests and callers that want data on disk now). Safe on nil.
func (*Recorder) RecordSession ¶
RecordSession records one completed agent session (infer.agent.runs + infer.agent.run.duration). outcome is one of RunSuccess/RunFailed/RunStoppedEarly.
func (*Recorder) RecordTool ¶
RecordTool records one tool execution (infer.agent.tool.calls + gen_ai.execute_tool.duration).
func (*Recorder) RecordUsage ¶
RecordUsage records one request's token usage (gen_ai.client.token.usage, one datapoint per token type) and the derived infer.client.cost split.
type SessionStat ¶
type SessionStat struct {
Execution string `json:"execution"`
Mode string `json:"mode"`
Count int `json:"count"`
}
SessionStat counts sessions by execution mode (interactive/headless) and agent mode.
type Stats ¶
type Stats struct {
Tools []ToolStat `json:"tools"`
Models []ModelStat `json:"models"`
Sessions []SessionStat `json:"sessions"`
Empty bool `json:"-"`
}
Stats is the `infer stats` aggregate over the local telemetry files. Empty is true when no datapoints matched (clean empty-store render).