Ответ
В Go существует два основных подхода к логированию: неструктурированное (стандартная библиотека) и структурированное (сторонние библиотеки), которое является предпочтительным для современных бэкенд-сервисов.
1. Стандартная библиотека log
(Неструктурированное логирование)
Простой механизм для вывода текстовых сообщений. Подходит для небольших утилит или на ранних этапах разработки.
import "log"
log.Println("Сервер запущен на порту 8080") // Просто текстовая строка
Недостаток: Текстовые логи сложно парсить, фильтровать и анализировать в автоматизированных системах (ELK, Splunk, Grafana Loki).
2. Структурированное логирование (Рекомендуемый подход)
Логи записываются в формате JSON
или key-value
, что делает их машиночитаемыми. Это стандарт для микросервисной архитектуры.
Популярные библиотеки:
zerolog
: Очень высокая производительность и удобный API.zap
: Разработана в Uber, также нацелена на максимальную производительность.slog
: Новый официальный пакет для структурированного логирования, добавленный в Go 1.21. Становится стандартом де-факто.
Пример с slog
(Go 1.21+):
package main
import (
"log/slog"
"os"
)
func main() {
// Создаем логгер, который пишет в stdout в формате JSON
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
// Устанавливаем его как логгер по умолчанию
slog.SetDefault(logger)
// Примеры логирования с разными уровнями и атрибутами
slog.Info(
"Пользователь успешно авторизовался",
slog.String("username", "admin"),
slog.Int("user_id", 123),
)
slog.Error(
"Не удалось обработать запрос",
slog.String("error", "database connection failed"),
slog.String("request_id", "abc-123-xyz"),
)
}
// Вывод:
// {"time":"...","level":"INFO","msg":"Пользователь успешно авторизовался","username":"admin","user_id":123}
// {"time":"...","level":"ERROR","msg":"Не удалось обработать запрос","error":"database connection failed","request_id":"abc-123-xyz"}
Лучшие практики и важные концепции:
Уровни логирования (Log Levels): Используйте разные уровни для классификации сообщений (
DEBUG
,INFO
,WARN
,ERROR
). Это позволяет настраивать детализацию логов в разных окружениях (например,DEBUG
на dev,INFO
и выше на prod).Контекстное логирование: Обогащайте логи сквозными данными, такими как
request_id
илиtrace_id
. Это критически важно для отслеживания потока выполнения запроса в микросервисах. Логгер следует передавать черезcontext.Context
.Вывод в
stdout
: В контейнеризированных средах (Docker, Kubernetes) всегда пишите логи вstdout
/stderr
. Система оркестрации сама позаботится об их сборе и перенаправлении.Не логируйте чувствительные данные: Никогда не записывайте в логи пароли, токены, персональные данные и другую конфиденциальную информацию.
Формат: Используйте
JSON
для продакшн-окружений для легкой интеграции с системами сбора логов и текстовый формат для локальной разработки для лучшей читаемости.