Skip to content

feat: add execution_id support for async stack #377

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

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

taeold
Copy link
Contributor

@taeold taeold commented Jun 15, 2025

Summary

Adds execution_id support for the async/ASGI stack (Starlette/Uvicorn) to match the existing functionality in the sync/WSGI stack (Flask/Gunicorn).

Key Changes

  • Added contextvars support: Use contextvars.ContextVar for async-safe execution context storage
  • Created AsgiMiddleware: Automatically injects execution_id header for ASGI applications
  • Updated LoggingHandlerAddExecutionId: Now retrieves context from both Flask g and contextvars
  • Added async decorators: set_execution_context_async decorator for async request handlers
  • Integrated with aio module: Execution_id functionality now works with async cloud functions
  • Preserved context on exceptions: Context remains available to exception handlers for proper logging
  • Added comprehensive tests: New test file test_execution_id_async.py with full coverage

taeold added 7 commits June 15, 2025 11:53
- Add contextvars support to execution_id.py for async-safe context storage
- Create AsgiMiddleware class to inject execution_id into ASGI requests
- Add set_execution_context_async decorator for both sync and async functions
- Update LoggingHandlerAddExecutionId to support both Flask g and contextvars
- Integrate execution_id support in aio/__init__.py with proper exception handling
- Add comprehensive async tests matching sync test functionality
- Follow Starlette best practices for exception handling

The implementation enables automatic execution_id injection and logging for async
functions when LOG_EXECUTION_ID=true, matching the existing sync stack behavior.
- Remove try/catch blocks from wrapper functions
- Centralize exception logging in _crash_handler
- Extract execution_id directly from request headers in crash handler
- Temporarily set context when logging exceptions to ensure execution_id is included
- This approach is cleaner and more similar to Flask's centralized exception handling
- Move imports to top of file instead of inside functions
- Extract common header parsing logic into _extract_context_from_headers helper
- Reduce code duplication between sync and async decorators
- Add comment explaining why crash handler needs to extract context from headers
- This addresses the context reset issue where decorators clean up before exception handlers run
- Don't reset context on exception, only on successful completion
- This allows exception handlers to access execution_id naturally
- Simplify crash handler since context is now available
- Rely on Python's automatic contextvar cleanup when task completes
- Each request runs in its own task, so no risk of context leakage

This is more correct and follows the principle that context should be
available throughout the entire request lifecycle, including error handling.
- Format code with black for consistent style
- Sort imports with isort for better organization
- All linting checks now pass
@taeold taeold changed the title Add execution_id support for async stack feat: add execution_id support for async stack Jun 15, 2025
taeold added 12 commits June 15, 2025 12:59
The AsgiMiddleware class and set_execution_context_async function in
execution_id.py require Python 3.8+ due to async dependencies. These
are now excluded from coverage calculations in Python 3.7 environments.
- Use contextvars.copy_context() to properly propagate execution context in async functions
- Implement AsyncExecutionIdHandler to handle JSON logging with execution_id
- Redirect logging output from stderr to stdout for consistency
- Add build dependency to dev dependencies
- Update tests to reflect new logging output location
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