From 5683b7fb5f6ea606a0fbdfb328e7cae7d191e580 Mon Sep 17 00:00:00 2001 From: Georgii Zhulikov Date: Mon, 7 Jul 2025 17:14:20 +0300 Subject: [PATCH] Add log recommendations --- pages/logs.md | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 pages/logs.md diff --git a/pages/logs.md b/pages/logs.md new file mode 100644 index 0000000..1f6374b --- /dev/null +++ b/pages/logs.md @@ -0,0 +1,195 @@ + +# Настройки логирования в модулях + +## ML-компонент + +Для единообразия логов самого модуля и логов библиотеки unip-mlcmp рекомендуется использовать один из двух форматов логирования: + +1. Простой формат. +2. Формат с добавлением request_id. + +### Простой формат + +Для соответствия простому формату, ваше сообщение должно форматироваться строкой: + +``` +"[%(asctime)s] %(name)-15.15s [%(levelname)-8.8s] %(message)s" +``` + +Примеры настроек приведены ниже. + +#### Настройка с помощью `dictConfig`: + +```python +from logging.config import dictConfig +dictConfig({ + 'version': 1, + 'formatters': { + 'default_formatter': { + 'format': '[%(asctime)s] %(name)-15.15s [%(levelname)-8.8s] %(message)s' + } + }, + 'handlers': { + 'default_handler': { + 'class': 'logging.StreamHandler', + 'stream': 'ext://sys.stdout', + 'formatter': 'default_formatter' + } + }, + 'loggers': { + 'my_project': { + 'level': 'INFO', + 'handlers': ['default_handler'] + }, + } + 'disable_existing_loggers': False + }) +``` + + +#### Настройка с помощью `fileConfig`: + +Файл `logging.conf` + +```toml +[loggers] +keys=root,my_project + +[handlers] +keys=default_handler + +[formatters] +keys=default_formatter + +[logger_root] +level=INFO +handlers= + +[logger_my_project] +level=INFO +handlers=default_handler +propagate=1 +qualname=my_project + +[handler_default_handler] +class=StreamHandler +level=NOTSET +formatter=default_formatter +args=(sys.stdout,) + +[formatter_default_formatter] +format=[%(asctime)s] %(name)-15.15s [%(levelname)-8.8s] %(message)s +datefmt= +style=% +validate=True +class=logging.Formatter +``` + +Настройка в коде: + +```python +from logging.config import fileConfig +fileConfig("logging.conf") +``` + +### Формат с добавлением request_id + +Для добавления `request_id` в логи достаточно изменить формат на следующий: + +``` +"[%(asctime)s] %(name)-15.15s [%(levelname)-8.8s] [%(request_id)s] %(message)s" +``` + +Но в таком случае при локальном выполнении кода возникнет ошибка - значение `request_id` устанавливается при обработке запроса в модуле, чего локально не происходит. + +Чтобы эта ошибка не возникала, рекомендуется использовать функцию-фильтр, добавляющую поле `request_id` в объект `LogRecord`, полями которого заполняется строка логов. + +#### Фильтр напрямую в коде + +Пример добавления фильтр-функции через `logger.addFilter()`. Предполагается, что обработчик (hanlder) добавлен только к логгеру `"my_project"` как корневому логгеру проекта. Метод `addFilter` нужно вызвать для всех логгеров, к которым добавлены обработчики, либо к самому обработчику. + +```python + logger = logging.getLogger("my_project") + + def filter_request_id(record): + if not hasattr(record, "request_id"): + record.request_id = "-" + return True + + logger.addFilter(filter_request_id) +``` + +#### Фильтр в `dictConfig` + +При настройке фильтров в `dictConfig` нужно передавать не саму фильтр-функцию, а функцию, которая возвращает фильтр-функцию. + +Пример: + +```python +def filter_record_factory(): + def filter_record(record): + if not hasattr(record, "request_id"): + record.request_id = "-" + return True + return filter_record + +dictConfig({ + 'version': 1, + 'formatters': { + 'default_formatter': { + 'format': '[%(asctime)s] %(name)-15.15s [%(levelname)-8.8s] %(message)s' + } + }, + 'filters': { + 'request_id': { + '()': filter_record_factory + }, + } + 'handlers': { + 'default_handler': { + 'class': 'logging.StreamHandler', + 'stream': 'ext://sys.stdout', + 'filters': ['request_id'] + 'formatter': 'default_formatter', + } + }, + 'loggers': { + 'my_project': { + 'level': 'INFO', + 'handlers': ['default_handler'] + }, + } + 'disable_existing_loggers': False + }) +``` + +## Пайплайн + +В пайплайнах рекомендуется использовать следующий формат логирования: `[%(asctime)s] %(name)s [%(levelname)s] %(message)s`. + +Пример конфигурации: + +```python +from logging.config import dictConfig +dictConfig({ + 'version': 1, + 'formatters': { + 'validation': { + 'format': '[%(asctime)s] %(name)s [%(levelname)s] %(message)s', + } + }, + 'handlers': { + 'default': { + 'class': 'logging.StreamHandler', + 'stream': 'ext://sys.stdout', + 'formatter': 'validation', + } + }, + 'loggers': { + 'my_project': { + 'level': 'INFO', + 'handlers': ['default_handler'] + }, + } +}) +``` \ No newline at end of file