usage

package
v0.5.1 Latest Latest
Warning

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

Go to latest
Published: Aug 28, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Index

Constants

View Source
const (
	OTLPProtocolGRPC = "grpc"
	OTLPProtocolHTTP = "http"
)

OTLP transport protocols accepted by OTLPConfig.Protocol.

Variables

This section is empty.

Functions

func Bool

func Bool(v bool) *bool

func ContextWithDimensions added in v0.5.0

func ContextWithDimensions(ctx context.Context, dims InteractionDimensions) context.Context

ContextWithDimensions replaces the dimensions visible to nested spans while retaining the current InteractionSpan binding.

func ContextWithSpan

func ContextWithSpan(ctx context.Context, span InteractionSpan) context.Context

func GenerateSpanID

func GenerateSpanID() string

func GenerateTraceID

func GenerateTraceID() string

func Int

func Int(v int) *int

func RenderPrometheus

func RenderPrometheus(snap PrometheusSnapshot, stats RuntimeStats) string

RenderPrometheus formats a snapshot plus pipeline health counters as Prometheus text exposition (version 0.0.4).

func TransferFinishOwnership added in v0.5.1

func TransferFinishOwnership(ctx context.Context) bool

TransferFinishOwnership transfers terminal responsibility to the response lifecycle. It returns false when no dispatcher token exists or ownership was already transferred.

func ValidLowerHex

func ValidLowerHex(v string, n int) bool

ValidLowerHex reports whether v is exactly n lowercase hex characters. Unlike ValidTraceID and ValidSpanID it permits the all-zero form, which is legal for traceparent fields that are not ids.

func ValidSpanID

func ValidSpanID(v string) bool

ValidSpanID reports whether v is a W3C span id: 16 lowercase hex characters, not all zeroes. It rejects uppercase for the same reason as ValidTraceID.

func ValidTraceID

func ValidTraceID(v string) bool

ValidTraceID reports whether v is a W3C trace id: 32 lowercase hex characters, not all zeroes. Uppercase is rejected rather than normalized, because a caller that sends it is not speaking the format the gateway echoes back.

Types

type ACPExtension

type ACPExtension struct {
	ServiceID           string
	AgentType           string
	Operation           string
	ThreadID            string
	SessionID           string
	PermissionRequestID string
	FreshSession        *bool
	EventCounts         map[string]int
	UsageJSON           string
	ResultStatus        string
}

type ACPSummary

type ACPSummary struct {
	RequestCount int64 `json:"request_count"`
	TurnCount    int64 `json:"turn_count"`
	SuccessCount int64 `json:"success_count"`
	FailureCount int64 `json:"failure_count"`
	AvgLatencyMS int64 `json:"avg_latency_ms"`
}

type ACPUsageEvent

type ACPUsageEvent struct {
	InteractionEvent
	ServiceID           string
	AgentType           string
	Operation           string
	ThreadID            string
	SessionID           string
	PermissionRequestID string
	FreshSession        *bool
	EventCounts         map[string]int
	UsageJSON           string
	ResultStatus        string
}

type AgentAttribution

type AgentAttribution struct {
	// contains filtered or unexported fields
}

AgentAttribution is a settable holder for an AgentAttributor. The metrics pipeline (and therefore the observer) is constructed before the agent manager exists, so the concrete attributor is injected later via Set without rebuilding the observer.

func NewAgentAttribution

func NewAgentAttribution() *AgentAttribution

func (*AgentAttribution) ResolveAgentID

func (a *AgentAttribution) ResolveAgentID(routeID, serviceID, sessionID string) (string, bool)

ResolveAgentID delegates to the installed attributor, returning ok=false when none is installed.

func (*AgentAttribution) Set

func (a *AgentAttribution) Set(attr AgentAttributor)

Set installs (or replaces) the active attributor. A nil attributor is ignored.

type AgentAttributor

type AgentAttributor interface {
	ResolveAgentID(routeID, serviceID, sessionID string) (string, bool)
}

AgentAttributor maps an originating route/service/session back to a single agent id for write-time usage attribution. It is implemented by the agent control-plane layer and consumed here so the lower layers never depend on pkg/agent (the dependency arrow stays pkg/agent -> runtime). It returns ok=false when the mapping is empty or ambiguous, in which case the agent id is left empty.

type AttributionFilter

type AttributionFilter struct {
	AgentID  string
	RouteIDs []string
}

