Skip to content

[SEA-NodeJS] Unify kernel + driver logging into one DBSQLLogger sink#417

Open
msrathore-db wants to merge 2 commits into
mainfrom
msrathore/kernel-logging
Open

[SEA-NodeJS] Unify kernel + driver logging into one DBSQLLogger sink#417
msrathore-db wants to merge 2 commits into
mainfrom
msrathore/kernel-logging

Conversation

@msrathore-db
Copy link
Copy Markdown
Contributor

What

Routes the Rust kernel's logs into the same DBSQLLogger (and file) the Node driver already logs through, so logs from all three layers — driver, napi shim, kernel — land in one place.

Today the kernel emits via tracing, but in a Node process nothing subscribes to those events, so they're silently dropped — the user's DBSQLLogger only ever sees driver-side lines. (The Python connector already unifies via pyo3_log; this is the Node equivalent.)

How

  • New lib/sea/SeaLogging.ts: installKernelLogBridge(binding, logger, level) registers a JS callback with the binding's initKernelLogging. Each kernel LogRecord ({ level, target, message }) is level-mapped onto the driver's LogLevel and re-emitted through the client's IDBSQLLogger, tagged [kernel <target>] … so origin is clear in a shared file.
  • SeaBackend.connect() installs the bridge using IClientContext.getLogger().
  • Verbosity follows the driver logger's level: IDBSQLLogger gains an optional getLevel() (implemented by DBSQLLogger); the bridge passes it to the kernel so events the sink would discard never cross the bridge. Loggers without a level default the bridge to info.
  • Process-global, last-writer-wins, and a graceful no-op on an older binding that predates the bridge export (logging is advisory).

So a user who does new DBSQLClient({ logger: new DBSQLLogger({ level: 'debug', filepath: '…' }) }) and connects with useSEA: true now gets kernel logs in that same file, at that same level.

Dependency

Requires the kernel napi exports initKernelLogging / setKernelLogLevel / LogRecord from databricks/databricks-sql-kernel#126. KERNEL_REV is pinned to that branch and the binding rebuilt so the generated native/sea/index.d.ts carries them. Merge order: kernel #126 first, then bump KERNEL_REV here to the merged SHA.

Verification

  • tsc / eslint / prettier clean; SEA unit suite 256 passing (incl. new SeaLogging unit tests: level mapping, batch routing, err-drop, older-binding no-op).
  • Live end-to-end: one DBSQLLogger file held both driver lines and 29 [kernel databricks::sql::kernel] lines (full SEA lifecycle — create session, ExecuteStatement … (attempt 1/6), polling, result manifest, close) for a single SELECT 1, level-mapped. Committed as tests/e2e/sea/logging-e2e.test.ts.

This pull request and its description were written by Isaac.

The Rust kernel emits its diagnostics via `tracing`; in a Node process nothing
subscribed to them, so kernel logs were silently dropped — the `DBSQLLogger`
only ever saw driver-side lines. This wires the kernel into the SAME logger (and
file) the driver uses, so logs from all three layers — driver, napi shim,
kernel — land in one place.

How:
- `SeaBackend.connect()` calls `installKernelLogBridge(binding, logger, level)`
  (new `lib/sea/SeaLogging.ts`), which registers a JS callback with the binding's
  `initKernelLogging`. The callback maps each kernel `LogRecord`
  (`{ level, target, message }`) onto the driver's `LogLevel` and re-emits it
  through `IClientContext.getLogger()`, tagged `[kernel <target>] …`.
- Kernel verbosity follows the driver logger's level: `IDBSQLLogger` gains an
  optional `getLevel()` (implemented by `DBSQLLogger`); the bridge passes it to
  the kernel so events the sink would drop never cross the bridge. Defaults to
  `info` for loggers that don't expose a level.
- Process-global, last-writer-wins + graceful no-op on an older binding without
  the bridge export (logging is advisory) — see SeaLogging docs.

Requires kernel napi `initKernelLogging`/`setKernelLogLevel`/`LogRecord`
(databricks-sql-kernel#126); `KERNEL_REV` bumped + binding rebuilt so the
generated `native/sea/index.d.ts` carries them.

Verified: tsc clean, eslint + prettier clean, SEA unit suite 256 passing (incl.
new SeaLogging unit tests), and a live end-to-end run confirms a single
DBSQLLogger file holds both driver lines and 29 `[kernel databricks::sql::kernel]`
lines for one `SELECT 1` (committed as tests/e2e/sea/logging-e2e.test.ts).

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
Follow-up to the unified-logging wiring: a runtime `logger.setLevel(...)` now
retargets the kernel-side bridge too, not just the driver's own transports —
keeping kernel verbosity in lock-step with the driver's at runtime, not only at
connect.

- `IDBSQLLogger` gains an optional `onLevelChange(listener) => unsubscribe`;
  `DBSQLLogger` implements it (fires subscribers from `setLevel`, swallowing a
  throwing listener so it can't break level setting).
- `installKernelLogBridge` now returns an unsubscribe handle and, when both the
  logger can notify (`onLevelChange`) and the binding can retarget
  (`setKernelLogLevel`), subscribes to forward level changes to the kernel.
- `SeaBackend` stores the handle and drops it on `close()` (no stale listener;
  the process-global kernel sink follows the existing last-writer-wins model).

Backend-agnostic: `DBSQLLogger` never references the SEA binding — the SEA layer
subscribes via the interface. Loggers without `onLevelChange` keep the
connect-time level; older bindings without `setKernelLogLevel` simply don't
subscribe.

Verified: tsc / eslint / prettier clean; unit suite 1183 passing incl. new
`DBSQLLogger` level-subscription tests + `SeaLogging` runtime-retarget tests
(retarget, unsubscribe, no-notify logger, no-retarget binding). Live: with the
logger started at `warn`, a healthy SELECT logged 0 kernel lines; after
`logger.setLevel('debug')` mid-session the next SELECT logged 12
`[kernel databricks::sql::kernel]` lines — proving the kernel was retargeted.

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant