-
Notifications
You must be signed in to change notification settings - Fork 84
Improve Logging Serialization #6891
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
| extra_dict = { | ||
| **standard_dict, | ||
| "format": log_format + " | <dim>{extra}</dim>", | ||
| "filter": lambda logRecord: bool(logRecord["extra"]), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty sure this was always truthy. Before I swapped it for the has_custom_extra function, the Celery mingle messages weren't showing up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
This PR improves logging consistency by intercepting standard library logs from Celery, SQLAlchemy, and other libraries, routing them through Loguru for unified formatting.
Key changes:
- Added
InterceptHandlerclass to capture stdlib logging and route through Loguru - Connected to Celery's
setup_loggingsignal to prevent it from overriding Loguru configuration - Fixed color output when using JSON serialization (colors are now disabled for JSON)
- Replaced
print()statements with properlog.info()calls in config and database modules - Added comprehensive test coverage for the InterceptHandler
Potential issue:
- The frame traversal logic in
InterceptHandler.emit()may not correctly identify the caller when logs originate from logging module subfiles (likelogging/handlers.py), as it only checks againstlogging.__file__which points tologging/__init__.py
Confidence Score: 4/5
- This PR is safe to merge with minimal risk after addressing the frame traversal logic issue
- The PR successfully improves logging consistency with good test coverage and clean refactoring. The only concern is the frame traversal logic in InterceptHandler which may not correctly identify caller info in all scenarios when logs come from logging module subfiles, though this is unlikely to cause runtime failures - just potentially incorrect file/line info in logs
- src/fides/api/util/logger.py - Review the frame traversal logic in InterceptHandler.emit()
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| src/fides/api/util/logger.py | 4/5 | Adds InterceptHandler to route stdlib logs through Loguru; disables color when using JSON serialization; improves filter logic for extra context |
| src/fides/api/tasks/init.py | 5/5 | Adds signal handler to prevent Celery from overriding Loguru configuration |
5 files reviewed, 1 comment
Codecov Report❌ Patch coverage is
❌ Your patch status has failed because the patch coverage (81.25%) is below the target coverage (100.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #6891 +/- ##
=======================================
Coverage 87.30% 87.30%
=======================================
Files 524 524
Lines 34355 34382 +27
Branches 3956 3957 +1
=======================================
+ Hits 29992 30017 +25
- Misses 3503 3505 +2
Partials 860 860 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This comment was marked as resolved.
This comment was marked as resolved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
This PR improves logging consistency by intercepting standard library logs (from Celery, SQLAlchemy, etc.) and routing them through Loguru for unified formatting and serialization.
Key changes:
- Added
InterceptHandlerclass to capture stdlib logs and route through Loguru - Connected to Celery's
setup_loggingsignal to prevent Celery from overriding logging config - Fixed colorization to be disabled when using JSON serialization
- Improved filter functions to properly check for custom extra context
- Enabled Python warnings capture through logging
Issues found:
- Path logic in
InterceptHandler.emit()uses forward-slash splitting that will fail on Windows, causing incorrect stack depth calculation for all intercepted logs
Confidence Score: 3/5
- This PR is safe to merge on Linux/Unix systems but has a critical path handling bug for Windows environments
- Score reflects a well-designed logging improvement with proper Celery integration, but the Windows path compatibility issue in the InterceptHandler could cause all logs to have incorrect caller information on Windows, affecting log quality and debugging capability
- Pay close attention to
src/fides/api/util/logger.py- the path logic needs to useos.path.dirname()instead of string splitting for cross-platform compatibility
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| src/fides/api/util/logger.py | 3/5 | Added InterceptHandler to unify logging through Loguru and fixed JSON colorization; path logic has Windows compatibility issue |
1 file reviewed, 1 comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
This PR improves logging consistency by intercepting standard library logs (Celery, SQLAlchemy, etc.) and routing them through Loguru for uniform formatting and serialization.
Key changes:
- Added
InterceptHandlerclass to capture stdlib logging and redirect to Loguru - Added Celery signal handler to prevent Celery from overriding logging config
- Fixed colorization to be disabled when JSON serialization is enabled
- Replaced lambda filters with named functions for better code clarity
- Changed
print()statements to properlogger.info()calls
The implementation addresses two previously identified issues with the frame traversal and path logic that have been resolved with os.path.dirname() and os.sep.
Confidence Score: 4/5
- This PR is safe to merge with low risk of regressions
- The changes are well-tested with comprehensive unit tests covering the InterceptHandler functionality. The implementation follows best practices for log interception and the previous path logic issues have been addressed. Minor deduction for the potential impact on logging behavior across the entire application
- No files require special attention
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| src/fides/api/util/logger.py | 4/5 | Added InterceptHandler to capture stdlib logs and route through Loguru, improved colorize logic for JSON serialization, replaced lambda filters with named functions |
2 files reviewed, no comments
|
Deployment failed with the following error: View Documentation: https://vercel.com/docs/two-factor-authentication |
de53e32 to
7d2d493
Compare
CHANGELOG.md
Outdated
|
|
||
| ### Changed | ||
| - Updated filter modal in new privacy request screen to store filters as query params in url [#6818](https://github.com/ethyca/fides/pull/6818) | ||
| - Updated logging configuration to intercept all standard library logs and route them through Loguru[#6891](https://github.com/ethyca/fides/pull/6891) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| - Updated logging configuration to intercept all standard library logs and route them through Loguru[#6891](https://github.com/ethyca/fides/pull/6891) | |
| - Updated logging configuration to intercept all standard library logs and route them through Loguru [#6891](https://github.com/ethyca/fides/pull/6891) |
galvana
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes look good, let's keep this one moving along. I went ahead and resolved the merge conflicts since they were caused by some recent changes I made to database.py
1ab8ea4 to
9d3eb20
Compare
Description Of Changes
This PR addresses some logging issues where certain logs were not getting logged in the loguru format, but rather whatever native logging format their libraries were set up with. Most notably this should cover Celery.
Doing so helps to improve logging consistency, which is especially helpful when ingesting logs into a logging service like Datadog.
Code Changes
Steps to Confirm
Here are some examples of what the worker logs looked like and what they'll look like now.
BEFORE
2025-10-30 14:08:55 {"text": "2025-10-30 19:08:54.999 | INFO | fides.api.worker:log_celery_setup:102 - Celery connection setup complete | {'celery_details': {'hostname': 'celery@5c3d786ecf84', 'version': '5.5.3 (immunity)', 'app': 'fides.api.tasks:0xffff6d1defe0', 'transport': 'redis://:@redis:6379//', 'results': 'redis://:@redis:6379/', 'concurrency': '2', 'queues': 'fides|fidesops.messaging|fides.privacy_preferences|fides.dsr|fidesplus.consent_webhooks|fidesplus.discovery_monitors_detection|fidesplus.discovery_monitors_classification|fidesplus.discovery_monitors_promotion'}}\n", "record": {"elapsed": {"repr": "0:00:16.177022", "seconds": 16.177022}, "exception": null, "extra": {"celery_details": {"hostname": "celery@5c3d786ecf84", "version": "5.5.3 (immunity)", "app": "fides.api.tasks:0xffff6d1defe0", "transport": "redis://:@redis:6379//", "results": "redis://:@redis:6379/", "concurrency": "2", "queues": "fides|fidesops.messaging|fides.privacy_preferences|fides.dsr|fidesplus.consent_webhooks|fidesplus.discovery_monitors_detection|fidesplus.discovery_monitors_classification|fidesplus.discovery_monitors_promotion"}}, "file": {"name": "init.py", "path": "/fidesplus/ethyca-fides/src/fides/api/worker/init.py"}, "function": "log_celery_setup", "level": {"icon": "ℹ️", "name": "INFO", "no": 20}, "line": 102, "message": "Celery connection setup complete", "module": "init", "name": "fides.api.worker", "process": {"id": 70, "name": "MainProcess"}, "thread": {"id": 281473004183584, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:08:54.999411+00:00", "timestamp": 1761851334.999411}}}
2025-10-30 14:08:56 [2025-10-30 19:08:56,147: INFO/MainProcess] Connected to redis://:**@redis:6379//
2025-10-30 14:08:56 [2025-10-30 19:08:56,153: INFO/MainProcess] mingle: searching for neighbors
2025-10-30 14:08:57 [2025-10-30 19:08:57,162: INFO/MainProcess] mingle: all alone
2025-10-30 14:08:57 [2025-10-30 19:08:57,175: INFO/MainProcess] celery@5c3d786ecf84 ready.
AFTER
2025-10-30 14:13:55 {"text": "2025-10-30 19:13:55.228 | DEBUG | celery.bootsteps:_debug:259 - | Consumer: Starting Connection\n", "record": {"elapsed": {"repr": "0:00:14.838384", "seconds": 14.838384}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "_debug", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 259, "message": "| Consumer: Starting Connection", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:55.228718+00:00", "timestamp": 1761851635.228718}}}
2025-10-30 14:13:55 {"text": "2025-10-30 19:13:55.257 | INFO | celery.worker.consumer.connection:start:22 - Connected to redis://:@redis:6379//\n", "record": {"elapsed": {"repr": "0:00:14.867344", "seconds": 14.867344}, "exception": null, "extra": {}, "file": {"name": "connection.py", "path": "/usr/local/lib/python3.10/site-packages/celery/worker/consumer/connection.py"}, "function": "start", "level": {"icon": "ℹ️", "name": "INFO", "no": 20}, "line": 22, "message": "Connected to redis://:@redis:6379//", "module": "connection", "name": "celery.worker.consumer.connection", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:55.257678+00:00", "timestamp": 1761851635.257678}}}
2025-10-30 14:13:55 {"text": "2025-10-30 19:13:55.260 | DEBUG | celery.bootsteps:start:117 - ^-- substep ok\n", "record": {"elapsed": {"repr": "0:00:14.870206", "seconds": 14.870206}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "start", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 117, "message": "^-- substep ok", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:55.260540+00:00", "timestamp": 1761851635.26054}}}
2025-10-30 14:13:55 {"text": "2025-10-30 19:13:55.262 | DEBUG | celery.bootsteps:_debug:259 - | Consumer: Starting Events\n", "record": {"elapsed": {"repr": "0:00:14.871811", "seconds": 14.871811}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "_debug", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 259, "message": "| Consumer: Starting Events", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:55.262145+00:00", "timestamp": 1761851635.262145}}}
2025-10-30 14:13:55 {"text": "2025-10-30 19:13:55.292 | DEBUG | celery.bootsteps:start:117 - ^-- substep ok\n", "record": {"elapsed": {"repr": "0:00:14.901767", "seconds": 14.901767}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "start", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 117, "message": "^-- substep ok", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:55.292101+00:00", "timestamp": 1761851635.292101}}}
2025-10-30 14:13:55 {"text": "2025-10-30 19:13:55.293 | DEBUG | celery.bootsteps:_debug:259 - | Consumer: Starting Mingle\n", "record": {"elapsed": {"repr": "0:00:14.902812", "seconds": 14.902812}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "_debug", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 259, "message": "| Consumer: Starting Mingle", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:55.293146+00:00", "timestamp": 1761851635.293146}}}
2025-10-30 14:13:55 {"text": "2025-10-30 19:13:55.293 | INFO | celery.worker.consumer.mingle:sync:40 - mingle: searching for neighbors\n", "record": {"elapsed": {"repr": "0:00:14.903514", "seconds": 14.903514}, "exception": null, "extra": {}, "file": {"name": "mingle.py", "path": "/usr/local/lib/python3.10/site-packages/celery/worker/consumer/mingle.py"}, "function": "sync", "level": {"icon": "ℹ️", "name": "INFO", "no": 20}, "line": 40, "message": "mingle: searching for neighbors", "module": "mingle", "name": "celery.worker.consumer.mingle", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:55.293848+00:00", "timestamp": 1761851635.293848}}}
2025-10-30 14:13:56 {"text": "2025-10-30 19:13:56.326 | INFO | celery.worker.consumer.mingle:sync:49 - mingle: all alone\n", "record": {"elapsed": {"repr": "0:00:15.935805", "seconds": 15.935805}, "exception": null, "extra": {}, "file": {"name": "mingle.py", "path": "/usr/local/lib/python3.10/site-packages/celery/worker/consumer/mingle.py"}, "function": "sync", "level": {"icon": "ℹ️", "name": "INFO", "no": 20}, "line": 49, "message": "mingle: all alone", "module": "mingle", "name": "celery.worker.consumer.mingle", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:56.326139+00:00", "timestamp": 1761851636.326139}}}
2025-10-30 14:13:56 {"text": "2025-10-30 19:13:56.327 | DEBUG | celery.bootsteps:start:117 - ^-- substep ok\n", "record": {"elapsed": {"repr": "0:00:15.937072", "seconds": 15.937072}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "start", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 117, "message": "^-- substep ok", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:56.327406+00:00", "timestamp": 1761851636.327406}}}
2025-10-30 14:13:56 {"text": "2025-10-30 19:13:56.328 | DEBUG | celery.bootsteps:_debug:259 - | Consumer: Starting Gossip\n", "record": {"elapsed": {"repr": "0:00:15.938101", "seconds": 15.938101}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "_debug", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 259, "message": "| Consumer: Starting Gossip", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:56.328435+00:00", "timestamp": 1761851636.328435}}}
2025-10-30 14:13:56 {"text": "2025-10-30 19:13:56.341 | DEBUG | celery.bootsteps:start:117 - ^-- substep ok\n", "record": {"elapsed": {"repr": "0:00:15.951336", "seconds": 15.951336}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "start", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 117, "message": "^-- substep ok", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:56.341670+00:00", "timestamp": 1761851636.34167}}}
2025-10-30 14:13:56 {"text": "2025-10-30 19:13:56.342 | DEBUG | celery.bootsteps:_debug:259 - | Consumer: Starting Heart\n", "record": {"elapsed": {"repr": "0:00:15.951901", "seconds": 15.951901}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "_debug", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 259, "message": "| Consumer: Starting Heart", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:56.342235+00:00", "timestamp": 1761851636.342235}}}
2025-10-30 14:13:56 {"text": "2025-10-30 19:13:56.347 | DEBUG | celery.bootsteps:start:117 - ^-- substep ok\n", "record": {"elapsed": {"repr": "0:00:15.957161", "seconds": 15.957161}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "start", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 117, "message": "^-- substep ok", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:56.347495+00:00", "timestamp": 1761851636.347495}}}
2025-10-30 14:13:56 {"text": "2025-10-30 19:13:56.348 | DEBUG | celery.bootsteps:_debug:259 - | Consumer: Starting Tasks\n", "record": {"elapsed": {"repr": "0:00:15.958020", "seconds": 15.95802}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "_debug", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 259, "message": "| Consumer: Starting Tasks", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:56.348354+00:00", "timestamp": 1761851636.348354}}}
2025-10-30 14:13:56 {"text": "2025-10-30 19:13:56.387 | DEBUG | celery.bootsteps:start:117 - ^-- substep ok\n", "record": {"elapsed": {"repr": "0:00:15.996838", "seconds": 15.996838}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "start", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 117, "message": "^-- substep ok", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:56.387172+00:00", "timestamp": 1761851636.387172}}}
2025-10-30 14:13:56 {"text": "2025-10-30 19:13:56.387 | DEBUG | celery.bootsteps:_debug:259 - | Consumer: Starting Control\n", "record": {"elapsed": {"repr": "0:00:15.997428", "seconds": 15.997428}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "_debug", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 259, "message": "| Consumer: Starting Control", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:56.387762+00:00", "timestamp": 1761851636.387762}}}
2025-10-30 14:13:56 {"text": "2025-10-30 19:13:56.392 | DEBUG | celery.bootsteps:start:117 - ^-- substep ok\n", "record": {"elapsed": {"repr": "0:00:16.002032", "seconds": 16.002032}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "start", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 117, "message": "^-- substep ok", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:56.392366+00:00", "timestamp": 1761851636.392366}}}
2025-10-30 14:13:56 {"text": "2025-10-30 19:13:56.392 | DEBUG | celery.bootsteps:_debug:259 - | Consumer: Starting event loop\n", "record": {"elapsed": {"repr": "0:00:16.002270", "seconds": 16.00227}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "_debug", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 259, "message": "| Consumer: Starting event loop", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:56.392604+00:00", "timestamp": 1761851636.392604}}}
2025-10-30 14:13:56 {"text": "2025-10-30 19:13:56.392 | DEBUG | celery.bootsteps:_debug:259 - | Worker: Hub.register Pool...\n", "record": {"elapsed": {"repr": "0:00:16.002615", "seconds": 16.002615}, "exception": null, "extra": {}, "file": {"name": "bootsteps.py", "path": "/usr/local/lib/python3.10/site-packages/celery/bootsteps.py"}, "function": "_debug", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 259, "message": "| Worker: Hub.register Pool...", "module": "bootsteps", "name": "celery.bootsteps", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:56.392949+00:00", "timestamp": 1761851636.392949}}}
2025-10-30 14:13:56 {"text": "2025-10-30 19:13:56.397 | INFO | celery.apps.worker:on_consumer_ready:176 - celery@2427a933df37 ready.\n", "record": {"elapsed": {"repr": "0:00:16.007365", "seconds": 16.007365}, "exception": null, "extra": {}, "file": {"name": "worker.py", "path": "/usr/local/lib/python3.10/site-packages/celery/apps/worker.py"}, "function": "on_consumer_ready", "level": {"icon": "ℹ️", "name": "INFO", "no": 20}, "line": 176, "message": "celery@2427a933df37 ready.", "module": "worker", "name": "celery.apps.worker", "process": {"id": 69, "name": "MainProcess"}, "thread": {"id": 281473580527648, "name": "MainThread"}, "time": {"repr": "2025-10-30 19:13:56.397699+00:00", "timestamp": 1761851636.397699}}}
Pre-Merge Checklist
CHANGELOG.mdupdatedmaindowngrade()migration is correct and works