События Struclog неправильно отображаются в консоли при выполнении задач Celery
Я использую structlog
и celery
в своем Django приложении и у меня возникают трудности при логировании задач с помощью structlog в консоли. Действительно, события не выравниваются должным образом при выводе в консоль во время выполнения задачи Celery. Когда выполняется больше задач, логи становятся едва читаемыми. clear_contextvars
и reset_contextvars
в верхней части задач не меняют проблему.
Какова может быть причина этого перекоса?
Консоль
celery_worker-1 | 2022-10-09T12:25:57.251196Z [info ] Fetch orders complete [account.tasks] account=Anna
celery_worker-1 | 2022-10-09T12:25:57.934244Z [info ] Fetch trades [account.tasks] account=Anna length=0 symbol=BBB
celery_worker-1 | 2022-10-09T12:25:58.896769Z [info ] Fetch trades [account.tasks] account=Anna length=1 symbol=BBB
celery_worker-1 | 2022-10-09T12:25:58.911502Z [info ] Fetch trades complete [account.tasks] account=Anna
celery_worker-1 | 2022-10-09T12:25:58.974451Z [info ] Update assets inventory [2022-10-09T12:25:58.976925Zpnl.tasks] account=Anna
celery_worker-1 | [info ] Fetch orders [account.tasks] account=Nico
celery_worker-1 | 2022-10-09T12:25:58.989326Z2022-10-09T12:25:58.990257Z [info ] Update contracts inventory [pnl.tasks] account=Anna
celery_worker-1 | [info ] Update assets inventory no required [pnl.tasks] account=Anna
celery_worker-1 | 2022-10-09T12:25:59.011112Z [info ] Update contracts inventory no required [pnl.tasks] account=Anna
celery_worker-1 | 2022-10-09T12:26:00.380746Z [info ] Fetch orders complete [account.tasks] account=Nico
celery_worker-1 | 2022-10-09T12:26:01.222383Z [info ] Fetch trades [account.tasks] account=Nico length=0 symbol=ABC
celery_worker-1 | 2022-10-09T12:26:01.570339Z [info ] Fetch trades [account.tasks] account=Nico length=1 symbol=ABC
celery_worker-1 | 2022-10-09T12:26:01.588788Z [info ] Fetch trades complete [account.tasks] account=Nico
Версия пакетов
celery==5.2.7 # latest
django-structlog==3.0.1 # latest
structlog==22.1.0 # latest
tasks.py
import structlog
logger = structlog.get_logger(__name__)
@app.task(bind=True, name='Update_inventory')
def update_inventory(self, pk):
account = Account.objects.get(pk=pk)
log_asset = logger.bind(account=account.name)
log_asset.info('Log event')
...
celery.py
import structlog
from django_structlog.celery.steps import DjangoStructLogInitStep
app.steps['worker'].add(DjangoStructLogInitStep)
@setup_logging.connect
def receiver_setup_logging(loglevel, logfile, format, colorize, **kwargs):
from logging.config import dictConfig
from django.conf import settings
dictConfig(settings.LOGGING)
settings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'json_formatter': {
'()': structlog.stdlib.ProcessorFormatter,
'processor': structlog.processors.JSONRenderer(sort_keys=False),
},
'plain_console': {
'()': structlog.stdlib.ProcessorFormatter,
'processor': structlog.dev.ConsoleRenderer(pad_event=43, colors=True, force_colors=True),
},
'key_value': {
'()': structlog.stdlib.ProcessorFormatter,
'processor': structlog.processors.KeyValueRenderer(key_order=['level',
'logger',
'event',
'timestamp'],
sort_keys=False
),
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'plain_console',
},
'json_file': {
'class': 'logging.handlers.WatchedFileHandler',
'filename': 'logs/json.log',
'formatter': 'json_formatter',
},
'flat_line_file': {
'class': 'logging.handlers.WatchedFileHandler',
'filename': 'logs/flat_line.log',
'formatter': 'key_value',
},
},
'loggers': {
'': {
'handlers': ['console', 'flat_line_file', 'json_file'],
'level': 'WARNING',
'propagate': False,
},
'account': {
'handlers': ['console', 'flat_line_file', 'json_file'],
'level': 'INFO',
'propagate': False,
},
'authentication': {
'handlers': ['console', 'flat_line_file', 'json_file'],
'level': 'INFO',
'propagate': False,
},
'myapp': {
'handlers': ['console', 'flat_line_file', 'json_file'],
'level': 'INFO',
'propagate': False,
}
}
}
structlog.configure(
processors=[
structlog.contextvars.merge_contextvars,
structlog.stdlib.filter_by_level,
structlog.processors.TimeStamper(fmt="iso"),
structlog.stdlib.add_logger_name,
structlog.stdlib.add_log_level,
structlog.stdlib.PositionalArgumentsFormatter(),
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
structlog.processors.UnicodeDecoder(),
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
],
logger_factory=structlog.stdlib.LoggerFactory(),
cache_logger_on_first_use=True,
)