Сначала позвольте немного поразглагольствовать: программа, поддержкой которой я занимаюсь по работе, содержит много милых особенностей. “Произошла ошибка” — не то, что достойно такого описания. Сообщения об ошибке не просто начинаются этой фразой. Они ей исчерпываются.
Или как насчет: “Информация об ошибке находится в логах сервера”, но в сообщении нет никаких указаний, какой сервер на самом деле выдал исключение?
Эта статья — о том, как писать логи и сообщения об ошибках, которые не выглядят настолько плохо.
А это точно нужно?
Большая часть этой статьи посвящена предоставлению дополнительной информации. Но сначала — только на мгновение — посмотрим на некоторые сообщения в логах, которые можно безопасно вырезать. Почему? Скажем так: читая лог-файл в километр длиной, вы будете благодарны за все, что не отнимает у вас мыслительные ресурсы.
- Записи вида “Все хорошо” для каждой итерации цикла. Пока я знаю, что программа запустилась нормально и, возможно, сейчас войдет в этот цикл, меня волнуют только ошибки.
- Записи журналов производительности, когда я не тестирую производительность.
- Каждый шаг функции/вычисления. Не нужно регистрировать “а” и “в”, когда вы уже регистрируете “а+в=с”.
В большинстве случаев лучше избыток информации, чем недостаток, но все же стоит учитывать обстоятельства, чтобы не перегнуть палку.
Пожалуйста, сообщите, в чем ошибка
Большинство исключений, с которыми мы сталкиваемся в обычной жизни, не обрабатываются явно, а это означает, что мы часто получаем трассировку стека, которая точно сообщает нам, что произошло, где и когда. Тут все в порядке. Это не особенно читабельно, но, по крайней мере, есть возможность проследить источник.
Если, однако, вы фиксировали исключение через блок catch
, чтобы затем вывести на консоль: “Что-то не работает”, даже не печатая в лог-файл, просто не делайте этого. Если вы пишете пользовательский обработчик исключений, то потратьте одну лишнюю минуту на объяснение, в чем заключается ошибка. Это неправильная запись в базе данных, например, или неправильно отформатированное имя? Хорошо, теперь не нужно клонировать репозиторий и отлаживать все самому. Можно просто немедленно исправить нужную запись в базе данных.
Пожалуйста, сообщите, где конкретно возникла ошибка
Это моя самая большая болевая точка при исправлении ошибок: мы получаем ежедневный мониторинг сообщений об ошибках, но самое хорошо написанное сообщение не приведет далеко, если я даже не знаю, откуда оно взялось. Просто выведите что-нибудь вроде:
fatal error: invalid cast at serverIWouldLikeToSlaughter
И это уже гораздо лучше.
Предоставьте дополнительные параметры, с которыми можно работать
В продолжение предыдущего примера: вероятно, когда вы пишете сообщение об ошибке, у вас под рукой уже есть вся информация, так почему бы не дать ее мне? Просто выведите идентификатор клиента, номер счета, адрес электронной почты, который вы не можете десериализовать.
Fatal error: Invalid cast type Boolean to Integer numberOfSwearwords at serverIWouldLikeToSlaughter
Перегружайте только конкретные исключения
Если вам хочется создать исключение для неправильных типов данных или что-то в этом роде, вам надо подключиться к InvalidCastException
или аналогично — но не к Exeption
. Таким образом, самая распространенная ошибка будет сопровождаться большим сообщением с говорящим именем и описанием. Но когда происходит что-то необычное, вы все равно регистрируете полную трассировку стека, и она не теряется.
Try{thisOrthat();}
Catch castEx as InvalidCastException{
log.error("detailed description of error");
}
Catch ex as Exception{
log.error(ex.stacktrace);
}
Взглянем на примеры таких лог-файлов
Вот лишь некоторые случайно выбранные образцы того, что я бы счел полезными записями в журнале логов — вещи, которые значительно облегчают понимание того, где возникла ошибка и как ее исправить:
-загружается server1 application4
-соединение с otherServer на порту 1337 - успешно
-проверка базы данных; соединение с databaseServer5 Ошибка 400:Of course it doesn’t work, your credentials are outdated but not even the database admins have a clue what the new one are. Конечно, ничего не работает, ваши учетные данные устарели, но даже администраторы базы данных не имеют понятия, какими должны быть новые.
-программа завершила работу в 00:34 pm, 1234 файлов обработано успешно, 23 неуспешно, 45 пропущено
-Нет доступа к файлу asdfadsfa.txt поскольку файл открыт другим процессом
-ошибка обновления таблицы базы данных tb_xyz, максимальная длина столбца 50 превышена в столбце "name"
-обработка текстового поля HTML не удалась, это часто вызвано проблемами форматирования на стороне базы данных. Проверьте у администраторов базы данных, было ли получено из БД следующее значение: <a\">helloworld\"</a>
Каждое из этих сообщений об ошибках сэкономило бы полчаса просто на поиске источника и сути ошибки — по сравнению с теми сообщениями, которые либо не описывают ошибку вообще, либо описывают неэффективным способом.
Заключение
Минута затраченного времени может сэкономить вам часы в будущем.
Надеюсь, статья была для вас полезной!
Читайте также:
- Простая защита от DoS и брутфорс атак
- notebookJS: JavaScript и D3 в Jupyter Notebook
- 7 факторов, которые помогут улучшить UX-дизайн
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи: keypressingmonkey, “How to Write Log Files That Save You Hours of Time”