Логирование для Go (Golang): лучшие решения
Логирование — фундаментальная часть любого серьёзного приложения. В экосистеме Go (Golang) существует множество библиотек, каждая из которых предлагает свой баланс между производительностью, гибкостью и удобством. В этой статье мы рассмотрим лучшие решения для логирования в Go, начиная от стандартной библиотеки и заканчивая высокопроизводительными инструментами, такими как zerolog и zap.
Стандартная библиотека: log
Go поставляется со встроенным пакетом log. Он прост, но имеет ограничения: отсутствие уровней логирования (Debug, Info, Warn, Error), нет поддержки структурированного вывода (JSON) и минимальные возможности форматирования. Однако для небольших проектов или быстрой отладки он вполне пригоден.
package main
import (
"log"
)
func main() {
log.Println("Это информационное сообщение")
log.Fatalln("Фатальная ошибка, приложение завершится")
}
Плюсы: не требует установки, нулевая зависимость.
Минусы: низкая гибкость, отсутствие уровней логирования, нет структурированных логов.
Logrus — классика с широкими возможностями
Logrus долгое время был стандартом де-факто для логирования в Go. Он предоставляет уровни логирования, поддержку JSON-формата и множество хуков (hooks) для интеграции с внешними системами (Logstash, Sentry и др.).
package main
import (
"github.com/sirupsen/logrus"
)
func main() {
log := logrus.New()
log.SetFormatter(&logrus.JSONFormatter{})
log.WithFields(logrus.Fields{
"user_id": 123,
"action": "login",
}).Info("Пользователь вошёл в систему")
}
Плюсы: богатый API, множество хуков, поддержка структурированных логов.
Минусы: относительно низкая производительность, большой размер бинарного файла.
Zerolog — высокая производительность и ноль аллокаций
Zerolog (от создателей RSocket) — это библиотека, которая ставит производительность во главу угла. Она использует принцип «zero allocation» (нулевое выделение памяти) для горячих путей, что делает её одной из самых быстрых в Go. Zerolog идеально подходит для микросервисов и высоконагруженных систем.
package main
import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func main() {
// Настройка глобального логгера
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
log.Info().
Str("service", "auth").
Int("user_id", 456).
Msg("Запрос авторизован")
// Логирование ошибок
err := someFunction()
if err != nil {
log.Error().Err(err).Msg("Не удалось выполнить операцию")
}
}
func someFunction() error {
return nil
}
Плюсы: рекордная производительность, низкое потребление памяти, простой API.
Минусы: менее гибкий, чем Logrus, требует привыкания к цепочечному синтаксису.
Zap — промышленный стандарт от Uber
Zap (Zap Awesome Performance) разработан инженерами Uber. Он предлагает два режима: SugaredLogger (удобный, но с небольшими накладными расходами) и Logger (максимально быстрый). Zap поддерживает структурированные логи, уровни и кастомные кодировщики.
package main
import (
"go.uber.org/zap"
)
func main() {
// Создаём логгер (режим Production)
logger, _ := zap.NewProduction()
defer logger.Sync() // flushes buffer, если есть
// SugaredLogger — удобный синтаксис
sugar := logger.Sugar()
sugar.Infow("Сервер запущен",
"port", 8080,
"env", "production",
)
// Logger — максимальная производительность
logger.Info("Ключевое событие",
zap.Int("attempt", 3),
zap.String("status", "success"),
)
}
Плюсы: высочайшая производительность, два режима работы, гибкая настройка.
Минусы: более сложный API, чем у Logrus, требует компиляции схемы.
Сравнение производительности
Для наглядности приведём приблизительные результаты бенчмарков (количество операций в секунду, чем больше — тем лучше):
- Zap (Logger): ~ 1,5 млн ops/sec
- Zerolog: ~ 1,4 млн ops/sec
- Logrus: ~ 200 тыс ops/sec
- Стандартный
log: ~