Я использую structlog
с Django и заметил, что вывод пар key:value
осуществляется в алфавитном порядке в режиме консоли, что означает, что когда я связываю новую клавишу, начинающуюся с _
, как log.bind('_id'=id)
, она добавляется в самый первый.
Я задаю этот вопрос, потому что после вставки новой пары key:value
в середину или в начало строки преимущество хорошо структурированного и цветного журнала теряется при чтении консоли.
В документации упоминается логический параметр процессора sort_keys
, но он не поддерживается форматером key_value
. Как я могу отменить сортировку пары ключ-значение в простой консоли?
Это мой конфиг:
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=['timestamp', 'level', 'logger', 'event'],
sort_keys=False
),
},
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"formatter": "plain_console",
},
"json_file": {
"class": "logging.handlers.WatchedFileHandler",
"filename": "json.log",
"formatter": "json_formatter",
},
"flat_line_file": {
"class": "logging.handlers.WatchedFileHandler",
"filename": "flat_line.log",
"formatter": "key_value",
},
},
"loggers": {
'': {
"handlers": ["console", "flat_line_file", "json_file"],
"level": "WARNING",
'propagate': False,
},
'app1': {
"handlers": ["console", "flat_line_file", "json_file"],
"level": "INFO",
'propagate': False,
},
'app2': {
"handlers": ["console", "flat_line_file", "json_file"],
"level": "INFO",
'propagate': False,
},
'app3': {
"handlers": ["console", "flat_line_file", "json_file"],
"level": "INFO",
'propagate': False,
}
}
}
structlog.configure(
processors=[
structlog.stdlib.filter_by_level,
structlog.processors.TimeStamper(fmt="%Y-%m-%d %H:%M:%S.%f"), # (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,
],
context_class=structlog.threadlocal.wrap_dict(dict),
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=structlog.stdlib.BoundLogger,
cache_logger_on_first_use=True,
)