telemetry

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 3, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package telemetry generates the OpenTelemetry Collector configuration that receives OTLP from Claude Code, Codex and Gemini CLI, normalises their harness-specific metrics into the halo.* schema, and exports to ClickHouse and Prometheus.

Verified end to end by `make obs-e2e` (scripts/obs-e2e.sh): the config loads in otelcol-contrib 0.161.0 (`validate`), the transform renames metrics and stamps halo.harness, and clickhouseexporter writes the rows that deploy/observability/clickhouse/schema.sql projects into halo_metrics. Codex telemetry is event-oriented and its native metrics are not mapped; Codex only matches when it reports gen_ai.client.token.usage with halo.harness=codex set. API/tool events from all three CLIs arrive on the logs pipeline and are turned into halo.api.request / halo.tool.call rows by the schema's log view.

Metrics fan out to two pipelines: ClickHouse gets cumulativetodelta (so per-unit sums never double count cumulative counters); Prometheus keeps the native temporality, takes only the halo.* resource attributes as labels, and drops halo-proxy's halo.gateway.* metrics, whose per-unit halo.unit attribute would explode label cardinality (halo-proxy serves its own /metrics).

Evidence trust: there are two OTLP receivers. `otlp` (CLI, 4317/4318) must be reachable from developer machines, so anything on it is client-controlled: it drops every halo.gateway.* metric and overwrites the data point attribute halo.source with "cli". `otlp/gateway` (OTLP/HTTP, 4319) requires the halo-proxy bearer token (${env:HALO_OTLP_GATEWAY_TOKEN}; the collector refuses to start without it) and stamps halo.source="gateway". internal/promote only counts halo.gateway.* rows carrying halo.source=gateway, and the controller only auto-kills on gateway-sourced evidence. Optionally the CLI receiver requires per-device bearer tokens (Options.CLITokenFile, one per line, hot-reloaded); either way its request size is capped.

Optionally (Options.EvalReceiver) a third receiver, `otlp/eval` (OTLP/HTTP, 4320), takes `halo eval online` quality readings behind its own token (${env:HALO_OTLP_EVAL_TOKEN}, never the gateway token): it keeps only halo.eval.* metrics (so it can never carry halo.gateway.* evidence) and stamps halo.source="eval", which nothing auto-kills on.

Index

Constants

View Source
const (
	SourceGateway = "gateway"
	SourceCLI     = "cli"
	SourceEval    = "eval"
)

Trusted per-receiver values of the halo.source data point attribute.

View Source
const EvalTokenEnv = "HALO_OTLP_EVAL_TOKEN" //nolint:gosec // env var name, not a credential

EvalTokenEnv is the collector environment variable holding the bearer token `halo eval online` presents on the eval receiver. It must differ from the gateway token: eval jobs must never be able to write gateway evidence.

View Source
const GatewayTokenEnv = "HALO_OTLP_GATEWAY_TOKEN" //nolint:gosec // env var name, not a credential

GatewayTokenEnv is the collector environment variable holding the bearer token halo-proxy presents on the gateway receiver.

Variables

View Source
var Mappings = []Mapping{
	{"claude-code", "claude_code.cost.usage", "halo.cost.usd"},
	{"claude-code", "claude_code.token.usage", "halo.tokens"},
	{"claude-code", "claude_code.code_edit_tool.decision", "halo.edit.decision"},
	{"claude-code", "claude_code.session.count", "halo.sessions"},
	{"claude-code", "claude_code.lines_of_code.count", "halo.loc"},
	{"claude-code", "claude_code.pull_request.count", "halo.pull_requests"},
	{"claude-code", "claude_code.commit.count", "halo.commits"},
	{"claude-code", "claude_code.active_time.total", "halo.active_time.seconds"},
	{"gemini-cli", "gen_ai.client.token.usage", "halo.tokens"},
	{"gemini-cli", "gen_ai.client.operation.duration", "halo.operation.duration"},
	{"gemini-cli", "gemini_cli.session.count", "halo.sessions"},
	{"gemini-cli", "gemini_cli.tool.call.count", "halo.tool.calls"},
}

Mappings is the single source of truth for metric normalisation.

Functions

func Generate

func Generate(o Options) ([]byte, error)

Generate renders the collector configuration as YAML. Output is deterministic (map keys sorted by the YAML encoder).

Types

type Mapping

type Mapping struct {
	Harness string // value stamped into resource attribute halo.harness if absent
	From    string
	To      string
}

Mapping renames one harness-native metric to its normalised halo.* name.

type Options

type Options struct {
	GRPCEndpoint        string // CLI OTLP/gRPC listen address, default 0.0.0.0:4317
	HTTPEndpoint        string // CLI OTLP/HTTP listen address, default 0.0.0.0:4318
	GatewayHTTPEndpoint string // halo-proxy OTLP/HTTP listen address (bearer token), default 0.0.0.0:4319
	// CLITokenFile, if set, makes the CLI receiver require a bearer token listed
	// in this file (one per line; the collector re-reads it on change).
	CLITokenFile string
	// EvalReceiver adds the authenticated online-eval receiver on
	// EvalHTTPEndpoint (default 0.0.0.0:4320), token from EvalTokenEnv.
	EvalReceiver       bool
	EvalHTTPEndpoint   string
	ClickHouseEndpoint string // required, e.g. tcp://clickhouse:9000
	ClickHouseDatabase string // default halo
	PrometheusEndpoint string // scrape listen address, default 0.0.0.0:8889
}

Options configures the generated collector.

Directories

Path Synopsis
Package gwmetrics is halo-proxy's per-request OTLP metrics emitter: the gateway assigns ring/variant itself, so these are the best-attributed online samples for halo.api.error_rate and halo.latency.* (and the only ones for traffic-axis experiments).
Package gwmetrics is halo-proxy's per-request OTLP metrics emitter: the gateway assigns ring/variant itself, so these are the best-attributed online samples for halo.api.error_rate and halo.latency.* (and the only ones for traffic-axis experiments).
Package synth emits synthetic OTLP/HTTP (JSON) telemetry shaped like the real harnesses, for control vs treatment cohorts with a known injected effect.
Package synth emits synthetic OTLP/HTTP (JSON) telemetry shaped like the real harnesses, for control vs treatment cohorts with a known injected effect.

Jump to

Keyboard shortcuts

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