AttributionFilter selects events that belong to one agent. Write-time agent_id stamping is the primary signal, but it cannot cover events written before the agent existed, before the agent_id column existed, or while the route/service was bound to a different agent. The filter therefore matches the durable agent_id tag OR a resource route the agent currently references, so per-agent reads retain historical nested LLM/MCP rows. Agent ingress itself is always stamped directly from AgentRoute.agent_id; the removed ACP service identity is never used as an active attribution fallback.

func (*AttributionFilter) IsEmpty

func (f *AttributionFilter) IsEmpty() bool

IsEmpty reports whether the filter carries no selector at all.

type BreakdownOptions

type BreakdownOptions struct {
	From        string
	To          string
	GroupBy     string
	OrderBy     string
	Limit       int
	Filters     map[string]string
	Attribution *AttributionFilter
}

type BreakdownResponse

type BreakdownResponse struct {
	GroupBy string           `json:"group_by,omitempty"`
	Items   []map[string]any `json:"items"`
	Limit   int              `json:"limit"`
}

type BuiltinExtension added in v0.5.0

type BuiltinExtension struct {
	Operation           string
	SessionID           string
	RunID               string
	PermissionRequestID string
	LinkTraceID         string
	LinkSpanID          string
	TopologyKind        string
	ModelSteps          *int
	ToolSteps           *int
	EventCounts         map[string]int
	ResultStatus        string
}

type BuiltinSummary added in v0.5.0

type BuiltinSummary struct {
	RequestCount int64 `json:"request_count"`
	TurnCount    int64 `json:"turn_count"`
	SuccessCount int64 `json:"success_count"`
	FailureCount int64 `json:"failure_count"`
	AvgLatencyMS int64 `json:"avg_latency_ms"`
}

type BuiltinUsageEvent added in v0.5.0

type BuiltinUsageEvent struct {
	InteractionEvent
	Operation string
	SessionID string
	// RunID is retained as the typed builtin extension field while the embedded
	// common event carries the same value for cross-runtime consumers.
	RunID               string
	PermissionRequestID string
	// LinkTraceID/LinkSpanID identify the earlier asynchronous segment of the
	// same run. The OTLP adapter reconstructs them as an OpenTelemetry Span
	// Link instead of pretending a resumed HITL turn is a synchronous child.
	LinkTraceID  string
	LinkSpanID   string
	TopologyKind string
	// ModelSteps counts assistant model outputs and ToolSteps counts tool
	// executions observed during the turn.
	ModelSteps   int
	ToolSteps    int
	EventCounts  map[string]int
	ResultStatus string
}

BuiltinUsageEvent captures one builtin-agent turn served by the in-process ADK host. It deliberately does not reuse the ACP family: builtin turns have no backing service, use checkpoint-based permission continuation rather than ACP's side channel, and carry topology step counts instead.

type CommonExtension added in v0.5.0

type CommonExtension struct {
	AgentID     string
	RuntimeType string
	RunID       string
}

CommonExtension lets an execution boundary bind identities that are only known after the outer HTTP span begins (for example a generated run_id).

type Config

type Config struct {
	RetentionDays int        `json:"retention_days,omitempty"`
	MaxAgentDepth int        `json:"max_agent_depth,omitempty"`
	OTLP          OTLPConfig `json:"otlp,omitzero"`
}

func (Config) Normalized

func (c Config) Normalized() Config

type EventListOptions

type EventListOptions struct {
	From        string
	To          string
	Limit       int
	Filters     map[string]string
	Success     *bool
	Attribution *AttributionFilter
}

type EventListResponse

type EventListResponse struct {
	Items []map[string]any `json:"items"`
	Limit int              `json:"limit"`
}

type EventSink

type EventSink interface {
	Enqueue(any) bool
}

type FinishOwnership added in v0.5.1

type FinishOwnership struct {
	// contains filtered or unexported fields
}

FinishOwnership coordinates the single owner allowed to finish an interaction span. The dispatcher owns it initially; a response lifecycle transfers ownership immediately before provider or local execution.

func ContextWithFinishOwnership added in v0.5.1

func ContextWithFinishOwnership(ctx context.Context) (context.Context, *FinishOwnership)

ContextWithFinishOwnership installs a new dispatcher-owned finish token.

func (*FinishOwnership) Transferred added in v0.5.1

func (o *FinishOwnership) Transferred() bool

Transferred reports whether the dispatcher must suppress its normal defer.

type InMemorySink

type InMemorySink struct {
	Dropped atomic.Uint64
	Events  []any
}

func (*InMemorySink) Enqueue

func (s *InMemorySink) Enqueue(v any) bool

type InteractionDimensions

type InteractionDimensions struct {
	TraceID       string
	SpanID        string
	ParentSpanID  string
	AgentDepth    int
	RouteID       string
	RouteKind     string
	RouteProtocol string
	VirtualKeyID  string
	// AgentID, when set by the caller, is stamped verbatim. When empty the
	// observer attempts attribution from RouteID via the wired AgentAttributor.
	AgentID string
	// RuntimeType selects the Agent backend while RunID identifies one logical
	// execution across transport/HITL resume segments.
	RuntimeType string
	RunID       string
}

func DimensionsFromContext added in v0.5.0

func DimensionsFromContext(ctx context.Context) (InteractionDimensions, bool)

DimensionsFromContext returns the resolved dimensions of the interaction span carried by ctx (trace/span ids populated, agent_id resolved). In-process callers use it to derive child-span dimensions for nested interactions.

type InteractionEvent

type InteractionEvent struct {
	EventID       string
	TraceID       string
	SpanID        string
	ParentSpanID  string
	AgentDepth    int
	StartedAt     time.Time
	FinishedAt    time.Time
	RouteID       string
	RouteKind     string
	RouteProtocol string
	VirtualKeyID  string
	Success       bool
	StatusCode    int
	ErrorType     string
	LatencyMS     int64
	// AgentID is the write-time attribution tag. It is empty for non-agent
	// traffic and for events whose route/service maps to zero or more than one
	// agent (stamp only when unambiguous).
	AgentID string
	// RuntimeType and RunID are common Agent-execution dimensions. They remain
	// empty for direct non-Agent protocol traffic and legacy rows.
	RuntimeType string
	RunID       string
}

InteractionEvent captures fields common to every gateway interaction.

type InteractionObserver

type InteractionObserver interface {
	Begin(ctx context.Context, dims InteractionDimensions) (InteractionSpan, context.Context)
}

type InteractionOutcome

type InteractionOutcome struct {
	Success    bool
	StatusCode int
	ErrorType  string
	FinishedAt time.Time
}

type InteractionSpan

type InteractionSpan interface {
	SetExtension(v any)
	AddAnnotation(key, value string)
	Finish(outcome InteractionOutcome)
	// Discard ends the span without emitting an event. Dispatch paths that
	// turn out not to handle the request (path passthrough to the next
	// handler) use it so unhandled requests do not pollute usage events.
	Discard()
}

func SpanFromContext

func SpanFromContext(ctx context.Context) InteractionSpan

type LLMExtension

type LLMExtension struct {
	LLMAPI                string
	APIOperation          string
	ProviderID            string
	ProviderType          string
	LogicalModel          string
	UpstreamModel         string
	CredentialSource      string
	CredentialID          string
	Stream                *bool
	Transport             string
	ResponseOutcome       string
	ResponseCommitted     *bool
	ResponseMode          string
	RelayIneligibleReason string
	MessageIDSource       string
	UsageSource           string
	Execution             string
	InputTokens           *int
	OutputTokens          *int
	TotalTokens           *int
	CachedTokens          *int
	ReasoningTokens       *int
	UsageFinalized        *bool
	RequestToolCount      *int
	RequestToolNames      []string
	ToolCallCount         *int
	ToolNames             []string
}

type LLMSummary

type LLMSummary struct {
	RequestCount    int64 `json:"request_count"`
	SuccessCount    int64 `json:"success_count"`
	FailureCount    int64 `json:"failure_count"`
	InputTokens     int64 `json:"input_tokens"`
	OutputTokens    int64 `json:"output_tokens"`
	TotalTokens     int64 `json:"total_tokens"`
	CachedTokens    int64 `json:"cached_tokens"`
	ReasoningTokens int64 `json:"reasoning_tokens"`
	AvgLatencyMS    int64 `json:"avg_latency_ms"`
}

type LLMUsageEvent

type LLMUsageEvent struct {
	InteractionEvent
	LLMAPI                string
	APIOperation          string
	ProviderID            string
	ProviderType          string
	LogicalModel          string
	UpstreamModel         string
	CredentialSource      string
	CredentialID          string
	Stream                bool
	Transport             string
	ResponseOutcome       string
	ResponseCommitted     bool
	ResponseMode          string
	RelayIneligibleReason string
	MessageIDSource       string
	UsageSource           string
	Execution             string
	InputTokens           int
	OutputTokens          int
	TotalTokens           int
	// CachedTokens is the cache-served subset of InputTokens; ReasoningTokens
	// is the reasoning subset of OutputTokens. Zero when the upstream does not
	// report the breakdown.
	CachedTokens     int
	ReasoningTokens  int
	UsageFinalized   bool
	RequestToolCount int
	RequestToolNames []string
	ToolCallCount    int
	ToolNames        []string
}

type MCPExtension

type MCPExtension struct {
	RequestID          string
	ServiceID          string
	Method             string
	ToolName           string
	PresentedToolName  string
	ExecutedToolName   string
	ExecutionMode      string
	PolicyAction       string
	ResourceURI        string
	PromptName         string
	CompletionRefType  string
	CompletionArgument string
	ArgCount           *int
	ResultStatus       string
	Cancelled          *bool
	ToolArgsJSON       string
}

type MCPSummary

type MCPSummary struct {
	RequestCount   int64 `json:"request_count"`
	SuccessCount   int64 `json:"success_count"`
	FailureCount   int64 `json:"failure_count"`
	ToolsCallCount int64 `json:"tools_call_count"`
	AvgLatencyMS   int64 `json:"avg_latency_ms"`
}

type MCPUsageEvent

type MCPUsageEvent struct {
	InteractionEvent
	RequestID          string
	ServiceID          string
	Method             string
	ToolName           string
	PresentedToolName  string
	ExecutedToolName   string
	ExecutionMode      string
	PolicyAction       string
	ResourceURI        string
	PromptName         string
	CompletionRefType  string
	CompletionArgument string
	ArgCount           int
	ResultStatus       string
	Cancelled          bool
	ToolArgsJSON       string
}

type NoopObserver

type NoopObserver struct{}

type NoopSpan

type NoopSpan struct{}

func (NoopSpan) AddAnnotation

func (NoopSpan) AddAnnotation(string, string)

func (NoopSpan) Discard added in v0.5.0

func (NoopSpan) Discard()

func (NoopSpan) Finish

func (NoopSpan) Finish(InteractionOutcome)

func (NoopSpan) SetExtension

func (NoopSpan) SetExtension(any)

type OTLPConfig added in v0.5.0

type OTLPConfig struct {
	// Endpoint is the collector address as host:port, or a full URL
	// (scheme://host:port). Empty disables export.
	Endpoint string `json:"endpoint,omitempty"`
	// Protocol selects the OTLP transport: "grpc" (default) or "http"
	// (OTLP/HTTP protobuf).
	Protocol string `json:"protocol,omitempty"`
	// Insecure disables transport TLS. Ignored when Endpoint is a full URL,
	// where the scheme decides.
	Insecure bool `json:"insecure,omitempty"`
	// Headers are sent with every export request (e.g. auth tokens).
	Headers map[string]string `json:"headers,omitempty"`
	// ServiceName sets the OTel resource service.name. Default "agent-gateway".
	ServiceName string `json:"service_name,omitempty"`
	// TimeoutSeconds bounds one export batch. Default 10.
	TimeoutSeconds int `json:"timeout_seconds,omitempty"`
	// Components additionally exports one span per eino chat-model component
	// call (via the process-global callbacks tap), nested under the
	// interaction span. Off by default: it multiplies span volume.
	Components bool `json:"components,omitempty"`
}

OTLPConfig configures exporting usage events as OpenTelemetry spans over OTLP. Export is disabled unless Endpoint is set. Events already carry W3C trace/span/parent ids, so the exporter reconstructs the interaction span tree post-hoc instead of running a live tracer.

func (OTLPConfig) Enabled added in v0.5.0

func (c OTLPConfig) Enabled() bool

Enabled reports whether an export endpoint is configured.

func (OTLPConfig) Normalized added in v0.5.0

func (c OTLPConfig) Normalized() OTLPConfig

Normalized fills defaults. It does not validate; see Validate.

func (OTLPConfig) Validate added in v0.5.0

func (c OTLPConfig) Validate() error

Validate checks the normalized form of the config.

type Observer

type Observer struct {
	// contains filtered or unexported fields
}

func NewObserver

func NewObserver(sink EventSink) Observer

func NewObserverWithAttribution

func NewObserverWithAttribution(sink EventSink, attribution *AgentAttribution) Observer

NewObserverWithAttribution wires an attribution holder so the observer stamps agent_id at Begin from the route id when the caller did not set it.

func (Observer) Begin

type Pipeline

type Pipeline interface {
	EventSink
	Start()
	Close() error
	DroppedEvents() uint64
	WriteFailures() uint64
}

