/** * ObservabilityService for structured logging, metrics, and sampling. * * Provides centralized observability with deterministic sampling, JSON logging, * token/cost metrics, and run storage for hook events and trace export. * * @module src/core/observability/service */ import { Effect, Context, Layer } from 'effect'; import type { CorrelationContext } from './context'; import { type SecretRedactionOptions } from './errors'; /** * Observability service configuration. */ export interface ObservabilityServiceConfig { /** Success sampling rate (0.0 to 1.0). Default: 0.01 (1%) */ successSampleRate?: number; /** Slow threshold in milliseconds. Runs exceeding this are always sampled. Default: 5000 */ slowThresholdMs?: number; /** Debug mode: force all runs to be sampled. Default: false */ debugMode?: boolean; /** Service metadata attached to all logs and spans */ serviceMetadata?: { serviceName?: string; serviceVersion?: string; environment?: string; [key: string]: unknown; }; /** Pricing table for cost calculation (model -> price per token) */ pricing?: Record; /** Hash payloads by default (only include raw content when explicitly flagged) */ hashPayloads?: boolean; /** Fields and dot paths that must be removed from structured log annotations. */ secretRedaction?: SecretRedactionOptions; } /** * Sampling decision result. */ export interface SamplingDecision { /** Whether to sample this run */ shouldSample: boolean; /** Reason for the decision */ reason: 'error' | 'slow' | 'debug' | 'sampled' | 'filtered'; } /** * Run storage entry for hook events and trace export. */ export interface RunRecord { runId: string; traceId?: string; startTime: number; endTime?: number; /** Hook events recorded for this run */ hookEvents: HookEvent[]; /** Step spans recorded for this run */ stepSpans: StepSpan[]; /** Tool usage recorded for this run */ toolUsage: ToolUsage[]; /** Model usage recorded for this run */ modelUsage: ModelUsage[]; /** Whether this run had an error */ hasError: boolean; /** Whether this run was slow */ isSlow: boolean; /** Correlation context for this run */ correlationContext?: CorrelationContext; } /** * Hook event record. */ export interface HookEvent { hookType: string; timestamp: number; metadata: Record; } /** * Step span record. */ export interface StepSpan { stepName: string; startTime: number; endTime: number; status: 'success' | 'error'; metadata: Record; } /** * Tool usage record. */ export interface ToolUsage { toolId: string; timestamp: number; inputHash?: string; outputHash?: string; durationMs: number; } /** * Model usage record. */ export interface ModelUsage { provider: string; model: string; timestamp: number; inputTokens: number; outputTokens: number; cost?: number; messageHash?: string; } /** * Metrics snapshot for JSON export. */ export interface MetricsSnapshot { timestamp: number; runId?: string; metrics: { hookEvents: Record; tokenUsage: { total: number; byProvider: Record; }; modelCost: { total: number; byProvider: Record; }; }; } /** * OpenTelemetry metrics export format. */ export interface OtelMetricsExport { resourceMetrics: Array<{ resource: { attributes: Record; }; scopeMetrics: Array<{ scope: { name: string; version: string; }; metrics: Array<{ name: string; description: string; unit?: string; sum?: { dataPoints: Array<{ attributes: Record; value: number; timeUnixNano: string; }>; isMonotonic: boolean; aggregationTemporality?: 'AGGREGATION_TEMPORALITY_CUMULATIVE'; }; gauge?: { dataPoints: Array<{ attributes: Record; value: number; timeUnixNano: string; }>; }; histogram?: { dataPoints: Array<{ attributes: Record; count: number; sum: number; min: number; max: number; bucketCounts: ReadonlyArray; explicitBounds: ReadonlyArray; timeUnixNano: string; }>; aggregationTemporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE'; }; }>; }>; }>; } declare const ObservabilityService_base: Context.TagClass Effect.Effect; /** Determine if a run should be sampled */ readonly shouldSampleRun: (options: { runId: string; hasError?: boolean; durationMs?: number; }) => Effect.Effect; /** Log structured JSON with correlation context and service metadata */ readonly logStructured: (options: { level: "trace" | "debug" | "info" | "warning" | "error" | "fatal"; message: string; metadata?: Record; }) => Effect.Effect; /** Record a hook event metric */ readonly recordHookEvent: (hookType: string) => Effect.Effect; /** Record token usage metric */ readonly recordTokenUsage: (options: { provider: string; model: string; inputTokens: number; outputTokens: number; }) => Effect.Effect; /** Record model cost metric (if pricing configured) */ readonly recordModelCost: (options: { provider: string; model: string; inputTokens: number; outputTokens: number; }) => Effect.Effect; /** Hash a payload (for message/tool content) */ readonly hashPayload: (payload: unknown) => Effect.Effect; /** Start tracking a run */ readonly startRun: (runId: string) => Effect.Effect; /** Record a hook event for a run */ readonly recordRunHookEvent: (runId: string, event: HookEvent) => Effect.Effect; /** Record a step span for a run */ readonly recordRunStepSpan: (runId: string, span: StepSpan) => Effect.Effect; /** Record tool usage for a run */ readonly recordRunToolUsage: (runId: string, usage: ToolUsage) => Effect.Effect; /** Record model usage for a run */ readonly recordRunModelUsage: (runId: string, usage: ModelUsage) => Effect.Effect; /** Mark a run as having an error */ readonly markRunError: (runId: string) => Effect.Effect; /** Mark a run as slow */ readonly markRunSlow: (runId: string) => Effect.Effect; /** Complete a run */ readonly completeRun: (runId: string) => Effect.Effect; /** Get run record */ readonly getRunRecord: (runId: string) => Effect.Effect; /** Export run as trace */ readonly exportTrace: (runId: string) => Effect.Effect; /** Export metrics as JSON snapshot */ readonly exportMetrics: (options?: { runId?: string; safe?: boolean; }) => Effect.Effect; /** Export metrics in Prometheus text format */ readonly exportMetricsPrometheus: () => Effect.Effect; /** Export metrics in OpenTelemetry format */ readonly exportMetricsOtel: () => Effect.Effect; /** Get traceId by runId */ readonly getTraceIdByRunId: (runId: string) => Effect.Effect; }>; /** * ObservabilityService tag. */ export declare class ObservabilityService extends ObservabilityService_base { } export declare const ObservabilityServiceLive: Layer.Layer; export {}; //# sourceMappingURL=service.d.ts.map