Логирование в Go приложениях: лучшие практики для начинающих

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Логирование в Go приложениях: лучшие практики для начинающих

Логирование — одна из ключевых составляющих любого серьёзного приложения. Оно помогает отслеживать ошибки, анализировать поведение системы и понимать, что происходит "под капотом". В этой статье мы разберём лучшие практики логирования в Go (Golang) для начинающих разработчиков. Вы узнаете, какие библиотеки использовать, как организовать логи и избежать типичных ошибок.

Почему логирование важно в Go?

Go — язык, ориентированный на создание высоконагруженных серверных приложений и микросервисов. В таких системах без качественного логирования невозможно:

  • Быстро найти причину сбоя
  • Понять последовательность событий
  • Собрать метрики для мониторинга
  • Отлаживать код в production-среде

Плохо настроенное логирование может привести к потере критических данных или, наоборот, к переполнению диска миллионами бесполезных сообщений. Поэтому важно с самого начала заложить правильную архитектуру.

Стандартная библиотека log

Go предоставляет встроенный пакет log, который подходит для простых проектов. Он умеет выводить сообщения в stdout/stderr, добавлять временные метки и завершать программу при фатальных ошибках.

package main

import (
    "log"
)

func main() {
    log.Println("Приложение запущено")
    log.Printf("Пользователь %s вошёл в систему", "admin")
    // log.Fatal("Критическая ошибка") // завершает программу
}

Недостатки стандартного логгера:

  • Нет уровней логирования (debug, info, warn, error)
  • Нет структурированного вывода (только текст)
  • Сложно менять формат и направление вывода

Для учебных проектов и простых утилит этого достаточно, но для production-приложений лучше использовать более мощные библиотеки.

Популярные библиотеки для логирования

Рассмотрим три наиболее распространённых варианта.

1. Logrus

Logrus — одна из первых сторонних библиотек для Go. Она поддерживает уровни логирования, структурированные поля и множество форматов вывода (JSON, текст).

package main

import (
    "github.com/sirupsen/logrus"
)

func main() {
    log := logrus.New()
    log.SetFormatter(&logrus.JSONFormatter{})
    log.SetLevel(logrus.InfoLevel)

    log.WithFields(logrus.Fields{
        "user":   "ivan",
        "action": "login",
    }).Info("Пользователь вошёл в систему")
}

Logrus прост в использовании, но имеет высокое потребление памяти и немного медленнее современных альтернатив.

2. Zerolog

Zerolog — современная библиотека с фокусом на производительность и минимальное выделение памяти. Она использует zero-allocation подход и идеально подходит для высоконагруженных систем.

package main

import (
    "github.com/rs/zerolog"
    "github.com/rs/zerolog/log"
)

func main() {
    zerolog.TimeFieldFormat = zerolog.TimeFormatUnix

    log.Info().
        Str("user", "ivan").
        Str("action", "login").
        Msg("Пользователь вошёл в систему")

    log.Error().
        Err(fmt.Errorf("connection refused")).
        Msg("Ошибка подключения к БД")
}

Zerolog выводит логи в формате JSON по умолчанию, что упрощает их парсинг системами мониторинга (ELK, Grafana Loki).

3. Zap

Zap от Uber — ещё один высокопроизводительный логгер. Он работает в двух режимах: SugaredLogger (удобный, но чуть медленнее) и Logger (максимальная скорость).

package main

import (
    "go.uber.org/zap"
)

func main() {
    logger, _ := zap.NewProduction()
    defer logger.Sync()

    logger.Info("Сервер запущен",
        zap.String("port", "8080"),
        zap.Int("workers", 10),
    )
}

Для начинающих я рекомендую Zerolog или Logrus — они имеют понятный API и хорошую документацию. Zap выбирают, когда производительность критична.

Лучшие практики логирования

Чтобы логи приносили пользу, а не превращались в "шум", следуйте этим правилам.

1. Используйте уровни логирования

Определите для себя четыре базовых уровня:

  • Debug — отладочная информация, только для разработки
  • Info — стандартные события (запуск, остановка, действия пользователя)
  • Warn — предупреждения (нештатные, но не критичные ситуации)
  • Error — ошибки, требующие внимания

Не используйте log.Fatal без крайней необходимости — он завершает программу, что может быть опасно в production.

2. Структурируйте логи

Вместо строк вида "User 123 logged in" используйте структурированные поля:

log.Info().
    Str("user_id", "123").
    Str("ip", "192.168.1.1").
    Msg("user logged in")

Такой подход позволяет легко фильтровать и агрегировать логи в системах анализа.

3. Логируйте контекст запроса

В веб-приложениях важно связывать логи с конкретным HTTP-запросом. Для этого используйте request ID или trace ID:

requestID := "req-abc-123"
log.Info().
    Str("request_id", requestID).
    Str("path", "/api/users").
    Msg("обработка запроса")

4. Избегайте логирования чувствительных данных

Никогда не пишите в логи пароли, токены, номера кредитных карт и другую конфиденциальную информацию. Если нужно залогировать запрос — маскируйте чувствительные поля.

5. Настройте ротацию логов

В production логи пишутся в файлы. Чтобы они не заняли весь диск, настройте ротацию по размеру или времени. Для этого можно использовать пакет lumberjack или настроить внешнюю утилиту (logrotate).

import "gopkg.in/natefinch/lumberjack.v2"

log.SetOutput(&lumberjack.Logger{
    Filename:   "/var/log/myapp/app.log",
    MaxSize:    100, // мегабайт
    MaxBackups: 3,
    MaxAge:     28, // дней                

Блоги

Рекомендаций по книгам