"""Correlation ID context variable for distributed tracing. This module provides a :class:`contextvars.ContextVar` that stores the correlation ID for the current execution context. Background tasks inherit or explicitly set the correlation ID to enable log correlation across request/task boundaries. Usage in background tasks:: from app.utils.correlation import get_correlation_id, set_correlation_id async def my_background_task(correlation_id: str) -> None: token = set_correlation_id(correlation_id) try: log.info("task_started") # Logs include correlation_id finally: reset_correlation_id(token) For APScheduler jobs, pass the correlation ID through kwargs and call :func:`set_correlation_id` at the start of the async callback. """ from __future__ import annotations from contextvars import ContextVar from typing import TYPE_CHECKING if TYPE_CHECKING: from contextvars import Token #: Default correlation ID used when no parent request context exists. _DEFAULT_BG_CORRELATION_ID: str = "bg-task" #: ContextVar holding the current correlation ID. correlation_id_var: ContextVar[str] = ContextVar( "correlation_id", default=_DEFAULT_BG_CORRELATION_ID, ) def get_correlation_id() -> str: """Return the current correlation ID from context. Returns: The current correlation ID string. Returns ``"bg-task"`` if no correlation ID has been set in the current context. """ return correlation_id_var.get() def set_correlation_id(correlation_id: str) -> Token[str]: """Set the correlation ID for the current context. Args: correlation_id: The correlation ID to bind (typically passed from the triggering request). Returns: A :class:`contextvars.Token` that must be passed to :func:`reset_correlation_id` when the task completes. """ return correlation_id_var.set(correlation_id) def reset_correlation_id(token: Token[str]) -> None: """Reset the correlation ID to its previous value. Args: token: The token returned by :func:`set_correlation_id`. """ correlation_id_var.reset(token)