otel

package
v0.0.0-...-80ccc60 Latest Latest
Warning

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

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

Documentation

Overview

Package otel provides OpenTelemetry instrumentation for Deputy. It handles SDK initialization, shutdown, and provides helpers for traces, metrics, and log correlation.

Package otel provides OpenTelemetry instrumentation for Deputy.

This package handles initialization and configuration of OpenTelemetry tracing and metrics. When enabled, it exports telemetry data to an OTLP-compatible collector.

Configuration

Enable OpenTelemetry via environment variables:

export DEPUTY_OTEL_ENABLED=true
export OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317

Or via configuration file (.deputy.yaml):

otel:
  enabled: true
  endpoint: localhost:4317
  insecure: true

Initialization

Initialize OpenTelemetry early in program startup:

provider, err := otel.Init(ctx, cfg)
if err != nil {
    log.Warn("failed to initialize OpenTelemetry", "error", err)
}
defer provider.Shutdown(context.Background())

Creating Spans

Use StartSpan to create traced operations:

ctx, span := otel.StartSpan(ctx, "deputy.scan",
    trace.WithAttributes(
        attribute.String("target", target),
    ))
defer span.End()

// ... do work ...

otel.SetSpanOK(span)  // or otel.SetSpanError(span, err)

HTTP Instrumentation

Wrap HTTP handlers for automatic tracing:

handler := otel.WrapHandler(myHandler, "my-handler")

Checking Status

Check if OpenTelemetry is enabled:

if otel.IsEnabled() {
    // Include trace context in logs
}

Index

Constants

View Source
const (
	// MeterName is the default meter name for Deputy metrics.
	MeterName = "github.com/temporalio/deputy"
)
View Source
const (
	// TracerName is the default tracer name for Deputy spans.
	TracerName = "github.com/temporalio/deputy"
)

Variables

View Source
var (
	// Ecosystem attributes - using deputy.ecosystem for consistency with traces
	AttrEcosystemGo    = attribute.String("deputy.ecosystem", "go")
	AttrEcosystemNpm   = attribute.String("deputy.ecosystem", "npm")
	AttrEcosystemPyPI  = attribute.String("deputy.ecosystem", "pypi")
	AttrEcosystemRuby  = attribute.String("deputy.ecosystem", "ruby")
	AttrEcosystemCargo = attribute.String("deputy.ecosystem", "cargo")
	AttrEcosystemMaven = attribute.String("deputy.ecosystem", "maven")
	AttrEcosystemNuget = attribute.String("deputy.ecosystem", "nuget")

	// Severity attributes
	AttrSeverityCritical = attribute.String("severity", "CRITICAL")
	AttrSeverityHigh     = attribute.String("severity", "HIGH")
	AttrSeverityMedium   = attribute.String("severity", "MEDIUM")
	AttrSeverityLow      = attribute.String("severity", "LOW")
	AttrSeverityUnknown  = attribute.String("severity", "UNKNOWN")

	// Status attributes
	AttrStatusSuccess = attribute.String("status", "success")
	AttrStatusError   = attribute.String("status", "error")

	// Policy result attributes
	AttrPolicyResultAllow = attribute.String("result", "allow")
	AttrPolicyResultDeny  = attribute.String("result", "deny")
	AttrPolicyResultWarn  = attribute.String("result", "warn")

	// Auth result attributes
	AttrAuthResultSuccess   = attribute.String("result", "success")
	AttrAuthResultAnonymous = attribute.String("result", "anonymous")
	AttrAuthResultRejected  = attribute.String("result", "rejected")

	// Cache type attributes - using deputy.cache.type for consistency with trace attributes
	AttrCacheTypeOSV     = attribute.String("deputy.cache.type", "osv")
	AttrCacheTypeKEV     = attribute.String("deputy.cache.type", "kev")
	AttrCacheTypeEPSS    = attribute.String("deputy.cache.type", "epss")
	AttrCacheTypeLicense = attribute.String("deputy.cache.type", "license")
	AttrCacheTypeDisk    = attribute.String("deputy.cache.type", "disk")
	AttrCacheTypeImage   = attribute.String("deputy.cache.type", "image_scan")
	AttrCacheTypeDepsDev = attribute.String("deputy.cache.type", "depsdev")
	AttrCacheTypeGoProxy = attribute.String("deputy.cache.type", "goproxy")
	AttrCacheTypeGraph   = attribute.String("deputy.cache.type", "graph")
	AttrCacheTypeGit     = attribute.String("deputy.cache.type", "git")

	// Image transport attributes for container image scans
	AttrImageTransportRemote    = attribute.String("deputy.image.transport", "remote")
	AttrImageTransportDaemon    = attribute.String("deputy.image.transport", "docker-daemon")
	AttrImageTransportTarball   = attribute.String("deputy.image.transport", "tarball")
	AttrImageTransportOCILayout = attribute.String("deputy.image.transport", "oci-layout")

	// Sandbox runtime attributes
	AttrSandboxRuntimeNone        = attribute.String("deputy.sandbox.runtime", "none")
	AttrSandboxRuntimeDocker      = attribute.String("deputy.sandbox.runtime", "docker")
	AttrSandboxRuntimeGVisor      = attribute.String("deputy.sandbox.runtime", "gvisor")
	AttrSandboxRuntimeSandboxExec = attribute.String("deputy.sandbox.runtime", "sandbox-exec")
	AttrSandboxRuntimePlugin      = attribute.String("deputy.sandbox.runtime", "plugin")

	// Sandbox network mode attributes
	AttrSandboxNetworkNone      = attribute.String("deputy.sandbox.network_mode", "none")
	AttrSandboxNetworkHost      = attribute.String("deputy.sandbox.network_mode", "host")
	AttrSandboxNetworkBridge    = attribute.String("deputy.sandbox.network_mode", "bridge")
	AttrSandboxNetworkAllowlist = attribute.String("deputy.sandbox.network_mode", "allowlist")

	// Sandbox workspace isolation attributes
	AttrSandboxIsolationDirect   = attribute.String("deputy.sandbox.workspace_isolation", "direct")
	AttrSandboxIsolationOverlay  = attribute.String("deputy.sandbox.workspace_isolation", "overlay")
	AttrSandboxIsolationSnapshot = attribute.String("deputy.sandbox.workspace_isolation", "snapshot")
	AttrSandboxIsolationTmpfs    = attribute.String("deputy.sandbox.workspace_isolation", "tmpfs")
)

