/** Severity levels, ordered low -> high. */
type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';
/** Numeric ordering used for level threshold comparisons. */
declare const LEVEL_ORDER: Record<LogLevel, number>;
/** Bound key/value pairs attached to every record emitted by a logger. */
type LogContext = Record<string, unknown>;
/** A single structured log record handed to a sink. */
interface LogRecord {
    level: LogLevel;
    message: string;
    timestamp: number;
    app: string;
    env: TelemetryEnv;
    /** Merged bound context (child loggers) + per-call context, post-redaction. */
    context: LogContext;
}
/** A span record handed to a sink when a span ends. */
interface SpanRecord {
    name: string;
    startTime: number;
    endTime: number;
    durationMs: number;
    app: string;
    env: TelemetryEnv;
    /** Merged bound context + span attributes, post-redaction. */
    context: LogContext;
    /** 'ok' unless ended with an error. */
    status: 'ok' | 'error';
    error?: {
        name: string;
        message: string;
    };
}
/**
 * Vendor-neutral telemetry sink. Engines (console, Faro, custom) implement
 * this — no vendor type ever leaks across this boundary.
 */
interface TelemetrySink {
    /** Engine name, for diagnostics. */
    name: string;
    /** Receive a log record. May buffer; honor flush(). */
    log(record: LogRecord): void;
    /** Receive a finished span. May buffer; honor flush(). */
    span(record: SpanRecord): void;
    /** Force-deliver any buffered records. Resolves once delivery is attempted. */
    flush(): Promise<void>;
}
/** Telemetry environment — selects a behavior preset. */
type TelemetryEnv = 'development' | 'production';
/** Config for {@link createTelemetry} — mirrors `createAI`'s config shape. */
interface TelemetryConfig {
    /** Logical app/service name attached to every record. */
    app: string;
    /** Environment preset selector. */
    env: TelemetryEnv;
    /**
     * Remote collector endpoint. When omitted, telemetry stays console-only
     * (no network engine is constructed).
     */
    endpoint?: string;
    /**
     * Master kill switch. When `false`, a tree-shakeable noop logger is
     * returned and zero records are ever produced. Defaults to `true`.
     */
    enabled?: boolean;
    /**
     * Fraction of records kept, 0..1. Defaults to the preset value
     * (1 in development, 0.25 in production). Records below the sample
     * are dropped before reaching any sink.
     */
    sampleRate?: number;
    /**
     * Context keys to strip (deep) before a record is emitted. Use for
     * PII / secrets, e.g. `['password', 'token', 'authorization']`.
     */
    redactKeys?: string[];
}
/** A logger bound to a context. Child loggers inherit + extend that context. */
interface Logger {
    debug(message: string, context?: LogContext): void;
    info(message: string, context?: LogContext): void;
    warn(message: string, context?: LogContext): void;
    error(message: string, context?: LogContext): void;
    fatal(message: string, context?: LogContext): void;
    /**
     * Derive a logger with additional bound context (e.g.
     * `{ sessionId, interviewId, turnId }`). Merges over the parent's context.
     */
    child(context: LogContext): Logger;
    /** Begin a span. Call {@link Span.end} to record its duration. */
    startSpan(name: string, attributes?: LogContext): Span;
    /** Force-deliver buffered records on every sink. */
    flush(): Promise<void>;
}
/** An in-flight span returned by {@link Logger.startSpan}. */
interface Span {
    /** End the span and emit a {@link SpanRecord}. Optionally attach error/attrs. */
    end(opts?: {
        error?: unknown;
        attributes?: LogContext;
    }): void;
}
/** Return type of {@link createTelemetry}. */
interface Telemetry extends Logger {
    /** Registered sink names, in insertion order. */
    readonly sinks: string[];
    /** Register an additional sink (e.g. a custom collector). */
    addSink(sink: TelemetrySink): void;
    /** Remove a sink by name. */
    removeSink(name: string): void;
}

/**
 * Behavior derived from {@link TelemetryConfig.env}. The manager reads these
 * fields to decide level filtering, batching, sampling, and flush triggers.
 */
interface TelemetryPreset {
    /** Records strictly below this level are dropped. */
    minLevel: LogLevel;
    /** Buffer records and deliver in batches instead of synchronously. */
    batch: boolean;
    /** Batch size before an automatic flush (only when `batch`). */
    batchSize: number;
    /** Default sample rate when config omits `sampleRate`. */
    sampleRate: number;
    /** Pretty, single-line console output (vs. structured JSON). */
    pretty: boolean;
    /**
     * Flush buffered records on `pagehide` + `visibilitychange` (hidden),
     * using `navigator.sendBeacon` when available.
     */
    beaconFlush: boolean;
}
/**
 * - development: sync, pretty, level=debug, no batching, sample everything.
 * - production: batched + sampled, level>=warn, beacon flush on page exit.
 */
