Coverage for paperless/logging.py: 100%
11 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 09:07 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 09:07 +0000
1from __future__ import annotations
3import logging
4from contextvars import ContextVar
6consume_task_id: ContextVar[str] = ContextVar("consume_task_id", default="")
9class ConsumeTaskFormatter(logging.Formatter):
10 """
11 Logging formatter that prepends a short task correlation ID to messages
12 emitted during document consumption.
14 The ID is the first 8 characters of the Celery task UUID, set via the
15 ``consume_task_id`` ContextVar at the entry of ``consume_file``. When
16 the ContextVar is empty (any log outside a consume task) no prefix is
17 added and the output is identical to the standard verbose format.
18 """
20 def __init__(self) -> None:
21 super().__init__(
22 fmt="[{asctime}] [{levelname}] [{name}] {task_prefix}{message}",
23 style="{",
24 validate=False, # {task_prefix} is not a standard LogRecord attribute, so Python's
25 # init-time format-string validation would raise ValueError without
26 # this. Runtime safety comes from format() always setting
27 # record.task_prefix before calling super().format().
28 )
30 def format(self, record: logging.LogRecord) -> str:
31 task_id = consume_task_id.get()
32 record.task_prefix = f"[{task_id}] " if task_id else ""
33 return super().format(record)