Common attribute values for metrics. Note: Attribute keys use the "deputy." namespace to match trace attributes for cross-signal correlation. The OTel SDK automatically converts dots to underscores for Prometheus export (e.g., "deputy.ecosystem" -> "deputy_ecosystem").

View Source
var (
	// Command attributes
	AttrCommand      = attribute.Key("deputy.command")
	AttrSubcommand   = attribute.Key("deputy.subcommand")
	AttrTargetPath   = attribute.Key("deputy.target.path")
	AttrTargetRef    = attribute.Key("deputy.target.ref")
	AttrTargetRemote = attribute.Key("deputy.target.remote")

	// Scan attributes
	AttrEcosystem             = attribute.Key("deputy.ecosystem")
	AttrPackageCount          = attribute.Key("deputy.package.count")
	AttrVulnerabilityCount    = attribute.Key("deputy.vulnerability.count")
	AttrVulnerabilityCritical = attribute.Key("deputy.vulnerability.critical")
	AttrVulnerabilityHigh     = attribute.Key("deputy.vulnerability.high")
	AttrVulnerabilityMedium   = attribute.Key("deputy.vulnerability.medium")
	AttrVulnerabilityLow      = attribute.Key("deputy.vulnerability.low")
	AttrDirectDepsOnly        = attribute.Key("deputy.direct_deps_only")
	AttrPolicyEvaluated       = attribute.Key("deputy.policy.evaluated")
	AttrPolicyPassed          = attribute.Key("deputy.policy.passed")

	// OSV attributes
	AttrOSVBatchSize           = attribute.Key("deputy.osv.batch_size")
	AttrOSVCacheHit            = attribute.Key("deputy.osv.cache_hit")
	AttrOSVVulnerabilityID     = attribute.Key("deputy.osv.vulnerability_id")
	AttrOSVQueryType           = attribute.Key("deputy.osv.query_type")
	AttrOSVResponseLen         = attribute.Key("deputy.osv.response_len")
	AttrOSVDroppedNoVersion    = attribute.Key("deputy.osv.dropped_no_version")
	AttrOSVDroppedNoIdentifier = attribute.Key("deputy.osv.dropped_no_identifier")

	// Policy attributes
	AttrPolicyName       = attribute.Key("deputy.policy.name")
	AttrPolicyAction     = attribute.Key("deputy.policy.action")
	AttrPolicyEntrypoint = attribute.Key("deputy.policy.entrypoint")

	// Proxy attributes
	AttrProxyListener  = attribute.Key("deputy.proxy.listener")
	AttrProxyUpstream  = attribute.Key("deputy.proxy.upstream")
	AttrProxyPackage   = attribute.Key("deputy.proxy.package")
	AttrProxyVersion   = attribute.Key("deputy.proxy.version")
	AttrProxyOperation = attribute.Key("deputy.proxy.operation")
	AttrProxyBlocked   = attribute.Key("deputy.proxy.blocked")

	// Auth attributes
	AttrAuthMode      = attribute.Key("deputy.auth.mode")
	AttrAuthResult    = attribute.Key("deputy.auth.result")
	AttrAuthSubject   = attribute.Key("deputy.auth.subject")
	AttrAuthErrorCode = attribute.Key("deputy.auth.error_code")

	// Cache attributes
	AttrCacheType = attribute.Key("deputy.cache.type")
	AttrCacheHit  = attribute.Key("deputy.cache.hit")
	AttrCacheKey  = attribute.Key("deputy.cache.key")

	// MCP attributes
	AttrMCPTool               = attribute.Key("deputy.mcp.tool")
	AttrMCPVulnerabilityID    = attribute.Key("deputy.mcp.vulnerability_id")
	AttrMCPVulnerabilityCount = attribute.Key("deputy.mcp.vulnerability_count")
	AttrMCPPackageCount       = attribute.Key("deputy.mcp.package_count")
	AttrMCPImage              = attribute.Key("deputy.mcp.image")
	AttrMCPBaseRef            = attribute.Key("deputy.mcp.base_ref")
	AttrMCPTargetRef          = attribute.Key("deputy.mcp.target_ref")
	AttrMCPChangeCount        = attribute.Key("deputy.mcp.change_count")
	AttrMCPTriageCount        = attribute.Key("deputy.mcp.triage_count")
	AttrMCPGraphPackage       = attribute.Key("deputy.mcp.graph_package")
	AttrMCPGraphFound         = attribute.Key("deputy.mcp.graph_found")
	AttrMCPGraphDirect        = attribute.Key("deputy.mcp.graph_direct")
	AttrMCPGraphPathCount     = attribute.Key("deputy.mcp.graph_path_count")
)

