fix: log execution errors server-side (stream, Lakebase, SQL Warehouse)#255
fix: log execution errors server-side (stream, Lakebase, SQL Warehouse)#255jamesbroadhead merged 8 commits intomainfrom
Conversation
Query execution errors were only sent to the browser via SSE but never logged server-side, making them invisible in `databricks apps logs`. Add logger.error() call in the StreamManager catch block so errors appear in application logs for debugging and monitoring. Fixes #243
Extends the same pattern from stream-manager to connector catch blocks that previously only recorded errors in telemetry spans. Co-authored-by: Isaac
Log only error.message and error code instead of the full error object (%O) to avoid leaking SQL query strings into server logs. pg errors store the raw query in a .query property which %O would dump. Co-authored-by: Isaac
Verifies that when connectors or stream manager log errors, only the error message and code appear in output — not the raw SQL statement or parameter values from the error object. Co-authored-by: Isaac
Co-authored-by: Isaac
MarioCadenas
left a comment
There was a problem hiding this comment.
A few things before merge:
[Required] SQL Warehouse: asymmetric abort gating — packages/appkit/src/connectors/sql-warehouse/client.ts
The new logger.error in executeStatement (~L240) sits inside the existing if (!isAborted) { ... } block, but the one in _pollForStatementResult (~L385) is not gated. The same failure bubbling through both layers will log in one and stay silent in the other depending on cancel state. Pick one policy and apply it uniformly.
[Recommended] StreamManager: aborts will spam error logs — packages/appkit/src/stream/stream-manager.ts:265
_categorizeError maps AbortError → STREAM_ABORTED, which is a normal client cancel (user navigates away). After this PR every cancel becomes a logger.error("Stream execution failed: ...") line. Suggest branching on errorCode === STREAM_ABORTED and logging at info/debug, or skipping.
[Follow-up] pg .message is still a leak surface
The redaction tests use synthetic Error objects with custom .query/.parameters. Realistic pg errors like invalid input syntax for type uuid: "<sensitive>" put the leak directly in .message, which we do log. Either allowlist by error.code (log a stable class label instead of free-form message) or at least add one test with a realistic pg-shaped error (code: '22P02', message containing the rejected literal) so a future change can't silently regress to String(error). This is the 6th time error-message-leakage has surfaced in reviews of this repo — probably worth a stricter policy.
Nit: docs/static/appkit-ui/styles.gen.css has unrelated regenerated lines (removed .max-w-full, added [&_table]:overflow-x-auto, etc.). Looks like a stale rebuild — drop from this PR?
Otherwise direction is right and the proactive redaction tests are appreciated.
- Quiet StreamManager: log STREAM_ABORTED at info instead of error so normal client cancels do not produce error-level log spam. - Make SQL Warehouse abort logging uniform: drop logger.error from _pollForStatementResult; let executeStatement be the single (gated) point of error logging so the same failure is never double-logged and never silent depending on cancel state. - Lock in pg-shaped error redaction: add a test using a realistic pg error (code 22P02 with a sensitive literal in .message) so a future change to e.g. String(error) cannot silently re-introduce error.query or error.parameters into the log. - Reorder imports per biome organize-imports. Co-authored-by: Isaac Signed-off-by: James Broadhead <jamesbroadhead@gmail.com>
|
@MarioCadenas — pushed
Re-requesting your review. |
Summary
databricks apps logs, hindering debugging and monitoringlogger.error()calls in error paths across:_processGeneratorInBackground()query()andtransaction()catch blocksexecuteStatement()and_pollForStatementResult()catch blocksWhat's NOT changed
logger.error()on all error pathstraced()are re-thrown and logged by the files plugin's_handleApiError()Test plan
databricks apps logsFixes #243
This pull request was AI-assisted by Isaac.