documentation/pages/logs.md
2025-07-08 13:26:44 +03:00

6.8 KiB
Raw Permalink Blame History

Настройки логирования в модулях

ML-компонент

Для единообразия логов самого модуля и логов библиотеки unip-mlcmp рекомендуется использовать один из двух форматов логирования:

  1. Простой формат.
  2. Формат с добавлением request_id.

Простой формат

Для соответствия простому формату, ваше сообщение должно форматироваться строкой:

"[%(asctime)s] %(name)-15.15s [%(levelname)-8.8s]  %(message)s"

Примеры настроек приведены ниже.

Настройка с помощью dictConfig:

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

[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

Настройка в коде:

from logging.config import fileConfig
fileConfig("logging.conf")

Формат с добавлением request_id

request_id - это идентификатор корреляции, уникальный идентификатор, который присваивается каждому запросу. Он позволяет провести соответствие между записями в логах и запросами к сервису модели.

Этот идентификатор представляет из себя строку. Если при запросе к сервису модели в заголовке X-Request-Id была передана строка, она используется в качестве идентификатора корреляции запроса. Если при запросе заголовок X-Request-Id не передан, идентификатор корреляции генерируется сервисом. В ответе на запрос к сервису модели в заголовке X-Request-Id идентификатор корреляции возвращается в любом случае - передан он был в запросе или нет.

Для добавления request_id в логи достаточно изменить формат на следующий:

"[%(asctime)s] %(name)-15.15s [%(levelname)-8.8s] [%(request_id)s]  %(message)s"

request_id добавляется в запись логов при обработке запроса сервисом модели. Чтобы логирование с request_id не приводило к ошибкам при выполнении кода модуля вне сервиса, рекомендуется использовать функцию-фильтр, добавляющую поле request_id в объект LogRecord, полями которого заполняется строка логов.

Фильтр напрямую в коде

Пример добавления фильтр-функции через logger.addFilter(). Предполагается, что обработчик (hanlder) добавлен только к логгеру "my_project" как корневому логгеру проекта. Метод addFilter нужно вызвать для всех логгеров, к которым добавлены обработчики, либо к самому обработчику.

    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 нужно передавать не саму фильтр-функцию, а функцию, которая возвращает фильтр-функцию.

Пример:

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.

Пример конфигурации:

from logging.config import dictConfig
dictConfig({
    'version': 1,
    'formatters': {
        'default_format': {
            'format': '[%(asctime)s] %(name)s [%(levelname)s]  %(message)s',
        }
    },
    'handlers': {
        'default': {
            'class': 'logging.StreamHandler',
            'stream': 'ext://sys.stdout',
            'formatter': 'default_format',
        }
    },
    'loggers': {
        'my_project': {
            'level': 'INFO',
            'handlers': ['default_handler']
        },
    }
})