Common attribute keys for Deputy spans.

Functions

func AddSpanEvent

func AddSpanEvent(span trace.Span, name string, attrs ...attribute.KeyValue)

AddSpanEvent adds an event to the span with optional attributes. Use events for discrete occurrences within a span (e.g., cache hits, policy evaluations). For continuous data, use span attributes instead.

func CacheTypeAttr

func CacheTypeAttr(cacheType string) attribute.KeyValue

CacheTypeAttr returns a cache type attribute for the given cache name.

func ClientSpanNameFormatter

func ClientSpanNameFormatter(service string) func(string, *http.Request) string

ClientSpanNameFormatter returns a span name formatter for outgoing HTTP client requests.

func EcosystemAttr

func EcosystemAttr(ecosystem string) attribute.KeyValue

EcosystemAttr returns an ecosystem attribute for the given ecosystem string. Uses "deputy.ecosystem" key for consistency with trace attributes.

func ImageTransportAttr

func ImageTransportAttr(transport string) attribute.KeyValue

ImageTransportAttr returns an image transport attribute for the given transport string.

func InstrumentedHandler

func InstrumentedHandler(handler http.Handler, operation string, opts ...otelhttp.Option) http.Handler

InstrumentedHandler wraps an http.Handler with OpenTelemetry tracing. Creates server spans for incoming HTTP requests.

func InstrumentedMiddleware

func InstrumentedMiddleware(operation string, opts ...otelhttp.Option) func(http.Handler) http.Handler

InstrumentedMiddleware returns middleware that wraps handlers with OTel tracing.

func InstrumentedTransport

func InstrumentedTransport(base http.RoundTripper, opts ...otelhttp.Option) http.RoundTripper

InstrumentedTransport wraps an http.RoundTripper with OpenTelemetry tracing. Creates client spans for outgoing HTTP requests with proper context propagation.

func IsEnabled

func IsEnabled() bool

