telemetry

package
v0.145.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 12, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

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

View Source
const (
	ExecInteractive = "interactive"
	ExecHeadless    = "headless"
)

Execution modes (resource attribute infer.execution.mode).

View Source
const (
	ToolSuccess  = "success"
	ToolError    = "error"
	ToolRejected = "rejected"

	ErrTypeTool = "tool_error"
)

Tool outcomes (attribute infer.tool.outcome; error.type on non-success).

View Source
const (
	RunSuccess      = "success"
	RunFailed       = "failed"
	RunStoppedEarly = "stopped_early"
)

Session/run outcomes (attribute infer.run.outcome) - infer-action's enum.

Variables

View Source
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

func Archive(dir string, cutoff time.Time)

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

type CostFunc func(model string, prompt, completion int) (input, output, total float64)

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

func New(opts Options) *Recorder

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

func (r *Recorder) Flush(ctx context.Context)

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

func (r *Recorder) RecordSession(mode, outcome string, dur time.Duration)

RecordSession records one completed agent session (infer.agent.runs + infer.agent.run.duration). outcome is one of RunSuccess/RunFailed/RunStoppedEarly.

func (*Recorder) RecordTool

func (r *Recorder) RecordTool(tool, outcome, errType string, dur time.Duration)

RecordTool records one tool execution (infer.agent.tool.calls + gen_ai.execute_tool.duration).

func (*Recorder) RecordUsage

func (r *Recorder) RecordUsage(model string, prompt, completion int)

RecordUsage records one request's token usage (gen_ai.client.token.usage, one datapoint per token type) and the derived infer.client.cost split.

func (*Recorder) Shutdown

func (r *Recorder) Shutdown(ctx context.Context)

Shutdown flushes the final export and releases resources. Safe on nil.

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).

func Aggregate

func Aggregate(dir string, since time.Time) (Stats, error)

Aggregate reads the per-session OTLP/stdout files under dir and folds their delta datapoints (timestamped on/after since) into Stats. The JSON shape is the SDK stdout exporter's ResourceMetrics; delta temporality means summing every datapoint across every file yields the totals.

type ToolStat

type ToolStat struct {
	Name     string `json:"name"`
	Calls    int    `json:"calls"`
	Failures int    `json:"failures"`
	AvgMs    int64  `json:"avg_ms"`
}

ToolStat aggregates one tool. Failures counts the error outcome (a rejection is not a failure). AvgMs is the mean execution duration.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL