Documentation
¶
Overview ¶
Copyright 2026 Teradata
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Package observability provides embedded trace storage for in-process observability.
EmbeddedTracer stores traces in-process using self-contained storage (memory or SQLite), providing high-performance tracing without external dependencies.
Copyright 2026 Teradata ¶
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Copyright 2026 Teradata ¶
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Copyright 2026 Teradata ¶
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Copyright 2026 Teradata ¶
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Copyright 2026 Teradata ¶
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Package observability provides distributed tracing and metrics for Loom agents.
Every operation in Loom is instrumented: LLM calls, tool executions, pattern selections, and full conversation flows. Traces are exported to Hawk (or other backends) for analysis, debugging, and cost attribution.
Example usage:
tracer := observability.NewHawkTracer(config)
ctx, span := tracer.StartSpan(ctx, "llm.completion")
defer tracer.EndSpan(span)
// ... do work ...
span.SetAttribute("llm.tokens", 1234)
Index ¶
- Constants
- func ContextWithSpan(ctx context.Context, span *Span) context.Context
- func ContextWithTraceID(ctx context.Context, traceID string) context.Context
- func TraceIDFromContext(ctx context.Context) string
- type AutoSelectConfig
- type EmbeddedConfig
- type EmbeddedTracer
- func (t *EmbeddedTracer) Close() error
- func (t *EmbeddedTracer) EndSpan(span *Span)
- func (t *EmbeddedTracer) Flush(ctx context.Context) error
- func (t *EmbeddedTracer) GetStorage() storage.Storage
- func (t *EmbeddedTracer) RecordEvent(ctx context.Context, name string, attributes map[string]interface{})
- func (t *EmbeddedTracer) RecordMetric(name string, value float64, labels map[string]string)
- func (t *EmbeddedTracer) SetEvalID(evalID string)
- func (t *EmbeddedTracer) StartSpan(ctx context.Context, name string, opts ...SpanOption) (context.Context, *Span)
- type EmbeddedTracerOption
- type Event
- type HawkConfig
- type HawkJudgeExporter
- type HawkJudgeExporterConfig
- type MockSpanExporter
- func (m *MockSpanExporter) ExportSpans(_ context.Context, spans []*Span) error
- func (m *MockSpanExporter) ForceFlush(_ context.Context) error
- func (m *MockSpanExporter) GetExportedSpans() []*Span
- func (m *MockSpanExporter) IsShutdown() bool
- func (m *MockSpanExporter) Reset()
- func (m *MockSpanExporter) SetExportError(err error)
- func (m *MockSpanExporter) Shutdown(_ context.Context) error
- type MockTracer
- func (m *MockTracer) EndSpan(span *Span)
- func (m *MockTracer) Flush(ctx context.Context) error
- func (m *MockTracer) GetSpanByName(name string) *Span
- func (m *MockTracer) GetSpans() []*Span
- func (m *MockTracer) GetSpansByName(name string) []*Span
- func (m *MockTracer) RecordEvent(ctx context.Context, name string, attributes map[string]interface{})
- func (m *MockTracer) RecordMetric(name string, value float64, labels map[string]string)
- func (m *MockTracer) Reset()
- func (m *MockTracer) StartSpan(ctx context.Context, name string, opts ...SpanOption) (context.Context, *Span)
- type NoOpTracer
- func (t *NoOpTracer) EndSpan(span *Span)
- func (t *NoOpTracer) Flush(ctx context.Context) error
- func (t *NoOpTracer) RecordEvent(ctx context.Context, name string, attributes map[string]interface{})
- func (t *NoOpTracer) RecordMetric(name string, value float64, labels map[string]string)
- func (t *NoOpTracer) StartSpan(ctx context.Context, name string, opts ...SpanOption) (context.Context, *Span)
- type PrivacyConfig
- type Span
- type SpanExporter
- type SpanOption
- type Status
- type StatusCode
- type Tracer
- type TracerMode
Constants ¶
const ( // Agent spans SpanAgentConversation = "agent.conversation" SpanAgentToolSelection = "agent.tool_selection" SpanAgentPatternMatch = "agent.pattern_match" SpanAgentSelfCorrection = "agent.self_correction" // LLM spans SpanLLMCompletion = "llm.completion" SpanLLMTokenize = "llm.tokenize" // #nosec G101 -- not a credential, just span name // Tool (shuttle) spans SpanToolExecute = "tool.execute" SpanToolValidate = "tool.validate" // Backend (fabric) spans SpanBackendQuery = "backend.query" SpanBackendConnect = "backend.connect" // Guardrail spans SpanGuardrailCheck = "guardrail.check" // Pattern spans SpanPatternLoad = "pattern.load" SpanPatternRender = "pattern.render" // MCP spans SpanMCPClientInitialize = "mcp.client.initialize" SpanMCPToolsList = "mcp.tools.list" SpanMCPToolsCall = "mcp.tools.call" SpanMCPResourcesList = "mcp.resources.list" SpanMCPResourcesRead = "mcp.resources.read" SpanMCPResourcesSubscribe = "mcp.resources.subscribe" SpanMCPPromptsList = "mcp.prompts.list" SpanMCPPromptsGet = "mcp.prompts.get" SpanMCPSamplingCreate = "mcp.sampling.create" // Workflow orchestration spans SpanWorkflowExecution = "workflow.execution" SpanDebateExecution = "workflow.debate" SpanDebateRound = "workflow.debate.round" SpanAgentExecution = "workflow.agent.execution" SpanForkJoinExecution = "workflow.fork_join" SpanPipelineExecution = "workflow.pipeline" SpanParallelExecution = "workflow.parallel" SpanConditionalExecution = "workflow.conditional" SpanMergeStrategy = "workflow.merge" // Collaboration pattern spans SpanSwarmExecution = "collaboration.swarm" SpanPairProgrammingExecution = "collaboration.pair_programming" SpanTeacherStudentExecution = "collaboration.teacher_student" // Judge evaluation spans SpanJudgeEvaluation = "judge.evaluation" SpanJudgeOrchestration = "judge.orchestration" SpanJudgeAggregation = "judge.aggregation" SpanHawkJudgeVerdictExport = "hawk.judge_verdict_export" // Teleprompter (DSPy-style) spans SpanTeleprompterCompile = "teleprompter.compile" SpanTeleprompterMetric = "teleprompter.metric" SpanTeleprompterBootstrap = "teleprompter.bootstrap" // Interrupt channel spans (4th communication channel) SpanInterruptSend = "interrupt.send" SpanInterruptBroadcast = "interrupt.broadcast" SpanInterruptHandle = "interrupt.handle" SpanInterruptEnqueue = "interrupt.enqueue" SpanInterruptRetry = "interrupt.retry" )
Standard span names for consistency across Loom. Use these constants instead of hardcoding strings.
const ( // Agent metrics MetricAgentConversations = "agent.conversations.total" MetricAgentConversationDuration = "agent.conversation.duration" MetricAgentSelfCorrections = "agent.self_corrections.total" // LLM metrics MetricLLMCalls = "llm.calls.total" MetricLLMLatency = "llm.latency" MetricLLMTokensInput = "llm.tokens.input" // #nosec G101 -- not a credential, just metric name MetricLLMTokensOutput = "llm.tokens.output" // #nosec G101 -- not a credential, just metric name MetricLLMCost = "llm.cost" MetricLLMErrors = "llm.errors.total" // Streaming metrics MetricLLMStreamingTTFT = "llm.streaming.ttft_ms" MetricLLMStreamingThroughput = "llm.streaming.throughput" MetricLLMStreamingChunks = "llm.streaming.chunks.total" // Tool metrics MetricToolExecutions = "tool.executions.total" MetricToolDuration = "tool.duration" MetricToolErrors = "tool.errors.total" // Guardrail metrics MetricGuardrailChecks = "guardrail.checks.total" MetricGuardrailBlocks = "guardrail.blocks.total" // MCP metrics MetricMCPCalls = "mcp.calls.total" MetricMCPDuration = "mcp.duration" MetricMCPErrors = "mcp.errors.total" // Interrupt channel metrics (4th communication channel) MetricInterruptSent = "interrupt.sent.total" MetricInterruptDelivered = "interrupt.delivered.total" MetricInterruptDropped = "interrupt.dropped.total" MetricInterruptQueued = "interrupt.queued.total" MetricInterruptRetried = "interrupt.retried.total" MetricInterruptLatency = "interrupt.latency_ms" MetricInterruptQueueSize = "interrupt.queue.size" )
Standard metric names for consistency.
const ( // Session/User context AttrSessionID = "session.id" AttrUserID = "user.id" AttrTraceID = "trace.id" AttrSpanID = "span.id" // LLM attributes AttrLLMProvider = "llm.provider" AttrLLMModel = "llm.model" AttrLLMTemperature = "llm.temperature" AttrLLMMaxTokens = "llm.max_tokens" // #nosec G101 -- not a credential, just attribute name // Streaming attributes AttrLLMStreaming = "llm.streaming" AttrLLMTTFT = "llm.ttft_ms" AttrLLMThroughput = "llm.streaming.throughput" // Tool attributes AttrToolName = "tool.name" AttrToolArgs = "tool.args" // Backend attributes AttrBackendType = "backend.type" AttrBackendHost = "backend.host" // Error attributes AttrErrorType = "error.type" AttrErrorMessage = "error.message" AttrErrorStack = "error.stack" // Prompt attributes AttrPromptKey = "prompt.key" AttrPromptVariant = "prompt.variant" AttrPromptVersion = "prompt.version" // Pattern attributes AttrPatternName = "pattern.name" AttrPatternCategory = "pattern.category" // MCP attributes AttrMCPServerName = "mcp.server.name" AttrMCPOperation = "mcp.operation" AttrMCPToolName = "mcp.tool.name" AttrMCPResourceURI = "mcp.resource.uri" AttrMCPPromptName = "mcp.prompt.name" AttrMCPProtocolVersion = "mcp.protocol.version" // Judge attributes AttrJudgeName = "judge.name" AttrJudgeCriticality = "judge.criticality" AttrJudgeVerdict = "judge.verdict" AttrJudgeScore = "judge.score" // Interrupt channel attributes (4th communication channel) AttrInterruptSignal = "interrupt.signal" AttrInterruptPriority = "interrupt.priority" AttrInterruptTarget = "interrupt.target" AttrInterruptSender = "interrupt.sender" AttrInterruptPath = "interrupt.path" // "fast" or "slow" AttrInterruptDelivered = "interrupt.delivered" // boolean AttrInterruptRetries = "interrupt.retries" // retry count AttrInterruptQueueID = "interrupt.queue.id" // persistent queue ID )
Standard attribute names for consistency. Use these constants for span and event attributes.
const ( ResourceAttrServiceName = "service.name" ResourceAttrServiceVersion = "service.version" ResourceAttrUserID = AttrUserID // "user.id" — same key as span attribute ResourceAttrSessionID = AttrSessionID // "session.id" — same key as span attribute ResourceAttrAgentID = "agent.id" )
Resource attribute keys for standard fields. Keys that overlap with span attributes (AttrUserID, AttrSessionID) are aliased here so callers can use the ResourceAttr* prefix consistently when setting resource-level metadata.
Variables ¶
This section is empty.
Functions ¶
func ContextWithSpan ¶
ContextWithSpan returns a new context with the span attached.
func ContextWithTraceID ¶ added in v1.3.0
ContextWithTraceID returns a new context with an explicit trace ID. When StartSpan creates a root span (no parent span in context), it will use this trace ID instead of generating a new one. If a parent span exists in the context, the parent's trace ID takes priority and this value is ignored.
func TraceIDFromContext ¶ added in v1.3.0
TraceIDFromContext retrieves the current trace ID from context, if any. Returns empty string if no span (and thus no trace) exists in context.
Types ¶
type AutoSelectConfig ¶
type AutoSelectConfig struct {
// Mode: "auto", "service", "embedded", or "none"
// If "auto", selects based on HawkURL presence and PreferEmbedded flag
Mode TracerMode
// PreferEmbedded: When Mode=auto, prefer embedded over service if both are available
PreferEmbedded bool
// HawkURL: Service endpoint (for service mode)
HawkURL string
// HawkAPIKey: Authentication for service mode
HawkAPIKey string
// EmbeddedStorageType: "memory" or "sqlite" (for embedded mode)
EmbeddedStorageType string
// EmbeddedSQLitePath: Path to SQLite database (required if EmbeddedStorageType="sqlite")
EmbeddedSQLitePath string
// Logger for tracer operations
Logger *zap.Logger
// Privacy settings (for service mode)
Privacy *PrivacyConfig
}
AutoSelectConfig provides configuration for automatic tracer selection
type EmbeddedConfig ¶
type EmbeddedConfig struct {
// StorageType: "memory" (default) or "sqlite"
StorageType string
// SQLitePath: Path to SQLite database file (required if StorageType = "sqlite")
SQLitePath string
// MaxMemoryTraces: Maximum traces to keep in memory storage (default: 10,000)
MaxMemoryTraces int
// Logger for embedded tracer (optional)
Logger *zap.Logger
// FlushInterval: How often to flush metrics (default: 30s)
FlushInterval time.Duration
}
EmbeddedConfig configures the embedded tracer
func DefaultEmbeddedConfig ¶
func DefaultEmbeddedConfig() *EmbeddedConfig
DefaultEmbeddedConfig returns sensible defaults for embedded mode
type EmbeddedTracer ¶ added in v1.1.0
type EmbeddedTracer struct {
// contains filtered or unexported fields
}
EmbeddedTracer implements Tracer interface using embedded storage
func NewEmbeddedHawkTracer ¶
func NewEmbeddedHawkTracer(config *EmbeddedConfig) (*EmbeddedTracer, error)
NewEmbeddedHawkTracer is deprecated - use NewEmbeddedTracer instead. Kept for backward compatibility.
func NewEmbeddedTracer ¶ added in v1.1.0
func NewEmbeddedTracer(config *EmbeddedConfig, opts ...EmbeddedTracerOption) (*EmbeddedTracer, error)
NewEmbeddedTracer creates a new embedded tracer with in-process storage. Options can be used to attach a SpanExporter or set default resource attributes.
func (*EmbeddedTracer) Close ¶ added in v1.1.0
func (t *EmbeddedTracer) Close() error
Close shuts down the embedded tracer
func (*EmbeddedTracer) EndSpan ¶ added in v1.1.0
func (t *EmbeddedTracer) EndSpan(span *Span)
EndSpan completes a tracing span and stores it. The span exporter is called after releasing the lock to avoid blocking concurrent StartSpan/EndSpan calls during potentially slow network I/O.
func (*EmbeddedTracer) Flush ¶ added in v1.1.0
func (t *EmbeddedTracer) Flush(ctx context.Context) error
Flush forces a metrics update for the current evaluation
func (*EmbeddedTracer) GetStorage ¶ added in v1.1.0
func (t *EmbeddedTracer) GetStorage() storage.Storage
GetStorage returns the underlying storage (for testing/inspection)
func (*EmbeddedTracer) RecordEvent ¶ added in v1.1.0
func (t *EmbeddedTracer) RecordEvent(ctx context.Context, name string, attributes map[string]interface{})
RecordEvent records a standalone event
func (*EmbeddedTracer) RecordMetric ¶ added in v1.1.0
func (t *EmbeddedTracer) RecordMetric(name string, value float64, labels map[string]string)
RecordMetric records a point-in-time metric
func (*EmbeddedTracer) SetEvalID ¶ added in v1.1.0
func (t *EmbeddedTracer) SetEvalID(evalID string)
SetEvalID sets the current evaluation ID for grouping traces
func (*EmbeddedTracer) StartSpan ¶ added in v1.1.0
func (t *EmbeddedTracer) StartSpan(ctx context.Context, name string, opts ...SpanOption) (context.Context, *Span)
StartSpan creates a new tracing span
type EmbeddedTracerOption ¶ added in v1.3.0
type EmbeddedTracerOption func(*EmbeddedTracer)
EmbeddedTracerOption configures an EmbeddedTracer.
func WithDefaultResourceAttributes ¶ added in v1.3.0
func WithDefaultResourceAttributes(attrs map[string]string) EmbeddedTracerOption
WithDefaultResourceAttributes sets resource attributes that are automatically applied to every span created by this tracer.
func WithSpanExporter ¶ added in v1.3.0
func WithSpanExporter(exporter SpanExporter) EmbeddedTracerOption
WithSpanExporter attaches a SpanExporter to the EmbeddedTracer. The exporter receives completed spans on EndSpan in addition to the embedded storage. This enables exporting spans to external systems (e.g., PostgreSQL via CloudSpanExporter) while keeping local storage.
type Event ¶
Event represents a point-in-time occurrence within a span. Use for logging important events during span execution.
type HawkConfig ¶
type HawkConfig struct {
// Endpoint is the Hawk API endpoint for trace export.
// Example: "http://localhost:8080/v1/traces"
Endpoint string
// APIKey for authentication with Hawk.
APIKey string
// BatchSize is the number of spans to buffer before flushing.
// Default: 100
BatchSize int
// FlushInterval is how often to flush buffered spans.
// Default: 10s
FlushInterval time.Duration
// MaxRetries is the maximum number of retry attempts for failed exports.
// Default: 3
MaxRetries int
// RetryBackoff is the initial backoff duration for retries.
// Default: 1s (doubles with each retry: 1s, 2s, 4s, 8s...)
RetryBackoff time.Duration
// Privacy controls PII redaction.
Privacy PrivacyConfig
// HTTPClient for custom transport (e.g., timeouts, proxies).
// If nil, uses http.DefaultClient.
HTTPClient *http.Client
}
HawkConfig configures the Hawk tracer. This type is always available, but the actual HawkTracer implementation requires building with -tags hawk.
type HawkJudgeExporter ¶
type HawkJudgeExporter struct {
}
HawkJudgeExporter is defined here for type checking, but the actual implementation is in hawk_judge_exporter.go (requires -tags hawk). When built without -tags hawk, stub methods are provided in hawk_judge_exporter_stub.go.
func NewHawkJudgeExporter ¶
func NewHawkJudgeExporter(config *HawkJudgeExporterConfig) (*HawkJudgeExporter, error)
NewHawkJudgeExporter returns an error when built without hawk build tag. To enable Hawk judge export support, build with: go build -tags hawk
func (*HawkJudgeExporter) ExportJudgeResult ¶
func (e *HawkJudgeExporter) ExportJudgeResult(ctx context.Context, result *loomv1.JudgeResult) error
ExportJudgeResult returns an error when built without hawk build tag.
func (*HawkJudgeExporter) Start ¶
func (e *HawkJudgeExporter) Start(ctx context.Context)
Start is a no-op when built without hawk build tag.
type HawkJudgeExporterConfig ¶
type HawkJudgeExporterConfig struct {
// Endpoint is the Hawk API endpoint (default: HAWK_ENDPOINT env or http://localhost:8080)
Endpoint string
// APIKey for authentication (default: HAWK_API_KEY env)
APIKey string
// BatchSize is the number of verdicts to batch before sending (default: 10)
BatchSize int
// FlushInterval is the max time between flushes (default: 5s)
FlushInterval time.Duration
// BufferSize is the size of the verdict buffer channel (default: 100)
BufferSize int
// Timeout for HTTP requests (default: 10s)
Timeout time.Duration
// Logger for diagnostic output (default: nop logger)
Logger *zap.Logger
// Tracer for observability (default: nop tracer)
Tracer Tracer
}
HawkJudgeExporterConfig configures the Hawk judge verdict exporter. This type is always available, but the actual HawkJudgeExporter implementation requires building with -tags hawk.
type MockSpanExporter ¶ added in v1.3.0
type MockSpanExporter struct {
// contains filtered or unexported fields
}
MockSpanExporter is a test implementation of SpanExporter that captures exported spans. Thread-safe: All methods can be called concurrently.
func NewMockSpanExporter ¶ added in v1.3.0
func NewMockSpanExporter() *MockSpanExporter
NewMockSpanExporter creates a new mock span exporter for testing.
func (*MockSpanExporter) ExportSpans ¶ added in v1.3.0
func (m *MockSpanExporter) ExportSpans(_ context.Context, spans []*Span) error
ExportSpans captures the spans for inspection.
func (*MockSpanExporter) ForceFlush ¶ added in v1.3.0
func (m *MockSpanExporter) ForceFlush(_ context.Context) error
ForceFlush is a no-op for the mock exporter (all exports are synchronous).
func (*MockSpanExporter) GetExportedSpans ¶ added in v1.3.0
func (m *MockSpanExporter) GetExportedSpans() []*Span
GetExportedSpans returns all exported spans (for testing).
func (*MockSpanExporter) IsShutdown ¶ added in v1.3.0
func (m *MockSpanExporter) IsShutdown() bool
IsShutdown returns whether Shutdown was called (for testing).
func (*MockSpanExporter) Reset ¶ added in v1.3.0
func (m *MockSpanExporter) Reset()
Reset clears all captured spans and state (for testing).
func (*MockSpanExporter) SetExportError ¶ added in v1.3.0
func (m *MockSpanExporter) SetExportError(err error)
SetExportError sets an error to be returned by ExportSpans (for testing).
type MockTracer ¶
type MockTracer struct {
// contains filtered or unexported fields
}
MockTracer is a test implementation of Tracer that captures all spans for inspection. Thread-safe: All methods can be called concurrently.
func NewMockTracer ¶
func NewMockTracer() *MockTracer
NewMockTracer creates a new mock tracer for testing.
func (*MockTracer) EndSpan ¶
func (m *MockTracer) EndSpan(span *Span)
EndSpan completes a span and stores it.
func (*MockTracer) Flush ¶
func (m *MockTracer) Flush(ctx context.Context) error
Flush is a no-op for mock tracer.
func (*MockTracer) GetSpanByName ¶
func (m *MockTracer) GetSpanByName(name string) *Span
GetSpanByName finds the first span with the given name (for testing).
func (*MockTracer) GetSpans ¶
func (m *MockTracer) GetSpans() []*Span
GetSpans returns all captured spans (for testing).
func (*MockTracer) GetSpansByName ¶
func (m *MockTracer) GetSpansByName(name string) []*Span
GetSpansByName finds all spans with the given name (for testing).
func (*MockTracer) RecordEvent ¶
func (m *MockTracer) RecordEvent(ctx context.Context, name string, attributes map[string]interface{})
RecordEvent records a standalone event (captured but not stored in mock).
func (*MockTracer) RecordMetric ¶
func (m *MockTracer) RecordMetric(name string, value float64, labels map[string]string)
RecordMetric records a metric (captured but not stored in mock).
func (*MockTracer) Reset ¶
func (m *MockTracer) Reset()
Reset clears all captured spans (for testing).
func (*MockTracer) StartSpan ¶
func (m *MockTracer) StartSpan(ctx context.Context, name string, opts ...SpanOption) (context.Context, *Span)
StartSpan creates a new span and stores it for inspection.
type NoOpTracer ¶
type NoOpTracer struct{}
NoOpTracer is a tracer that does nothing. Use for testing or when observability is disabled.
func (*NoOpTracer) Flush ¶
func (t *NoOpTracer) Flush(ctx context.Context) error
Flush does nothing.
func (*NoOpTracer) RecordEvent ¶
func (t *NoOpTracer) RecordEvent(ctx context.Context, name string, attributes map[string]interface{})
RecordEvent does nothing.
func (*NoOpTracer) RecordMetric ¶
func (t *NoOpTracer) RecordMetric(name string, value float64, labels map[string]string)
RecordMetric does nothing.
func (*NoOpTracer) StartSpan ¶
func (t *NoOpTracer) StartSpan(ctx context.Context, name string, opts ...SpanOption) (context.Context, *Span)
StartSpan creates a minimal span but doesn't export it.
type PrivacyConfig ¶
type PrivacyConfig struct {
// RedactCredentials removes password, api_key, token fields from spans.
RedactCredentials bool
// RedactPII removes email, phone, SSN patterns from attribute values.
RedactPII bool
// AllowedAttributes is a whitelist of attribute keys that bypass redaction.
// Example: []string{"session.id", "llm.model", "tool.name"}
AllowedAttributes []string
}
PrivacyConfig controls what data is redacted before export.
type Span ¶
type Span struct {
// Identifiers
TraceID string // Unique ID for entire trace
SpanID string // Unique ID for this span
ParentID string // Parent span ID (empty for root)
// Metadata
Name string // Operation name (e.g., "llm.completion")
Attributes map[string]interface{} // Key-value metadata
// ResourceAttributes describe the entity producing spans (service.name, user.id, etc.).
// These are carried on every span and used by exporters to route/tag data.
ResourceAttributes map[string]string
// Timing
StartTime time.Time
EndTime time.Time
Duration time.Duration // Calculated on EndSpan
// Events and status
Events []Event
Status Status
}
Span represents a unit of work with timing and metadata. Spans form a tree structure via ParentID references.
func SpanFromContext ¶
SpanFromContext retrieves the current span from context, if any. Returns nil if no span exists in context.
func (*Span) RecordError ¶
RecordError records an error on the span. Sets status to StatusError and adds error attributes.
func (*Span) SetAttribute ¶
SetAttribute sets a key-value attribute on the span.
func (*Span) SetResourceAttribute ¶ added in v1.3.0
SetResourceAttribute sets a single resource attribute on the span.
type SpanExporter ¶ added in v1.3.0
type SpanExporter interface {
// ExportSpans sends a batch of completed spans to the external store.
// Called by the tracer on EndSpan (or on flush for batched exporters).
ExportSpans(ctx context.Context, spans []*Span) error
// ForceFlush requests the exporter to flush any buffered spans immediately.
// Returns when the flush completes or the context is cancelled.
ForceFlush(ctx context.Context) error
// Shutdown gracefully shuts down the exporter, flushing any buffered spans.
Shutdown(ctx context.Context) error
}
SpanExporter exports completed spans to an external store (e.g., PostgreSQL). Implementations must be goroutine-safe.
The tracer calls ExportSpans synchronously on each EndSpan with a single-span batch. Implementations that buffer spans internally should flush on ForceFlush and drain remaining spans on Shutdown.
type SpanOption ¶
type SpanOption func(*Span)
SpanOption is a functional option for configuring spans.
func WithAttribute ¶
func WithAttribute(key string, value interface{}) SpanOption
WithAttribute returns a SpanOption that sets an attribute.
func WithParentSpanID ¶
func WithParentSpanID(parentID string) SpanOption
WithParentSpanID returns a SpanOption that explicitly sets the parent span ID.
func WithResourceAttributes ¶ added in v1.3.0
func WithResourceAttributes(attrs map[string]string) SpanOption
WithResourceAttributes returns a SpanOption that sets resource attributes on the span. Resource attributes describe the entity producing spans (e.g., service.name, user.id).
func WithSpanKind ¶
func WithSpanKind(kind string) SpanOption
WithSpanKind returns a SpanOption that sets the span.kind attribute. Common values: "conversation", "llm", "tool", "backend", "guardrail"
type Status ¶
type Status struct {
Code StatusCode
Message string
}
Status represents the final status of a span with optional message.
type StatusCode ¶
type StatusCode int
StatusCode represents the final status of a span.
const ( // StatusUnset indicates status was not explicitly set. StatusUnset StatusCode = iota // StatusOK indicates successful completion. StatusOK // StatusError indicates an error occurred. StatusError )
func (StatusCode) String ¶
func (s StatusCode) String() string
type Tracer ¶
type Tracer interface {
// StartSpan creates a new span and returns a context containing it.
// The span is automatically linked to its parent via context propagation.
//
// Example:
// ctx, span := tracer.StartSpan(ctx, "llm.completion",
// WithAttribute("llm.model", "claude-3-5-sonnet"))
// defer tracer.EndSpan(span)
StartSpan(ctx context.Context, name string, opts ...SpanOption) (context.Context, *Span)
// EndSpan completes a span, calculates duration, and exports it.
// Always call this via defer after StartSpan.
EndSpan(span *Span)
// RecordMetric records a point-in-time metric value with labels.
// Use for counters, gauges, histograms (e.g., token counts, costs, latencies).
//
// Example:
// tracer.RecordMetric("llm.tokens.input", 1234, map[string]string{
// "provider": "anthropic",
// "model": "claude-3-5-sonnet",
// })
RecordMetric(name string, value float64, labels map[string]string)
// RecordEvent records a standalone event not tied to a span.
// Use sparingly - most events should be span.AddEvent().
RecordEvent(ctx context.Context, name string, attributes map[string]interface{})
// Flush forces immediate export of buffered traces and metrics.
// Blocks until export completes or times out.
// Automatically called on graceful shutdown.
Flush(ctx context.Context) error
}
Tracer is the main interface for instrumenting Loom operations.
Implementations export traces to observability backends (Hawk, OTLP, etc.) or provide no-op tracing for testing.
Thread-safe: All methods can be called concurrently.
func NewAutoSelectTracer ¶
func NewAutoSelectTracer(config *AutoSelectConfig) (Tracer, error)
NewAutoSelectTracer creates a tracer based on auto-selection logic
Selection Priority (when Mode=auto): 1. If PreferEmbedded=true: embedded → service → none 2. If PreferEmbedded=false: service → embedded → none
Embedded is available when: - EmbeddedStorageType is set - If SQLite, EmbeddedSQLitePath is provided
Service is available when: - HawkURL is set - HawkAPIKey is set (optional but recommended)
func NewAutoSelectTracerFromEnv ¶
NewAutoSelectTracerFromEnv creates a tracer using environment variables
Environment Variables: - LOOM_TRACER_MODE: "auto", "service", "embedded", or "none" (default: "auto") - LOOM_TRACER_PREFER_EMBEDDED: "true" or "false" (default: "true") - HAWK_URL: Service endpoint (for service mode) - HAWK_API_KEY: Service authentication (for service mode) - LOOM_EMBEDDED_STORAGE: "memory" or "sqlite" (default: "memory") - LOOM_EMBEDDED_SQLITE_PATH: Path to SQLite database (required if storage=sqlite)
Example:
# Use embedded memory storage (fast, non-persistent) export LOOM_TRACER_MODE=embedded export LOOM_EMBEDDED_STORAGE=memory # Use embedded SQLite storage (persistent) export LOOM_TRACER_MODE=embedded export LOOM_EMBEDDED_STORAGE=sqlite export LOOM_EMBEDDED_SQLITE_PATH=/tmp/loom-traces.db # Use Hawk service export LOOM_TRACER_MODE=service export HAWK_URL=http://localhost:8090 export HAWK_API_KEY=your-key # Auto-select (prefer embedded if both available) export LOOM_TRACER_MODE=auto export LOOM_TRACER_PREFER_EMBEDDED=true export LOOM_EMBEDDED_STORAGE=memory export HAWK_URL=http://localhost:8090
func NewHawkTracer ¶
func NewHawkTracer(config HawkConfig) (Tracer, error)
NewHawkTracer returns an error when built without hawk build tag. To enable Hawk HTTP export support, build with: go build -tags hawk Note: Embedded tracing (NewEmbeddedTracer) is always available without build tags.
type TracerMode ¶
type TracerMode string
TracerMode specifies which tracer implementation to use
const ( // TracerModeAuto automatically selects best tracer based on environment TracerModeAuto TracerMode = "auto" // TracerModeService uses Hawk service (gRPC) TracerModeService TracerMode = "service" // TracerModeEmbedded uses embedded Hawk storage (memory or SQLite) TracerModeEmbedded TracerMode = "embedded" // TracerModeNone disables tracing TracerModeNone TracerMode = "none" )