IsEnabled reports whether the global provider is enabled.

func LogWithTrace

func LogWithTrace(ctx context.Context) []any

LogWithTrace creates log attributes for trace context. Useful for manually adding trace context to log calls.

func Meter

func Meter(name string) metric.Meter

Meter returns a named meter for recording metrics. Returns a no-op meter if OTel is disabled.

func NewOTelHandler

func NewOTelHandler(name string) slog.Handler

NewOTelHandler creates an slog handler that exports logs via OpenTelemetry. The handler sends logs to the configured OTel collector endpoint. Use this as a base handler wrapped with TraceContextHandler for full correlation.

func ProxySpanNameFormatter

func ProxySpanNameFormatter(ecosystem string) func(string, *http.Request) string

ProxySpanNameFormatter returns a span name formatter suitable for proxy requests.

func RecordCacheAccess

func RecordCacheAccess(span trace.Span, cacheType string, hit bool, key string)

RecordCacheAccess adds a cache access event to a span.

func RecordCacheEviction

func RecordCacheEviction(ctx context.Context, cacheType string)

RecordCacheEviction records a single cache eviction event.

func RecordCacheExpiration

func RecordCacheExpiration(ctx context.Context, cacheType string)

RecordCacheExpiration records a single cache expiration event.

func RecordCacheHit

func RecordCacheHit(ctx context.Context, cacheType string)

RecordCacheHit records a single cache hit event.

func RecordCacheMiss

func RecordCacheMiss(ctx context.Context, cacheType string)

RecordCacheMiss records a single cache miss event.

func RecordCacheStats

func RecordCacheStats(ctx context.Context, cacheType string, stats CacheStats)

RecordCacheStats records cache statistics for a named cache. The cacheType parameter should identify the cache (e.g., "depsdev", "goproxy", "osv"). Use this function with stats from memory.TTLCache.Stats().

func RecordImageScanMetrics

func RecordImageScanMetrics(ctx context.Context, duration float64, transport string, registry string, pkgCount, layerCount int)

RecordImageScanMetrics records metrics for a completed container image scan.

func RecordMCPToolCall

func RecordMCPToolCall(ctx context.Context, toolName string, duration float64, success bool)

RecordMCPToolCall records an MCP tool invocation.

func RecordOSVCacheAccess

func RecordOSVCacheAccess(ctx context.Context, hit bool)

RecordOSVCacheAccess records an OSV cache access.

func RecordOSVQuery

func RecordOSVQuery(ctx context.Context, duration float64, queryType string, success bool)

RecordOSVQuery records an OSV query.

func RecordPolicyEvaluation

func RecordPolicyEvaluation(ctx context.Context, duration float64, result string)

RecordPolicyEvaluation records a policy evaluation.

func RecordPolicyResult

func RecordPolicyResult(span trace.Span, policyName, action string)

RecordPolicyResult adds a policy evaluation result event to a span. Called by the policy engine after each policy is evaluated to provide per-policy trace visibility. The action should be "allow", "deny", or "warn".

func RecordProxyAuth

func RecordProxyAuth(ctx context.Context, result string, errorCode string)

RecordProxyAuth records a proxy authentication attempt.

func RecordProxyPolicyDenial

func RecordProxyPolicyDenial(ctx context.Context, ecosystem, policyName string)

RecordProxyPolicyDenial records a policy denial in the proxy.

func RecordProxyRequest

func RecordProxyRequest(ctx context.Context, duration float64, ecosystem string, statusCode int)

RecordProxyRequest records a proxy request.

func RecordSandboxExecution

func RecordSandboxExecution(ctx context.Context, info SandboxExecutionInfo)

RecordSandboxExecution records metrics for a completed sandbox execution.

func RecordSandboxPolicyDenial

func RecordSandboxPolicyDenial(ctx context.Context, runtime, policyName string)

RecordSandboxPolicyDenial records a sandbox execution denied by policy.

func RecordScanCompletion

func RecordScanCompletion(ctx context.Context, c ScanCompletion)

RecordScanCompletion records scan results on both the span (trace) and metrics. This provides a single call to update both observability signals consistently, avoiding duplication and ensuring trace attributes and metrics stay in sync.

Note: This does NOT call SetSpanOK - the caller should still explicitly mark the span status after this call.

func RecordScanMetrics

func RecordScanMetrics(ctx context.Context, duration float64, ecosystem string, pkgCount, vulnCount int, severity map[string]int)

RecordScanMetrics records metrics for a completed scan.

func RecordScanResults

func RecordScanResults(span trace.Span, pkgCount, vulnCount, critical, high, medium, low int)

RecordScanResults adds scan result attributes to a span.

func RequestAttributes

func RequestAttributes(r *http.Request) []attribute.KeyValue

RequestAttributes returns common attributes for HTTP request spans.

func ResponseAttributes

func ResponseAttributes(statusCode int, contentLength int64) []attribute.KeyValue

ResponseAttributes returns common attributes for HTTP response spans.

func SandboxNetworkModeAttr

func SandboxNetworkModeAttr(mode string) attribute.KeyValue

SandboxNetworkModeAttr returns a sandbox network mode attribute.

func SandboxPluginAttr

func SandboxPluginAttr(pluginName string) attribute.KeyValue

SandboxPluginAttr returns a sandbox plugin name attribute.

func SandboxRuntimeAttr

func SandboxRuntimeAttr(runtime string) attribute.KeyValue

SandboxRuntimeAttr returns a sandbox runtime attribute.

func SandboxWorkspaceIsolationAttr

func SandboxWorkspaceIsolationAttr(isolation string) attribute.KeyValue

SandboxWorkspaceIsolationAttr returns a sandbox workspace isolation attribute.

func SetSpanError

func SetSpanError(span trace.Span, err error)

SetSpanError records an error on the span and sets its status to Error. Safe to call with nil error (no-op). Call this on error paths before returning an error from a function that started a span.

func SetSpanOK

func SetSpanOK(span trace.Span)

SetSpanOK sets the span status to OK. Call this on success paths before returning nil from a function that started a span. This explicitly marks the span as successful.

func SeverityAttr

func SeverityAttr(severity string) attribute.KeyValue

SeverityAttr returns a severity attribute for the given severity string.

func SpanFromContext

func SpanFromContext(ctx context.Context) trace.Span

SpanFromContext returns the current span from the context. Returns a no-op span if none is present, which is safe to use (all operations become no-ops).

func SpanIDFromContext

func SpanIDFromContext(ctx context.Context) string

SpanIDFromContext extracts the span ID from the context, if present. Returns an empty string if no valid trace context exists.

func StartSpan

func StartSpan(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span)

StartSpan starts a new span with the given name and options. Returns the updated context and the span.

Span lifecycle management:

  • The caller MUST call span.End() when the operation completes (typically via defer)
  • On success, call SetSpanOK(span) before returning nil
  • On error, call SetSpanError(span, err) before returning the error

Example:

ctx, span := otel.StartSpan(ctx, "deputy.myop")
defer span.End()

result, err := doWork(ctx)
if err != nil {
    otel.SetSpanError(span, err)
    return err
}
otel.SetSpanOK(span)
return nil

func TraceIDFromContext

func TraceIDFromContext(ctx context.Context) string

TraceIDFromContext extracts the trace ID from the context, if present. Returns an empty string if no valid trace context exists.

func Tracer

func Tracer(name string) trace.Tracer

Tracer returns a named tracer for creating spans. Returns a no-op tracer if OTel is disabled.

func WithCommandAttrs

func WithCommandAttrs(command string) trace.SpanStartOption

WithCommandAttrs returns span start options for command spans.

func WithEcosystemAttr

func WithEcosystemAttr(ecosystem string) trace.SpanStartOption

WithEcosystemAttr returns a span start option for ecosystem.

func WithOSVAttrs

func WithOSVAttrs(batchSize int, queryType string) trace.SpanStartOption

WithOSVAttrs returns span start options for OSV query spans.

func WithPolicyAttrs

func WithPolicyAttrs(name, entrypoint string) trace.SpanStartOption

WithPolicyAttrs returns span start options for policy evaluation spans.

func WithPropagators

func WithPropagators(p propagation.TextMapPropagator) otelhttp.Option

WithPropagators returns an option that sets custom propagators.

func WithProxyAttrs

func WithProxyAttrs(listener, ecosystem, pkg, version string) trace.SpanStartOption

WithProxyAttrs returns span start options for proxy request spans.

func WithPublicEndpoint

func WithPublicEndpoint() otelhttp.Option

WithPublicEndpoint returns an option that marks the endpoint as public. Public endpoints always start a new trace rather than continuing an existing one.