type PrometheusLabels added in v0.5.0

type PrometheusLabels struct {
	RouteKind   string
	RuntimeType string
}

PrometheusLabels contains only bounded dimensions. RouteKind is one of the registered route families and RuntimeType is empty or a registered Agent backend type; request, session, route, endpoint, and Agent ids never appear as labels.

type PrometheusProvider

type PrometheusProvider interface {
	PrometheusSnapshot() PrometheusSnapshot
}

PrometheusProvider is implemented by the in-process Prometheus sink and lets the Admin API expose an O(1) /metrics scrape without re-aggregating SQLite.

type PrometheusSnapshot

type PrometheusSnapshot struct {
	Requests map[PrometheusLabels]int64
	Failures map[PrometheusLabels]int64
	Tokens   map[PrometheusLabels]int64
}

PrometheusSnapshot is a low-cardinality counter view of usage events keyed by interaction kind (llm/mcp/acp). It lives in this package so both the sink that produces it (internal/observability/pipeline) and the Admin API that renders it can share the type without an import cycle.

type QueryService

type QueryService interface {
	Summary() (Summary, error)
	ListEvents(kind string, opts EventListOptions) (EventListResponse, error)
	ListInteractions(opts EventListOptions) (EventListResponse, error)
	LLMTimeseries(opts TimeseriesOptions) (SeriesResponse, error)
	LLMBreakdown(opts BreakdownOptions) (BreakdownResponse, error)
	MCPTimeseries(opts TimeseriesOptions) (SeriesResponse, error)
	MCPBreakdown(opts BreakdownOptions) (BreakdownResponse, error)
	MCPToolsSummary(opts SummaryOptions) (BreakdownResponse, error)
	ACPTimeseries(opts TimeseriesOptions) (SeriesResponse, error)
	ACPBreakdown(opts BreakdownOptions) (BreakdownResponse, error)
	ACPSummary(opts BreakdownOptions) (BreakdownResponse, error)
	InteractionsSummary(opts BreakdownOptions) (BreakdownResponse, error)
}

type RuntimeStats

type RuntimeStats interface {
	DroppedEvents() uint64
	WriteFailures() uint64
}

RuntimeStats exposes pipeline health counters for the metrics Admin API so silently dropped or failed usage writes remain observable.

type SQLDBProvider

type SQLDBProvider interface {
	UsageDB() *gorm.DB
}

type SeriesResponse

type SeriesResponse struct {
	Bucket  string           `json:"bucket"`
	GroupBy string           `json:"group_by,omitempty"`
	Items   []map[string]any `json:"items"`
}

type Summary

type Summary struct {
	LLM     LLMSummary     `json:"llm"`
	MCP     MCPSummary     `json:"mcp"`
	ACP     ACPSummary     `json:"acp"`
	Builtin BuiltinSummary `json:"builtin"`
}

type SummaryOptions

type SummaryOptions struct {
	From        string
	To          string
	Limit       int
	Filters     map[string]string
	Attribution *AttributionFilter
}

type TimeseriesOptions

type TimeseriesOptions struct {
	From        string
	To          string
	Bucket      string
	GroupBy     string
	Filters     map[string]string
	Attribution *AttributionFilter
}

type UsageService

type UsageService struct {
	// contains filtered or unexported fields
}

func NewUsageService

func NewUsageService(pipeline Pipeline, query QueryService) *UsageService

func (*UsageService) AttachPrometheus

func (s *UsageService) AttachPrometheus(p PrometheusProvider)

AttachPrometheus registers the in-process Prometheus snapshot provider so the Admin API can expose an O(1) /metrics scrape.

func (*UsageService) Attribution

func (s *UsageService) Attribution() *AgentAttribution

Attribution returns the settable agent attribution holder. Callers inject the concrete attributor (the agent manager) after the gateway is bootstrapped, so the observer can stamp agent_id at write time.

func (*UsageService) Close

func (s *UsageService) Close() error

func (*UsageService) DroppedEvents

func (s *UsageService) DroppedEvents() uint64

func (*UsageService) Observer

func (s *UsageService) Observer() InteractionObserver

func (*UsageService) Prometheus

func (s *UsageService) Prometheus() PrometheusProvider

func (*UsageService) Query

func (s *UsageService) Query() QueryService

func (*UsageService) Start

func (s *UsageService) Start()

func (*UsageService) WriteFailures

func (s *UsageService) WriteFailures() uint64

Jump to

Keyboard shortcuts

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