55 lines
1.7 KiB
Python
55 lines
1.7 KiB
Python
from __future__ import annotations
|
|
|
|
import contextvars
|
|
import json
|
|
import logging
|
|
from datetime import datetime, timezone
|
|
|
|
from celery import current_task
|
|
|
|
_request_id: contextvars.ContextVar[str] = contextvars.ContextVar('request_id', default='')
|
|
|
|
|
|
def set_request_id(value: str) -> None:
|
|
_request_id.set(value or '')
|
|
|
|
|
|
def get_request_id() -> str:
|
|
return _request_id.get('')
|
|
|
|
|
|
def clear_request_id() -> None:
|
|
_request_id.set('')
|
|
|
|
|
|
class RequestContextFilter(logging.Filter):
|
|
def filter(self, record: logging.LogRecord) -> bool:
|
|
record.request_id = get_request_id()
|
|
task = current_task
|
|
request = getattr(task, 'request', None) if task else None
|
|
record.task_id = getattr(request, 'id', '') if request else ''
|
|
record.task_name = getattr(task, 'name', '') if task else ''
|
|
return True
|
|
|
|
|
|
class JsonFormatter(logging.Formatter):
|
|
def format(self, record: logging.LogRecord) -> str:
|
|
payload = {
|
|
'timestamp': datetime.fromtimestamp(record.created, tz=timezone.utc).isoformat(),
|
|
'level': record.levelname,
|
|
'logger': record.name,
|
|
'message': record.getMessage(),
|
|
}
|
|
request_id = getattr(record, 'request_id', '') or ''
|
|
task_id = getattr(record, 'task_id', '') or ''
|
|
task_name = getattr(record, 'task_name', '') or ''
|
|
if request_id:
|
|
payload['request_id'] = request_id
|
|
if task_id:
|
|
payload['task_id'] = task_id
|
|
if task_name:
|
|
payload['task_name'] = task_name
|
|
if record.exc_info:
|
|
payload['exception'] = self.formatException(record.exc_info)
|
|
return json.dumps(payload, ensure_ascii=False)
|