Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions app/api/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from app.core.db import get_db_session
from app.core.enums import UserStatus
from app.core.config import get_settings
from app.core.logging import set_request_user_email
from app.core.security import decode_access_token
from app.repositories.user import UserRepository
from app.schemas.auth import TokenPayload, UserRead
Expand Down Expand Up @@ -52,7 +51,6 @@ def get_current_user(
span = trace.get_current_span()
span.set_attribute("user.id", str(resolved.id))
span.set_attribute("user.email", resolved.email)
set_request_user_email(resolved.email)
return resolved


Expand Down
17 changes: 8 additions & 9 deletions app/core/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,9 @@

import json
import logging
from contextvars import ContextVar

from opentelemetry import trace

_user_email_var: ContextVar[str] = ContextVar('user_email', default='')


def set_request_user_email(email: str) -> None:
_user_email_var.set(email)


_SKIP_ATTRS = frozenset((
"name", "msg", "args", "levelname", "levelno",
"pathname", "filename", "module", "exc_info",
Expand All @@ -41,7 +33,14 @@ def format(self, record: logging.LogRecord) -> str:
"span_id": format(ctx.span_id, "016x") if ctx.is_valid else "",
}

user_email = _user_email_var.get()
# Read off the span's attributes rather than a ContextVar: the
# dependency that resolves the user runs in FastAPI's threadpool
# (sync def), and contextvars.copy_context() there means any
# ContextVar.set() inside it never propagates back to the request's
# context. The span object itself is shared by reference across
# that boundary, so attribute mutations on it are visible everywhere.
attributes = getattr(span, "attributes", None) or {}
user_email = attributes.get("user.email")
if user_email:
entry["user_email"] = user_email

Expand Down
Loading