func WithPublicEndpointFn

func WithPublicEndpointFn(fn func(r *http.Request) bool) otelhttp.Option

WithPublicEndpointFn returns an option with a function to determine if an endpoint is public.

func WithServiceName

func WithServiceName(name string) otelhttp.Option

WithServiceName returns an option that sets the service name for spans.

func WithSpanNameFormatter

func WithSpanNameFormatter(fn func(operation string, r *http.Request) string) otelhttp.Option

WithSpanNameFormatter returns an option that customizes span names.

func WithTargetAttrs

func WithTargetAttrs(path, ref string, isRemote bool) trace.SpanStartOption

WithTargetAttrs returns span start options for target resolution spans.

func WrapHandler

func WrapHandler(h slog.Handler) slog.Handler

WrapHandler wraps an existing handler with trace context support. If the handler is already a TraceContextHandler, returns it unchanged.

Types

type AuditHandler

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

AuditHandler filters log records to only those matching audit event patterns and writes them as JSON to a dedicated audit log destination.

Audit events are identified by message prefixes (e.g., "deputy.scan.", "deputy.policy.", "deputy.proxy."). This allows using standard slog calls for audit logging without a separate API.

Usage:

auditFile, _ := os.OpenFile("audit.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
auditHandler := otel.NewAuditHandler(auditFile, "deputy.")
logger := slog.New(otel.NewMultiHandler(mainHandler, auditHandler))

// This goes to both main log and audit log:
logger.Info("deputy.scan.completed", "target", "github.com/example/repo", "vulns", 5)

// This only goes to main log (no "deputy." prefix):
logger.Debug("processing file", "path", "/tmp/foo")

func NewAuditHandler

func NewAuditHandler(w io.Writer, prefix string) *AuditHandler

NewAuditHandler creates a handler that filters for audit events and writes JSON. Only log records whose message starts with the given prefix are written. Common prefix values: "deputy." for all Deputy events.

func (*AuditHandler) Enabled

func (h *AuditHandler) Enabled(ctx context.Context, level slog.Level) bool

Enabled reports whether the handler handles records at the given level. The handler is always enabled; filtering happens in Handle based on message prefix.

func (*AuditHandler) Handle

func (h *AuditHandler) Handle(ctx context.Context, r slog.Record) error

Handle writes the record if its message matches the audit prefix.

func (*AuditHandler) WithAttrs

func (h *AuditHandler) WithAttrs(attrs []slog.Attr) slog.Handler

WithAttrs returns a new handler with the given attributes added.

func (*AuditHandler) WithGroup

func (h *AuditHandler) WithGroup(name string) slog.Handler

WithGroup returns a new handler with the given group name prepended.

type CacheStats

type CacheStats struct {
	Hits    uint64  // Total cache hits
	Misses  uint64  // Total cache misses
	Evicted uint64  // Total evictions due to capacity
	Expired uint64  // Total expirations due to TTL
	Size    int     // Current number of entries
	MaxSize int     // Maximum capacity
	HitRate float64 // Hit rate (0.0-1.0)
}

CacheStats represents a snapshot of cache statistics compatible with memory.Stats from the cache/memory package.

type Config

type Config struct {
	// Enabled controls whether OTel instrumentation is active.
	// Default: false (zero overhead when disabled).
	Enabled bool `yaml:"enabled"`

	// ServiceName identifies the service in traces/metrics.
	// Default: "deputy"
	ServiceName string `yaml:"service_name"`

	// ServiceVersion is the service version for resource attributes.
	// If empty, uses the build version.
	ServiceVersion string `yaml:"service_version"`

	// Exporter configures the OTLP exporter.
	Exporter ExporterConfig `yaml:"exporter"`

	// Traces configures tracing behavior.
	Traces TracesConfig `yaml:"traces"`

	// Metrics configures metrics collection.
	Metrics MetricsConfig `yaml:"metrics"`

	// Logs configures log correlation.
	Logs LogsConfig `yaml:"logs"`
}

Config configures OpenTelemetry instrumentation.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a configuration with sensible defaults. Note: Enabled defaults to false for zero overhead.

func (*Config) Validate

func (c *Config) Validate() error

Validate checks the configuration for invalid values.

type ExporterConfig

type ExporterConfig struct {
	// Protocol selects OTLP transport: "grpc" (default) or "http".
	Protocol string `yaml:"protocol"`

	// Endpoint is the collector address.
	// For gRPC: "localhost:4317" (default)
	// For HTTP: "localhost:4318"
	Endpoint string `yaml:"endpoint"`

	// Insecure disables TLS. Use for local development only.
	Insecure bool `yaml:"insecure"`

	// Headers for authentication (e.g., {"Authorization": "Bearer token"}).
	Headers map[string]string `yaml:"headers"`

	// Timeout for export operations. Default: 10s.
	Timeout time.Duration `yaml:"timeout"`
}

ExporterConfig configures the OTLP exporter.

type LogsConfig

type LogsConfig struct {
	// Enabled controls log export to OTel. Default: true when OTel enabled.
	Enabled bool `yaml:"enabled"`

	// IncludeTraceContext adds trace_id/span_id to log records.
	// Default: true.
	IncludeTraceContext bool `yaml:"include_trace_context"`
}

LogsConfig configures log correlation.

type Metrics

type Metrics struct {
	// Scan metrics
	ScanDuration      metric.Float64Histogram
	ScanPackages      metric.Int64Counter
	ScanVulns         metric.Int64Counter
	ScanPolicyResults metric.Int64Counter

	// Container image scan metrics
	ImageScanDuration metric.Float64Histogram
	ImageScanPackages metric.Int64Counter
	ImageScanLayers   metric.Int64Counter

	// OSV metrics
	OSVQueries       metric.Int64Counter
	OSVQueryDuration metric.Float64Histogram
	OSVCacheHits     metric.Int64Counter
	OSVCacheMisses   metric.Int64Counter

	// Policy metrics
	PolicyEvaluations metric.Int64Counter
	PolicyDuration    metric.Float64Histogram

	// Proxy metrics
	ProxyRequests        metric.Int64Counter
	ProxyRequestDuration metric.Float64Histogram
	ProxyAuth            metric.Int64Counter
	ProxyPolicyDenials   metric.Int64Counter

	// Cache metrics
	CacheHits      metric.Int64Counter
	CacheMisses    metric.Int64Counter
	CacheEvictions metric.Int64Counter
	CacheExpired   metric.Int64Counter
	CacheSize      metric.Int64Gauge
	CacheMaxSize   metric.Int64Gauge
	CacheHitRate   metric.Float64Gauge

	// MCP metrics
	MCPToolCalls    metric.Int64Counter
	MCPToolDuration metric.Float64Histogram
	MCPToolErrors   metric.Int64Counter

	// Sandbox metrics
	SandboxExecutions        metric.Int64Counter
	SandboxExecutionDuration metric.Float64Histogram
	SandboxFilesChanged      metric.Int64Counter
	SandboxPolicyDenials     metric.Int64Counter
}

Metrics holds all Deputy metric instruments. Use GetMetrics() to access the singleton instance.

func GetMetrics

func GetMetrics() (*Metrics, error)

GetMetrics returns the singleton Metrics instance. Creates the instruments on first call. Safe for concurrent use.

type MetricsConfig

type MetricsConfig struct {
	// Enabled controls metrics collection. Default: true when OTel enabled.
	Enabled bool `yaml:"enabled"`

	// Interval is the metrics export interval.
	// Default: 5s (optimized for interactive demos).
	// For production, consider 60s to reduce overhead.
	// Can be overridden with OTEL_METRIC_EXPORT_INTERVAL env var.
	Interval time.Duration `yaml:"interval"`
}

MetricsConfig configures metrics collection.

type MultiHandler

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

NewMultiHandler creates a handler that writes to multiple handlers. Useful for sending logs to both stdout and OTel collector.

func NewMultiHandler

func NewMultiHandler(handlers ...slog.Handler) *MultiHandler

NewMultiHandler creates a handler that fans out to multiple handlers.

func (*MultiHandler) Enabled

func (h *MultiHandler) Enabled(ctx context.Context, level slog.Level) bool

Enabled reports whether the handler handles records at the given level.

func (*MultiHandler) Handle

func (h *MultiHandler) Handle(ctx context.Context, r slog.Record) error

Handle writes the record to all handlers.

func (*MultiHandler) WithAttrs

func (h *MultiHandler) WithAttrs(attrs []slog.Attr) slog.Handler

WithAttrs returns a new handler with the given attributes added.

func (*MultiHandler) WithGroup

func (h *MultiHandler) WithGroup(name string) slog.Handler

WithGroup returns a new handler with the given group name prepended.

type Provider

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

Provider manages the OpenTelemetry SDK lifecycle. Call Shutdown when done to flush pending telemetry data.

func Init

func Init(ctx context.Context, cfg Config) (*Provider, error)

Init initializes the OpenTelemetry SDK based on configuration. Returns a Provider that must be shut down via Shutdown(). If OTel is disabled or not configured, returns a no-op provider.

This function is safe to call multiple times; subsequent calls after the first return the existing provider.

func (*Provider) Enabled

func (p *Provider) Enabled() bool

Enabled reports whether OTel instrumentation is active.

func (*Provider) LoggerProvider

func (p *Provider) LoggerProvider() *sdklog.LoggerProvider

LoggerProvider returns the logger provider, or nil if not initialized.

func (*Provider) Shutdown

func (p *Provider) Shutdown(ctx context.Context) error

Shutdown gracefully shuts down all providers, flushing pending data. Safe to call multiple times; subsequent calls are no-ops.

type SandboxExecutionInfo

type SandboxExecutionInfo struct {
	Runtime            string  // Runtime name (e.g., "plugin", "docker", "gvisor")
	PluginName         string  // Plugin name if runtime is "plugin"
	NetworkMode        string  // Network mode (e.g., "none", "host", "allowlist")
	WorkspaceIsolation string  // Workspace isolation mode (e.g., "direct", "overlay")
	Duration           float64 // Execution duration in seconds
	ExitCode           int32   // Exit code from the execution
	FilesAdded         int     // Number of files added
	FilesModified      int     // Number of files modified
	FilesDeleted       int     // Number of files deleted
	Success            bool    // Whether execution succeeded
}

SandboxExecutionInfo holds information about a sandbox execution for metrics recording.

type ScanCompletion

type ScanCompletion struct {
	Span         trace.Span     // The span to record attributes on
	Duration     float64        // Scan duration in seconds
	Ecosystem    string         // Package ecosystem (e.g., "go", "npm", "sbom")
	PackageCount int            // Number of packages scanned
	Severity     SeverityCounts // Vulnerability counts by severity
}

ScanCompletion holds data for recording scan completion on both traces and metrics. Use with RecordScanCompletion for consistent observability across both signals.

type SeverityCounts

type SeverityCounts struct {
	Critical int
	High     int
	Medium   int
	Low      int
}

SeverityCounts holds vulnerability counts by severity level. This provides a standard way to pass severity data to recording functions.

func (SeverityCounts) ToMap

func (s SeverityCounts) ToMap() map[string]int

ToMap converts SeverityCounts to a map for metric recording.

func (SeverityCounts) Total

func (s SeverityCounts) Total() int

Total returns the sum of all severity counts.

type TraceContextHandler

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

TraceContextHandler wraps an slog.Handler to add trace context attributes (trace_id, span_id) to log records when available.

func NewTraceContextHandler

func NewTraceContextHandler(base slog.Handler) *TraceContextHandler

NewTraceContextHandler creates a new handler that adds trace context to logs.

func (*TraceContextHandler) Enabled

func (h *TraceContextHandler) Enabled(ctx context.Context, level slog.Level) bool

Enabled reports whether the handler handles records at the given level.

func (*TraceContextHandler) Handle

func (h *TraceContextHandler) Handle(ctx context.Context, r slog.Record) error

Handle adds trace context attributes and delegates to the base handler.

func (*TraceContextHandler) WithAttrs

func (h *TraceContextHandler) WithAttrs(attrs []slog.Attr) slog.Handler

WithAttrs returns a new handler with the given attributes added.

func (*TraceContextHandler) WithGroup

func (h *TraceContextHandler) WithGroup(name string) slog.Handler

WithGroup returns a new handler with the given group name prepended.

type TracesConfig

type TracesConfig struct {
	// Enabled controls trace collection. Default: true when OTel enabled.
	Enabled bool `yaml:"enabled"`

	// SampleRate is the probability of sampling (0.0-1.0).
	// Default: 1.0 (sample everything).
	SampleRate float64 `yaml:"sample_rate"`

	// Propagators selects context propagation formats.
	// Default: ["tracecontext", "baggage"]
	Propagators []string `yaml:"propagators"`
}

TracesConfig configures tracing behavior.

Jump to

Keyboard shortcuts

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