← Назад к вопросам

Что такое структурированное логирование?

2.4 Senior🔥 201 комментариев
#Observability

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое структурированное логирование?

Структурированное логирование — это подход к записи логов, при котором данные выводятся не в виде простых текстовых строк, а в виде структурированных записей с четко определенными полями (ключ-значение), обычно в машиночитаемых форматах, таких как JSON, XML или Protocol Buffers. В отличие от традиционного логирования, где сообщение часто представляет собой форматированную строку, структурированное логирование отделяет данные (параметры, контекст, метрики) от текста сообщения, что значительно упрощает их последующий анализ, фильтрацию и агрегацию с помощью специальных инструментов (например, ELK-стек, Splunk, Grafana Loki).

Ключевые принципы и преимущества

  • Машиночитаемость и анализ: Логи в формате JSON могут быть напрямую индексированы системами централизованного сбора логов без сложных парсеров регулярных выражений. Это позволяет быстро выполнять сложные запросы, например: "показать все ошибки уровня ERROR от сервиса auth-service, где поле user_id равно 12345, за последний час".
  • Контекстное логирование: Каждая запись лога обогащается контекстными полями, которые автоматически добавляются ко всем последующим записям в пределах определенной области (например, HTTP-запроса, горутины, транзакции). Это критически важно в распределенных системах (микросервисах) для сквозной трассировки.
    // Пример с использованием log/slog (Go 1.21+)
    logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
    // Добавляем контекст ко всем записям в этой горутине
    logger = logger.With("trace_id", "abc-123", "user_ip", "192.168.1.1")
    logger.Info("user login attempt", "method", "POST", "path", "/login")
    // В лог попадут все поля: time, level, msg, trace_id, user_ip, method, path
    
  • Производительность: Современные библиотеки структурированного логирования (например, slog, zerolog, logrus для Go) часто оптимизированы для минимизации аллокаций памяти и накладных расходов на форматирование строк.
  • Согласованность: Формат записей стандартизирован, что облегчает создание общих пайплайнов обработки логов для разных команд и сервисов.
  • Гибкость вывода: Одна и та же структура лога может быть легко сериализована в разные форматы (JSON для продакшена, удобный текст для локальной разработки) без изменения кода приложения.
    // Текстовый вывод для разработки
    textHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})
    devLogger := slog.New(textHandler)
    devLogger.Info("server started", "port", 8080)
    // Вывод: time=2023-10-01T12:00:00.000Z level=INFO msg="server started" port=8080
    
    // JSON вывод для продакшена
    jsonHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})
    prodLogger := slog.New(jsonHandler)
    prodLogger.Info("server started", "port", 8080)
    // Вывод: {"time":"2023-10-01T12:00:00.000Z","level":"INFO","msg":"server started","port":8080}
    

Пример в Go: стандартная библиотека log/slog

Начиная с версии Go 1.21, в стандартную библиотеку был включен пакет slog, что сделало структурированное логирование идиоматическим и доступным по умолчанию. Вот его основные концепции:

  • slog.Logger: Центральный объект-логгер.
  • slog.Handler: Определяет, как обрабатываются записи логов (форматирование, фильтрация по уровню, добавление полей). Библиотека предоставляет TextHandler и JSONHandler.
  • slog.Record: Неизменяемое представление записи лога.
  • Уровни логирования: Debug, Info, Warn, Error.
  • Группировка атрибутов: Позволяет группировать связанные поля для лучшей организации в логах.
package main

import (
    "log/slog"
    "os"
)

func main() {
    // Создаем логгер с JSON-обработчиком
    logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
        AddSource: true, // Добавлять информацию об исходном файле и строке
        Level:     slog.LevelInfo,
    }))

    // Логирование с атрибутами
    logger.Info("processing request",
        slog.String("method", "GET"),
        slog.String("path", "/api/v1/users"),
        slog.Int("status", 200),
        slog.Duration("duration_ms", 150), // Атрибуты типизированы
        slog.Group("user", // Группировка атрибутов
            slog.String("id", "usr_123"),
            slog.String("email", "user@example.com"),
        ),
    )

    // Логирование ошибок с помощью Error
    logger.Error("database connection failed",
        slog.String("error", "connection timeout"),
        slog.String("db_host", "db-primary:5432"),
    )
}

Сравнение с неструктурированным логированием

АспектНеструктурированное логирование (fmt.Printf, log.Println)Структурированное логирование (slog, zerolog)
ФорматПроизвольная текстовая строка: "2023/10/01 12:00:00 Error: file not found: id=123"Структура (JSON): {"time":"...","level":"ERROR","msg":"file not found","file_id":123}
ПарсингСложен, требует регулярных выражений, хрупок при изменении формата.Тривиален, данные доступны по ключам.
КонтекстНужно явно добавлять в каждое сообщение, что ведет к дублированию кода.Прикрепляется к логгеру/группе один раз (With, WithGroup).
ЗапросыПолнотекстовый поиск, нет возможности фильтровать по конкретным полям.Мощные запросы по любому полю: level:ERROR AND service:payment.
ПроизводительностьМножественные аллокации при конкатенации/форматировании строк.Оптимизировано, часто используется пул буферов.

Заключение

Структурированное логирование — это современный, обязательный к использованию подход для разработки производственных систем, особенно в экосистеме Go и микросервисных архитектурах. Оно превращает логи из трудноанализируемого текстового потока в ценный структурированный источник данных для мониторинга, отладки сложных распределенных сценариев, аудита и анализа инцидентов. Внедрение структурированного логирования с самого начала проекта значительно сокращает операционные издержки и увеличивает скорость обнаружения и решения проблем. Использование стандартного пакета slog делает этот подход доступным, эффективным и идиоматичным для любого Go-разработчика.

Что такое структурированное логирование? | PrepBro