/** * Kernel → driver log bridge. * * The Rust kernel emits its diagnostics via `tracing`. In a Node process those * events have no subscriber and are dropped — so by default the driver's * `DBSQLLogger` only ever saw JS-side lines. The napi binding's * `initKernelLogging` installs a process-global subscriber that forwards * kernel events (batched) to a JS callback; this module wires that callback * into the **same** `IDBSQLLogger` the driver logs through, so logs from all * three layers (driver, napi shim, kernel) land in one place — and one file * when the logger has a file transport. * * Verbosity follows the driver's logger level (see `installKernelLogBridge`), * filtered kernel-side so we don't pay the channel/bridge cost for events the * sink would discard anyway. */ import IDBSQLLogger, { LogLevel } from '../contracts/IDBSQLLogger'; import { KernelNativeBinding, KernelNativeLogRecord } from './KernelNativeLoader'; /** * Map a kernel level string (`error`/`warn`/`info`/`debug`/`trace`) onto the * driver's `LogLevel`. The kernel's `trace` has no `LogLevel` analogue, so it * folds into `debug` (the most verbose driver level). */ export declare function kernelLevelToLogLevel(level: string): LogLevel; /** * Map a driver `LogLevel` onto the kernel level string the napi bridge expects. * The `LogLevel` enum values are already the kernel-compatible lower-case * strings, so this is the identity at runtime — kept as an explicit function so * the boundary is named and a future divergence has one place to live. */ export declare function logLevelToKernelLevel(level: LogLevel): string; /** * Format one kernel log record into a single driver log line, tagged with its * origin so kernel lines are distinguishable from driver lines in a shared * sink/file. */ export declare function formatKernelLine(record: KernelNativeLogRecord): string; /** * Install the kernel→driver log bridge: forward kernel `tracing` events into * `logger` at `level`. * * - **Verbosity** is set kernel-side to `level` so events the sink would drop * never cross the bridge. * - **Process-global, last-writer-wins:** the napi binding holds a single * process-global subscriber + sink (a `tracing` global subscriber installs * once). Each call retargets the sink to `logger`, so in a multi-client * process the most recently connected client's logger receives kernel logs — * mirroring the Python connector's `pyo3_log` model. Single-client apps, the * common case, are unaffected. * - **Runtime retargeting:** if `logger` exposes `onLevelChange` (as * `DBSQLLogger` does), the bridge subscribes so a later `logger.setLevel(...)` * also retargets the kernel-side filter via `setKernelLogLevel` — keeping * kernel verbosity in lock-step with the driver's at runtime, not just at * connect. Loggers without it still get the connect-time level. * - **Graceful on older bindings:** if the loaded `.node` predates * `initKernelLogging`, this is a no-op (kernel logs simply stay unbridged) * rather than a hard failure — logging is advisory. * * Returns an **unsubscribe** function the caller must invoke on teardown * (`KernelBackend.close()`) to drop the level-change listener; it is a safe no-op * when nothing was subscribed. */ export declare function installKernelLogBridge(binding: KernelNativeBinding, logger: IDBSQLLogger, level: LogLevel): () => void;