Skip to content

fix: surface WARNING/ERROR logs by default instead of suppressing them#1264

Merged
jschoedl merged 2 commits into
mainfrom
fix/default-warning-logging
May 27, 2026
Merged

fix: surface WARNING/ERROR logs by default instead of suppressing them#1264
jschoedl merged 2 commits into
mainfrom
fix/default-warning-logging

Conversation

@jschoedl
Copy link
Copy Markdown
Collaborator

Problem

Every CLI command calls enable_debug_logging(debug) as its first action. When --debug is off, that function added a logging.NullHandler to the root logger, which disables Python's lastResort handler — so all logging.warning/logging.error calls in the codebase were silent by default.

The primary output of each command was unaffected (it goes through the rich console on stdout), but the logging-channel diagnostics were lost, e.g.:

datacontract import sql --source t.sql --dialect postgres            # no warning shown
datacontract import sql --source t.sql --dialect postgres --debug    # warning appears on stderr

The sql_importer "placeholder connection values" warning (and resolve.py / excel_importer / spark_importer warnings) only appeared with --debug.

Fix

enable_debug_logging now defaults the root level to WARNING on stderr (so stdout stays clean for piped import/export YAML), and raises it to DEBUG with --debug. Noisy third-party loggers (snowflake.connector, py4j, pyspark, urllib3, soda) are pinned to ERROR to preserve the original intent of the NullHandler (muting library chatter) without blanket-suppressing everything.

Why test/ci/lint are gated

Run.log_info/warn/error deliberately emit to two sinks: the structured run.logs record (rendered to the console, exported to JUnit, published) and stdlib logging (the live stream, and the only output for library callers of DataContract(...).test()). For test/ci/lint, which render run.logs to the console themselves, un-suppressing stderr would print the same WARNING/ERROR twice. Those three commands therefore pass otherwise_disable_stderr=True to keep the old NullHandler behavior. Commands that don't render run.logs (import, export, changelog, catalog, dbt, publish) get the WARNING-on-stderr default — a clean win with no duplication.

Verification

Ran every command before/after, capturing stdout and stderr separately:

  • import sql: warning now on stderr; piped stdout YAML stays clean (warning not in the file).
  • lint/test/ci: failure/warnings shown once (on stdout, as before) — no doubling on stderr.
  • --debug: WARNING/ERROR/DEBUG still on stderr for all commands.
  • Test suite: 743 passed, 13 skipped (the only errors are Docker-unavailable integration tests, unrelated).

🤖 Generated with Claude Code

jschoedl and others added 2 commits May 27, 2026 13:13
Every command called enable_debug_logging(debug), which added a
logging.NullHandler to the root logger when --debug was off. That
disabled Python's lastResort handler, silencing all logging.warning/
logging.error output across the codebase unless --debug was passed.

Default the root level to WARNING (on stderr) so diagnostics like the
`import sql` placeholder-connection warning are visible. test/ci/lint
render run.logs to the console themselves and would otherwise print the
mirrored Run.log_* records twice, so they pass otherwise_disable_stderr
to keep the old NullHandler behavior. Noisy third-party loggers are
pinned to ERROR to preserve the original intent of muting library chatter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jschoedl jschoedl merged commit b189fef into main May 27, 2026
9 checks passed
@jschoedl jschoedl deleted the fix/default-warning-logging branch May 27, 2026 11:21
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