/** * Shared structured logger factory. Components create a logger with a namespace. * * Dual sink, one shape: every record renders to the TTY via `console.*` and is emitted * as a real OTel LogRecord via the global Logs API. When the SDK is not initialised (off, * or under test) the API resolves a no-op logger, so the emit is a near-zero no-op — no * `enabled` gate needed. trace_id/span_id are stamped natively from the active span; the * per-runtime `senpi.*` identity rides in via the async-context bag (see `trackingContext`). */ import { type AttrsFor, type EventName } from "./event-catalog.js"; export type LogLevel = "debug" | "info" | "warn" | "error"; export type LogLevelSource = "config" | "env" | "default" | "runtime"; /** Parse a candidate log-level string. Returns null for unknown values (caller decides how to warn/fallback). */ export declare function parseLogLevel(raw: string | undefined | null): LogLevel | null; export declare function setLogLevel(level: LogLevel, source?: LogLevelSource): void; export declare function getLogLevel(): LogLevel; export declare function getLogLevelSource(): LogLevelSource; /** OTel exception semconv, normalized from any thrown value. Stacks are kept unredacted. */ export interface NormalizedException { type?: string; message: string; stacktrace?: string; } /** * The options for an event emit. Placement is the control — there is no opt-out: * - `body` — a deterministic, human/agent-readable narrative, templated from safe scalars. Safe by * construction, so it is NEVER redacted (and never capped — it is bounded by its template). * - `attributes` — structured scalars, typed per event via {@link AttrsFor}. Safe by construction: * capped, but NEVER redacted. ONE exception, and it is deliberate: `signal.outcome` carries the * scanner's `meta` bag as the `senpi.signal.meta` JSON string. That value is operator-authored * content, not a runtime-derived scalar — it is not safe by construction, it is safe by contract * (a scanner must not put secrets in its `meta`), and it is not redacted either. * - `redact` — free-text / external strings (LLM reasoning, a venue error, a raw signal). The only * slot that is capped AND always run through redaction before it joins the emitted attributes. * - `error` — a thrown value when this catalogued event IS also a fault (e.g. `order.failed` from a * venue throw). Normalized to `exception.*` semconv on the record (stack kept, uncapped) and recorded * on the active span, so one emit carries narrative + typed attrs + exception. Severity is the call * site's to grade via `level`. */ export interface EventOptions { body: string; attributes?: AttrsFor; redact?: Record; error?: unknown; } export interface Logger { debug(message: string, attributes?: unknown): void; info(message: string, attributes?: unknown): void; /** * @param error An `Error` (or other thrown value) → normalized to `exception.*` attributes and * recorded on the active span. Omit for a plain log; pass attributes here only when there is no * error (a non-`Error` value here is treated as the attributes bag for back-compat). * @param attributes The attributes bag, when an error is also passed. */ warn(message: string, error?: unknown, attributes?: unknown): void; error(message: string, error?: unknown, attributes?: unknown): void; /** * Emit a first-class event from the closed {@link EventName} catalog: a deterministic narrative * `body`, safe scalar `attributes` (typed per event, capped, never redacted), and optional * free-text `redact` fields (capped + always scrubbed). The `name` is set as the OTel eventName, * never sniffed from attributes. `level` drives severity (and the console sink). See * {@link EventOptions}. */ event(name: N, level: LogLevel, opts: EventOptions): void; } export declare function createLogger(namespace: string): Logger; /** * A complete {@link Logger} that discards everything. Use it as an explicit "be silent here" default * (e.g. tests, or a consumer that doesn't wire logging) instead of hand-rolling a partial object — * being defined alongside {@link Logger} it always satisfies the full contract as the interface grows. */ export declare const noopLogger: Logger; //# sourceMappingURL=logger.d.ts.map