Documentation
¶
Overview ¶
Package observability wires OpenTelemetry into agentctl.
Slice 5.1 (v0.5.0 introduction):
- InitTracerProvider() sets up the global trace provider with an OTLP/HTTP exporter. Endpoint + headers come from the standard OTEL_EXPORTER_OTLP_* env vars so users don't learn a new config surface; BrainTrust / MLflow / Langfuse / OTel Collector all use the same vars.
- Tracer() returns the named tracer agentctl spans hang off of.
- StartRootSpan() opens a span at the root of agentctl's run path and sets the GenAI semconv attributes (gen_ai.system, gen_ai.request.model, gen_ai.operation.name).
Later slices (5.2 onward) add wire-event TRACEPARENT propagation, adapter-side spans, and per-tool spans. This file keeps the host-side CLI plumbing in one place.
Index ¶
- Constants
- func ExtractTraceContextFromEnv(ctx context.Context) context.Context
- func InitTracerProvider(ctx context.Context, serviceVersion string) (shutdown func(context.Context) error, err error)
- func SetLateAttributes(span trace.Span, attrs RunAttributes)
- func StartRootSpan(ctx context.Context, attrs RunAttributes) (context.Context, trace.Span)
- func Tracer() trace.Tracer
- type RunAttributes
Constants ¶
const TracerName = "github.com/CCDevelopForFun/agent-controller/cli"
TracerName is the instrumentation-scope name attached to every span agentctl emits. Downstream observability platforms can filter on it.
Variables ¶
This section is empty.
Functions ¶
func ExtractTraceContextFromEnv ¶
ExtractTraceContextFromEnv reads TRACEPARENT (and TRACESTATE if set) from the process environment, runs them through the globally-configured TextMapPropagator, and returns a child context carrying the extracted parent. When TRACEPARENT is unset the input ctx is returned unchanged.
Used by the agentctl entrypoint to pick up the trace context that KubernetesBackend.Submit injects into the Pod container env (slice 5.2). Without this call the in-Pod agentctl would start a fresh root span instead of nesting under the host `agentctl.run` span, defeating the host→pod→adapter trace stitching codex pass on slice 5.2 caught.
Safe to call unconditionally:
- tracing disabled at this level → no-op propagator, ctx unchanged
- TRACEPARENT unset → ctx unchanged
- malformed TRACEPARENT → the W3C propagator silently ignores it (no panic, no half-applied state)
func InitTracerProvider ¶
func InitTracerProvider(ctx context.Context, serviceVersion string) (shutdown func(context.Context) error, err error)
InitTracerProvider sets up the global OTel tracer provider and returns a shutdown func the caller MUST defer to flush spans before the process exits. When OTel is disabled (no OTEL_EXPORTER_OTLP_* env vars set, or spec opt-in is off), this is a no-op that returns a no-op shutdown func — callers don't need to branch.
Returns an error only when the OTLP exporter / TracerProvider fails to construct; missing env vars are NOT an error (they mean "don't trace this run").
func SetLateAttributes ¶
func SetLateAttributes(span trace.Span, attrs RunAttributes)
SetLateAttributes adds attributes to a span that weren't known at StartRootSpan time (binding name, session id, backend type). Safe to call after Start so the span lifecycle remains "start → enrich → end."
func StartRootSpan ¶
StartRootSpan opens the agentctl.run root span and sets the GenAI semconv attributes. The returned context carries the active span; the End func MUST be called when the run finishes (deferred is fine). Callers can enrich the span with binding/session/backend attrs later via SetLateAttributes once those values are known.
Types ¶
type RunAttributes ¶
type RunAttributes struct {
AgentName string
ModelProvider string // e.g. "anthropic"
ModelName string // e.g. "claude-sonnet-4-20250514"
RuntimeType string // in-Pod / in-process adapter: "local", "local-opencode", …
BackendType string // Backend implementation: "local" (LocalBackend), "kubernetes" (KubernetesBackend)
BindingName string // empty when no --binding
SessionID string // empty when no --resume
}
RunAttributes is the typed payload StartRootSpan annotates the root span with. Pulled out as a struct so callers don't have to remember which OTel attribute keys to use; we own the semconv mapping here.
RuntimeType vs BackendType is the load-bearing distinction: a K8s binding sets RuntimeType=local|local-pi|local-opencode (what runs inside the Pod) but BackendType=kubernetes (where the host launched it). Operators filter on backend.type to separate cluster traces from local-dev traces. Codex pass 4 of slice 5.1 added the split.