/** * OpenTelemetry observability layer factory using Effect's built-in logging and tracing. * * Provides Effect logger and tracer layers with OTLP exporter support. * Handles resource metadata (service name/version/environment) and defaults gracefully * when OTLP is not configured. * * @module src/core/observability/otel */ import { Effect, Layer, LogLevel } from 'effect'; /** * Observability configuration options */ export interface ObservabilityConfig { /** OTLP exporter endpoint (e.g., 'http://localhost:4318/v1/traces') */ otlp?: { endpoint?: string; headers?: Record; }; /** Minimum log level override (defaults to debug in dev, info in prod) */ logLevel?: 'trace' | 'debug' | 'info' | 'warning' | 'error' | 'fatal'; /** Resource attributes attached to all spans and logs */ resource?: { serviceName?: string; serviceVersion?: string; environment?: string; [key: string]: unknown; }; /** Enable console exporter as fallback when OTLP is not configured */ enableConsoleFallback?: boolean; /** Per-run verbosity overrides for controlling high-volume events */ verbosity?: VerbosityOverrides; } /** * Verbosity override settings for controlling event volume. */ export interface VerbosityOverrides { /** Gate token stream events to debug level (default: true) */ gateTokenStreams?: boolean; /** Gate heartbeat events to debug level (default: true) */ gateHeartbeats?: boolean; /** Minimum level for high-volume events when not gated (default: info) */ highVolumeLevel?: 'debug' | 'info'; } /** * Observability layers for the Effect runtime. * Includes tracer and logger layers with OTLP exporter wiring. */ export interface ObservabilityLayers { /** Combined layer for tracer provider */ tracerLayer: Layer.Layer; /** Logger layer with minimum log level applied */ loggerLayer: Layer.Layer; } /** * Build observability layers from configuration. * * Returns Effect logger and tracer layers with OTLP exporter support. * When OTLP is not configured, falls back to console exporter (if enabled) * or no-op tracer (spans still created but not exported). * * @param config - Observability configuration * @returns Observability layers ready for Effect runtime * * @example * ```typescript * const { tracerLayer, loggerLayer } = buildObservabilityLayers({ * otlp: { endpoint: 'http://localhost:4318/v1/traces' }, * logLevel: 'debug', * resource: { serviceName: 'fred', serviceVersion: '0.1.2' } * }); * * const program = Effect.withSpan("my-operation")(Effect.succeed("done")); * const programWithObservability = program.pipe( * Effect.provide(tracerLayer), * Effect.provide(loggerLayer) * ); * ``` */ export declare function buildObservabilityLayers(config?: ObservabilityConfig): ObservabilityLayers; /** * Annotate the current span with common Fred identifiers. * * Attaches runId, conversationId, workflowId, stepName, and other metadata * to the active span for observability correlation. * * @param metadata - Metadata to attach to current span * @returns Effect that annotates the current span * * @example * ```typescript * const program = Effect.withSpan("pipeline.step")( * annotateSpan({ * runId: 'run-123', * workflowId: 'support', * stepName: 'validate', * attempt: 1 * }).pipe( * Effect.flatMap(() => Effect.logDebug("processing step")) * ) * ); * ``` */ export declare function annotateSpan(metadata: { runId?: string; conversationId?: string; workflowId?: string; stepName?: string; attempt?: number; toolId?: string; provider?: string; agentId?: string; [key: string]: unknown; }): Effect.Effect; /** * Helper to create a span with Fred metadata attached. * * @param name - Span name * @param metadata - Metadata to attach (runId, workflowId, etc.) * @returns Effect that creates a span with metadata * * @example * ```typescript * const program = withFredSpan("tool.call", { runId: 'run-123', toolId: 'search' })( * Effect.logDebug("invoking tool").pipe( * Effect.flatMap(() => callTool()) * ) * ); * ``` */ export declare function withFredSpan(name: string, metadata: Parameters[0]): (effect: Effect.Effect) => Effect.Effect; /** * Check if an event should be logged based on verbosity settings. * * High-volume events (token streams, heartbeats) are gated to debug level * unless verbosity overrides allow them at info level. * * @param eventType - Type of event being logged * @param currentLevel - Current log level * @param verbosity - Verbosity override settings * @returns True if event should be logged at current level */ export declare function shouldLogEvent(eventType: 'token' | 'heartbeat' | 'summary' | 'other', currentLevel: LogLevel.LogLevel, verbosity?: VerbosityOverrides): boolean; /** * Get the effective log level from config and environment. * * Environment variables override config values: * - FRED_LOG_LEVEL: Overall log level * - NODE_ENV: Development vs production defaults * * @param config - Observability configuration * @returns Effective log level */ export declare function getEffectiveLogLevel(config?: ObservabilityConfig): LogLevel.LogLevel; //# sourceMappingURL=otel.d.ts.map