Skip to content

feat(kernel): forward kernel logs into the driver logger via callback#411

Draft
mani-mathur-arch wants to merge 1 commit into
mani/sea-kernel-tier2-featuresfrom
mani/sea-kernel-log-callback
Draft

feat(kernel): forward kernel logs into the driver logger via callback#411
mani-mathur-arch wants to merge 1 commit into
mani/sea-kernel-tier2-featuresfrom
mani/sea-kernel-log-callback

Conversation

@mani-mathur-arch

@mani-mathur-arch mani-mathur-arch commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

What

Wire the driver side of the kernel reverse-call log callback (behind the databricks_kernel build tag), completing the one-knob logging story:

  • Register a cgo-exported trampoline (kernelLogTrampoline) as the kernel's log sink via kernel_set_log_callback, so kernel-internal tracing events flow into the driver's logger — the unified Go+kernel stream, honouring logger.SetLogOutput — instead of only reaching stderr.
  • The reverse-call machinery: a runtime/cgo.Handle round-trips the *logSink through the C void* ctx (cgo pointer rules), and a defer recover() firewall converts any panic into a dropped line (a panic across the cgo boundary would abort the process). The handle is a deliberate process-lifetime pin (no detach in the v0 ABI).
  • initKernelLogging now installs the callback instead of calling kernel_init_logging. It passes the driver's mapped log level (resolveKernelLogArg, unchanged) as the callback's level, so the kernel's Rust lines follow DATABRICKS_LOG_LEVEL — the same knob PECOBLR-3650 established, now against the callback sink rather than stderr. DBSQL_KERNEL_DEBUG still defers to RUST_LOG (NULL level).
  • The two C-ABI logging routes share the one process-global subscriber and are mutually exclusive; a non-Success install (host already installed a subscriber) is logged, never fatal to connect.

Closes PECOBLR-3654 (driver side).

Stacked on the Tier 2 driver PR (mani/sea-kernel-tier2-features). Draft — CI build is red until KERNEL_REV is bumped to a merged kernel SHA carrying kernel_set_log_callback.

Tests

  • Untagged (CGO_ENABLED=0): logSink.forward level mapping + nil-sink no-op (logforward_test.go), pure Go so it runs without the kernel linked.
  • Tagged: TestLogCallbackRoundTrip drives the C→Go trampoline via a C invoke seam and asserts delivery (handle unwrap + recover firewall + sink dispatch); TestLogCallbackTrampolineNilCtxSafe proves a bad handle can't crash the process. Live round-trip verified — a forwarded WARN line lands in the driver's zerolog sink.

Co-authored-by: Isaac

Register a cgo-exported trampoline (kernelLogTrampoline) as the kernel's log sink
(kernel_set_log_callback) so kernel-internal tracing events flow into the driver's
logger — the unified Go+kernel stream, honouring logger.SetLogOutput — instead of
only reaching stderr via kernel_init_logging. This completes the one-knob logging
story: #399 unified the LEVEL across the Go binding lines and the kernel's Rust
lines (PECOBLR-3650) against the stderr sink; this replaces that sink with the
callback so the Rust lines land in the same writer as everything else.

The reverse-call machinery: a runtime/cgo.Handle round-trips the *logSink through
the C void* ctx (cgo pointer rules), and a defer recover() firewall converts any
panic into a dropped line (a panic across the cgo boundary would abort the
process) — the same shape a kernel->host token-provider callback would need. The
driver maps its own log level (resolveKernelLogArg, unchanged) and passes it as
the callback's level argument, so the kernel's Rust lines follow
DATABRICKS_LOG_LEVEL, not just RUST_LOG; DBSQL_KERNEL_DEBUG still defers to
RUST_LOG (NULL level).

The forwarding sink logs through a SNAPSHOT of the driver logger taken at install
and pinned to TraceLevel, for two reasons: (1) no double gating — the kernel
already filtered events against the level we passed it, so re-gating through the
live logger.Logger (at the driver level) would re-drop exactly the events the
DBSQL_KERNEL_DEBUG override was meant to surface; (2) no data race — the kernel
drain thread reads only its immutable snapshot rather than the mutable global
logger a concurrent SetLogLevel/SetLogOutput would rewrite. A non-Success install
is surfaced at Warn (visible at the default level), not the Debug-gated klog.

The two C-ABI logging routes share the one process-global subscriber and are
mutually exclusive; we install the callback, and a non-Success install (host
already installed a subscriber) is logged, never fatal to connect.

Level mapping and sink routing are pure Go (logforward.go, untagged) so they test
under CGO_ENABLED=0 — including the per-level mapping assertions and the
not-re-gated-by-driver-level property. The reverse-call round-trip, the recover
firewall (a panicking sink must not crash the process), the wrong-type/nil-ctx
guards, and delivery after a panic are exercised by tagged tests via a C invoke
seam.

Co-authored-by: Isaac
Signed-off-by: Mani Kaustubh Mathur <mani.mathur@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