Готовим логи в Go проекте. Часть 1

Anatoliy Fedorenko
Mad Devs — блог об IT
5 min readOct 30, 2019

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

Логи в проекте - это необходимость, это показатель профессионализма команды, чистоты кода и быстроты реакции в случае ошибки.

Кто-то ставит в проекте беспорядочно `print` или `fmt.Println` и не заботится о том, как и зачем вообще логировать что-либо. Кто-то делает лучше: использует уже готовые решения в виде библиотек для логирования, но это не всегда решает проблему беспорядочного, хаотичного логирования.

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

Отсюда вывод, не ведите логи хаотично! Их надо упорядочить и лучше это сделать как можно раньше!

Начать цикл статей про логи хочется с двух аспектов логирования, а именно с формата логов в проекте и применения уровней логирования. Но сначала нужно сказать о каком конкретно логере будет идти речь в статье. На данный момент один из самых поддерживаемых, функциональных и приятных в использовании логеров в Go можно считать Logrus. Соответственно, все примеры в этой статье будут делаться с использованием этого логера.

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

Что же касается общего формата лога, рекомендую упоминать название пакета, а так же название функции в которой произошло то или иное событие. Это поможет быстро найти место “происшествия” и предпринять соответствующие действия.

Самый очевидный способ залогировать что-то это просто … залогировать это

А второй, это потратить чуть больше времени и написать более серьёзный лог по установленному формату.

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

Рекомендую в любом серьезном проекте использовать конструкцию log.WithFields().Error(), в которой можно поместить всю нужную информацию в отдельные Fields и соответственно легко по ним ориентироваться.

Описав детально как должны выглядеть логи в проекте, вы сэкономите для себя и будущих разработчиков часы, а то и недели. Помните, добавляя новые логи, не надо лениться делать всё по установленному формату. Это всегда инвестиция в будущее! Ах да, логи стоит только добавлять, никогда не удалять, и об этом дальше

Многие новички не понимают зачем нужны уровни логирования, а даже если уже поняли зачем, всё равно не понимают как в проекте распределить логи по разным уровням, чтобы ими было удобно пользоваться.

В результате непонимания, разработка в проекте превращается в лихорадочное добавление логов для отладки на проде, а затем в следующих коммитах “спамные” логи удаляются (чтобы возможно вернуться через несколько коммитов снова). Это проблема, и если у вас она есть, остановитесь и подумайте как правильно распределить логи разного уровня в проекте, чтобы они не мешали разработке, но и не приходилось каждый раз добавлять/удалять их.

Удобство в логировании - это, когда количество “спамных” логов сводится к минимуму, и все логи, что есть в проекте служат какой-то цели. Они никогда не удаляются, а только добавляются

У логеров (в частности у Logrus) есть возможность настраивать уровни логирования, тем самым активируя или деактивируя различные логи в порядке их важности. Уровни, которые хочу рассмотреть сейчас это: “Fatal”, “Error”, “Info”, “Warning”, “Debug”, все остальные либо имеют примерно тот же самый смысл (Panic vs Fatal), либо слишком узконаправленные (Trace).

Куда надо ставить логи уровня Fatal/Panic? Они должны появляться тогда, когда продолжать работу просто нельзя. Например, проект не смог стартануть, потому что не стартанула база, или неправильно прогрузились конфигурации. Это должны быть совсем непредвиденные ситуации, которые ведут к полному отказу системы. И они по-хорошему должны фиксироваться в начале работы.

На логи уровня Fatal/Paniс надо реагировать немедленно!

Уровнем Error должны помечаться только те ОШИБКИ, которых не ожидаешь, на которые НУЖНО срочно обратить внимание. Например, если запрос в базу упал с ошибкой синтаксиса, если сторонний клиент отработал некорректно. Они же (как и паника) должны отправляться в различные инструменты мониторинга на подобии Sentry, чтобы наиболее экономично, но в тоже время эффективно использовать мониторинг логов.

Логи уровня Error должны жёстко тригерить и никогда не допускаться впредь.

В свою очередь Warning уровнем должно покрываться всё, на что стоит обратить внимание, но это “запрограммированно”, т.е. всё идёт в рамках заданной логики. Например, валидации структур, пропуски каких-либо итераций циклов по заданным условиям и т.д.

Warnings это все на что можно/стоит обратить внимание, но это не повергает в шок и не тригерит быстрее что-либо чинить или танцевать с бубном.

Уровень Info можно использовать везде, где хочется вставить информацию о работе проекта. Данный лог довольно универсален и может подходить куда угодно и даже часто смешивается c warning, либо debug логами. Лично я не рекомендую использовать этот уровень, так как он в целом “нейтрален”, и может означать всё, что угодно. Гораздо лучше использовать следующий уровень логирования, чтобы наверняка знать как используется показываемая информация.

Уровень Debug/Trace же должен показывать больше инфы, о том, что происходит в общем. Какие запросы приходят, как они обрабатываются, что меняется по ходу логики, какие ответы возвращаются, какая переменная имеет какое значение на определенных уровнях бизнес логики и т.д. То есть всё то, что поможет в случае поломки/дебага определить, как менялись данные и почему они приняли такой вид.

Debug/Trace логи — это микроскоп, вам не нужен микроскоп всегда и везде. Поэтому в production нужно отключать эти логи, чтобы не спамить понапрасну

Итоги:

  1. Используйте проверенные инструменты для логирования, так как это экономит нервы и время
  2. Заранее выстраивайте вашу систему логирования таким образом, чтобы было понятно куда и как добавлять логи, а также, чтобы их можно было потом читать и понимать
  3. Используйте уровни логирования с умом, так как иной раз невозможно в логах найти причину проблем, а иногда логов просто недостаточно, чтобы сказать хоть что-нибудь о возникшей проблеме. Оба варианта одинаково плачевны.

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

--

--