Use cosmos.log.get_logger consistently#2670
Conversation
The rest of the codebase (31 modules) instantiates loggers via cosmos.log.get_logger so messages carry the (astronomer-cosmos) prefix when rich_logging is enabled. A few outliers still used the stdlib logger directly, breaking that branding and bypassing scoped log-level configuration: - cosmos/operators/_asynchronous/base.py: dropped an unused `log = logging.getLogger(__name__)` (no callers in-module or via imports). - cosmos/profiles/snowflake/user_privatekey_file.py: switched `logger` to get_logger; it is used for the passphrase warning. - cosmos/dbt/parser/output.py: replaced a module-level `logging.error(...)` call (which hit the root logger) with a proper `logger.error(...)` via a module-level get_logger instance. - cosmos/plugin/airflow3.py: replaced four module-level `logging.exception(...)` root-logger calls similarly. No functional change beyond the log prefix and proper logger scoping. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cosmos.log.get_logger consistently
There was a problem hiding this comment.
Pull request overview
This PR standardizes logging across a few remaining outlier modules by switching from stdlib/root logger usage to cosmos.log.get_logger, ensuring log messages consistently include the (astronomer-cosmos) prefix when rich_logging is enabled and participate in Cosmos-scoped log configuration.
Changes:
- Replace stdlib/root logger usage with
get_logger(__name__)in modules that emit log messages. - Remove an unused
loggingimport and unused module-level logger in the async operator factory module. - Convert module-level
logging.exception/error(...)calls to use a module-level Cosmos logger instance.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
cosmos/profiles/snowflake/user_privatekey_file.py |
Switches module logger to get_logger for the passphrase warning. |
cosmos/plugin/airflow3.py |
Introduces a module-level Cosmos logger and replaces root-logger exception calls with logger.exception(...). |
cosmos/operators/_asynchronous/base.py |
Removes unused stdlib logger setup (logging import and unused log). |
cosmos/dbt/parser/output.py |
Adds module-level Cosmos logger and replaces a root-logger error call with logger.error(...). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2670 +/- ##
=======================================
Coverage 98.02% 98.02%
=======================================
Files 105 105
Lines 7844 7844
=======================================
Hits 7689 7689
Misses 155 155 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
tatiana
left a comment
There was a problem hiding this comment.
Thanks for improving this, @pankajastro ! Would it be worth updating our agents' CLAUDE.md with recommendations on how to instantiate log, so we avoid similar patterns in the future? Happy for this to be addressed in a follow-up PR.
Per PR #2670, all modules should instantiate loggers via cosmos.log.get_logger so messages carry the (astronomer-cosmos) prefix when rich_logging is on and pick up scoped log-level configuration. Calling logging.getLogger or the root logger directly bypasses both. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Created PR: #2679 |
The Logging section told contributors to "get loggers via `cosmos.log.get_logger`" unconditionally, which would lead someone working in an operator to add a module-level `get_logger` — the exact inconsistency #1157 set out to fix. Scope that guidance to library/module-level code and state the operator rule: inside operators and hooks (anything with `LoggingMixin`), log via `self.log` so messages land in the per-task-instance log shown in the Airflow UI. Examples updated to show both cases. This locks in the outcome of the logging cleanup (#2670, #2680, #2681) so it doesn't silently regress.
The rest of the codebase (31 modules) instantiates loggers via cosmos.log.get_logger so messages carry the (astronomer-cosmos) prefix when rich_logging is enabled. A few outliers still used the stdlib logger directly, breaking that branding and bypassing scoped log-level configuration:
log = logging.getLogger(__name__)(no callers in-module or via imports).loggerto get_logger; it is used for the passphrase warning.logging.error(...)call (which hit the root logger) with a properlogger.error(...)via a module-level get_logger instance.logging.exception(...)root-logger calls similarly.closes: #1157