Прямой ответ
Структура записи лога определяет возможность поиска: поля извлекаются без разбора текста, поэтому фильтр по значению работает одинаково для всех сервисов.
| Поле | Назначение |
|---|---|
| Метка времени | Сортировка записей по времени |
| Уровень | Фильтрация по значимости |
| Признак сервиса | Определение источника |
| Признак обращения | Поиск записей одного обращения |
import logging, json
class JsonFormatter(logging.Formatter):
def format(self, record):
return json.dumps({
"ts": self.formatTime(record),
"level": record.levelname,
"service": "orders",
"cid": getattr(record, "cid", None),
"msg": record.getMessage(),
})
Единый набор полей обеспечивает разбираемость записи при поиске, поэтому фильтр по значению работает без разбора строки. Об агрегации записей — в статье про агрегацию логов.
Уровни, признаки обращения и состав полей
Уровни записи позволяют отфильтровать значимые события, а признаки обращения связывают записи одного запроса.
Уровни записи. Уровень отражает значимость события, поэтому фильтр по уровню возвращает записи требуемой важности.
Признак обращения. Идентификатор обращения включается в запись, поэтому записи одного запроса находятся одним фильтром.
Состав полей. Единый набор полей обеспечивает одинаковый разбор для всех сервисов, поэтому поиск не требует отдельной настройки.
Практическое следствие: запись без признака обращения не находится по нему, поэтому связь записей одного запроса теряется.
Отдельный аспект — избыточность состава. Поля, не используемые при поиске, увеличивают объём записей без пользы.
Три признака некорректной структуры.
Отсутствие признака обращения. Записи одного запроса не связываются, поэтому поиск по обращению не работает.
Разный состав полей в сервисах. Разбор отличается, поэтому поиск требует отдельной настройки для каждого сервиса.
Избыточные поля. Объём записей растёт без пользы, поскольку поля не используются при поиске.
О признаках обращения — в статье про сквозной идентификатор; о разборе полей — в статье про log pipeline.
Читаемость и машинная обработка
Структура записи балансирует читаемость для человека и разбираемость для машинной обработки.
Читаемость. Запись с понятными полями читается без дополнительного разбора, поэтому поиск вручную выполняется быстро.
Машинная обработка. Единый формат обеспечивает извлечение полей без разбора строки, поэтому фильтр по значению работает.
Баланс. Избыточная детализация усложняет чтение, а недостаточная — машинную обработку, поэтому состав полей подбирается по задаче.
Практическое следствие: запись, удобная для чтения, но не разбираемая машиной, не подходит для автоматизированного поиска.
Практика: настройка структуры записей
1. Используйте единый набор полей. Разбор одинаков для всех сервисов, поэтому поиск не требует отдельной настройки.
2. Включайте признак обращения в запись. Записи одного запроса находятся одним фильтром.
3. Используйте уровни для значимости. Фильтр по уровню возвращает записи требуемой важности.
4. Фиксируйте метку времени в едином формате. Единый формат обеспечивает сортировку записей.
5. Не включайте избыточные поля. Объём записей растёт без пользы, поскольку поля не используются.
6. Проверяйте разбор полей при поиске. Неразбираемое поле указывает на отклонение структуры.
7. Ограничивайте объём одной записи. Избыточный объём усложняет передачу и хранение.
Рекомендации:
- Не смешивайте наборы полей между сервисами. Разный состав требует отдельного разбора, поэтому поиск усложняется.
- Учитывайте объём записей при хранении. Объём определяет требования к хранилищу и сроку хранения.
- Сопоставляйте признак обращения с трейсом. Связь признака с идентификатором трейса позволяет перейти от записи к дереву.
- Фиксируйте признак источника в ошибке. Признак в записи ошибки позволяет определить сервис сбоя.
- Пересматриваем состав полей при изменении поиска. Новое поле поиска требует включения в структуру записи.
Практический сценарий: записи одного запроса не связались
Контекст: поиск по признаку обращения возвращал записи не всех сервисов, поэтому картина обработки была неполной.
- Диагностика. Проверка показала, что один из сервисов не включал признак обращения в запись. Записи создавались, но без признака, поэтому фильтр по обращению их не возвращал.
- Причина. Структура записи сервиса не содержала поля признака обращения, поэтому связь записей терялась.
- Действия. (а) Добавили поле признака обращения в структуру записи сервиса; (б) привели набор полей к единому для всех сервисов; (в) проверили разбор полей на реальных записях; (г) проверили фильтр по признаку и убедились в возврате записей всех сервисов; (д) ограничили объём записи, убрав неиспользуемые поля.
- Результат. Записи всех сервисов находятся одним фильтром по признаку обращения.
Вывод: запись без признака обращения не находится по нему, поэтому связь записей одного запроса теряется. Единый набор полей с признаком обращения обеспечивает полноту поиска.
FAQ
Какие поля обязательны в записи лога? Метка времени, уровень, признак сервиса и признак обращения. Без них поиск по обращению и по источнику не работает.
Зачем нужны уровни записи? Уровень отражает значимость события, поэтому фильтр по уровню возвращает записи требуемой важности.
Почему важен единый набор полей? Разбор одинаков для всех сервисов, поэтому поиск не требует отдельной настройки для каждого формата.
Как структура связана с агрегацией? Единая структура обеспечивает разбираемость записей в общем потоке, поэтому фильтр по полю работает для всех сервисов.
Источники: Python logging, Grafana Loki, OpenTelemetry logs — ссылки в шапке.