declare const PRESETS: Record<TelemetryEnv, TelemetryPreset>;
/** Resolve the preset for an env (defensive copy so callers can't mutate it). */
declare function resolvePreset(env: TelemetryEnv): TelemetryPreset;

/**
 * createTelemetry — creates a telemetry manager that fans records out to
 * registered sinks. Manager/provider pattern, mirroring `createAI`.
 *
 * - `enabled: false` -> tree-shakeable noop (zero emissions, no engines).
 * - no `endpoint` -> console-only transport.
 * - `endpoint` set -> async Faro engine is registered when the optional
 *   peers exist; console stays as a safe fallback until then.
 *
 * The returned object IS a logger (root context = `{}`); `child()` derives
 * loggers with bound context (sessionId / interviewId / turnId / ...).
 */
declare function createTelemetry(config: TelemetryConfig): Telemetry;

interface ConsoleSinkOptions {
    /** Single-line pretty output (vs. structured JSON). */
    pretty?: boolean;
    /** Console to write to (injectable for tests). Defaults to global console. */
    console?: Pick<Console, 'debug' | 'info' | 'warn' | 'error'>;
}
/**
 * Default zero-dependency transport. Used whenever no `endpoint` is set.
 * Synchronous; `flush()` is a resolved no-op (nothing is buffered).
 */
declare function createConsoleSink(opts?: ConsoleSinkOptions): TelemetrySink;

/**
 * Faro-backed engine. `@grafana/faro-web-sdk` + `@grafana/faro-web-tracing`
 * are **optional peerDependencies** — they are loaded dynamically and never
 * referenced in this module's public types. If the peers are absent the
 * factory resolves to `null` so the caller can fall back to console.
 *
 * For tests, a `transport` may be injected: an object with a `push(payload)`
 * method. This bypasses Faro entirely (no network, no peer required).
 */
/** Minimal structural shape of a Faro-ish transport. Not exported. */
interface FaroTransport {
    push(payload: {
        kind: 'log' | 'span';
        record: LogRecord | SpanRecord;
    }): void;
}
interface FaroEngineOptions {
    app: string;
    endpoint: string;
    /**
     * Test/override transport. When provided, the Faro peers are NOT loaded
     * and records are forwarded straight to `transport.push`.
     */
    transport?: FaroTransport;
}
/**
 * Construct the Faro engine. Returns `null` when the optional peers are not
 * installed and no override transport was supplied — callers treat `null` as
 * "fall back to console".
 */
declare function createFaroSink(opts: FaroEngineOptions): Promise<TelemetrySink | null>;

/**
 * Returned by {@link createTelemetry} when `enabled: false`. Every method is
 * an empty stub, so a bundler can dead-code-eliminate call sites and the
 * engines (console/Faro) are never imported at runtime. Zero emissions.
 */
declare function createNoopTelemetry(): Telemetry;

/**
 * Deep-strip any object key whose name (case-insensitive) is in `keys`.
 * Arrays are walked; cycles are guarded; non-matching values pass through
 * unchanged. Returns a new structure — the input is never mutated.
 */
declare function redact(value: LogContext, keys: string[]): LogContext;

interface MockSinkExtended extends TelemetrySink {
    /** Every log record received, in order. */
    logs: LogRecord[];
    /** Every span record received, in order. */
    spans: SpanRecord[];
    /** Number of times {@link TelemetrySink.flush} was called. */
    flushCalls: number;
}
/**
 * createMockSink — a {@link TelemetrySink} that records everything for
 * assertions instead of doing I/O. Used to test the manager and the Faro
 * engine without any network. Mirrors `createMockAIProvider` in `packages/ai`.
 */
declare function createMockSink(name?: string): MockSinkExtended;

export { type ConsoleSinkOptions, type FaroEngineOptions, LEVEL_ORDER, type LogContext, type LogLevel, type LogRecord, type Logger, type MockSinkExtended, PRESETS, type Span, type SpanRecord, type Telemetry, type TelemetryConfig, type TelemetryEnv, type TelemetryPreset, type TelemetrySink, createConsoleSink, createFaroSink, createMockSink, createNoopTelemetry, createTelemetry, redact, resolvePreset };
