documentation/pages/logs.md

198 lines
6.8 KiB
Markdown
Raw Permalink Normal View History

2025-07-07 14:14:20 +00:00
# Настройки логирования в модулях
## 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
2025-07-08 10:26:44 +00:00
`request_id` - это идентификатор корреляции, уникальный идентификатор, который присваивается каждому запросу. Он позволяет провести соответствие между записями в логах и запросами к сервису модели.
Этот идентификатор представляет из себя строку. Если при запросе к сервису модели в заголовке `X-Request-Id` была передана строка, она используется в качестве идентификатора корреляции запроса. Если при запросе заголовок `X-Request-Id` не передан, идентификатор корреляции генерируется сервисом. В ответе на запрос к сервису модели в заголовке `X-Request-Id` идентификатор корреляции возвращается в любом случае - передан он был в запросе или нет.
2025-07-07 14:14:20 +00:00
Для добавления `request_id` в логи достаточно изменить формат на следующий:
```
"[%(asctime)s] %(name)-15.15s [%(levelname)-8.8s] [%(request_id)s] %(message)s"
```
2025-07-08 10:26:44 +00:00
`request_id` добавляется в запись логов при обработке запроса сервисом модели. Чтобы логирование с `request_id` не приводило к ошибкам при выполнении кода модуля вне сервиса, рекомендуется использовать функцию-фильтр, добавляющую поле `request_id` в объект `LogRecord`, полями которого заполняется строка логов.
2025-07-07 14:14:20 +00:00
#### Фильтр напрямую в коде
Пример добавления фильтр-функции через `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': {
2025-07-08 10:26:44 +00:00
'default_format': {
2025-07-07 14:14:20 +00:00
'format': '[%(asctime)s] %(name)s [%(levelname)s] %(message)s',
}
},
'handlers': {
'default': {
'class': 'logging.StreamHandler',
'stream': 'ext://sys.stdout',
2025-07-08 10:26:44 +00:00
'formatter': 'default_format',
2025-07-07 14:14:20 +00:00
}
},
'loggers': {
'my_project': {
'level': 'INFO',
'handlers': ['default_handler']
},
}
})
```