Как правильно писать логи (?) / Хабр
Тема может и банальная, но когда программа начинает работать как то не так, и вообще вести себя очень странно, часто приходится читать логи. И много логов, особенно если нет возможности отлаживать программу и не получается воспроизвести ошибку. Наверно каждый выработал для себя какие то правила, что, как и когда логировать. Ниже я хочу рассмотреть несколько правил записи сообщений в лог, а также будет небольшое сравнение библиотек логирования для языков php, ruby и go. Сборщики логов и системы доставки не будут рассматриваться сознательно (их обсуждали уже много раз).
Есть такая linux утилита, а также по совместительству сетевой протокол под названием syslog. И есть целый набор RFC посвящённый syslog, один из них описывает уровни логирования https://en.wikipedia.org/wiki/Syslog#Severity_level (https://tools.ietf.org/html/rfc5424). Согласно rfc 5424 для syslog определено 8 уровней логирования, для которых также дается краткое описание.
- что-то происходит и надо знать что
- что-то сломалось и нужно дополнительно активировать триггер
По триггеру может происходить: уведомление об ошибке на email, аварийное завершение или перезапуск программы или другие типичные сценарии.
В языке Go в котором всё упрощено до предела, стандартный логер тоже прилично покромсали и оставили следующие варианты:
- Fatal — вывод в лог и немедленный выход в ОС.
- Panic — вывод в лог и возбуждение «паники» (аналог исключения)
- Print — просто выводит сообщение в лог
Запутаться, что использовать в конкретной ситуации уже практически невозможно. Но сообщения в таком сильно усеченном виде сложно анализировать, а также настраивать системы оповещения, типично реагирующих на какой нибудь Alert\Fatal\Error в тексте лога.
Я часто при написании программы с нуля повсеместно использую debug уровень для логирования с расчётом, что на продакшене будет выставлен уровень логирования info и тем самым сократится зашумлённость сообщениями. Но в таком подходе часто возникают ситуация, что логов вдруг становится не хватать. Трудно угадать, какая информация понадобиться, что бы отловить редкий баг. Возможно рационально всегда использовать по умолчанию уровень info, а в обработчиках ошибок уровень error и выше.
Есть ещё тонкий момент, когда вы пишите что то вроде logger.debug(entity.values)
— то при выставленном уровне логирования выше debug содержимое entity.values не попадёт в лог, но оно каждый раз будет вычисляться отъедая ресурсы. В Ruby логеру можно передать вместо строки сообщения блок кода:
Logger.debug { entity.values }
. В таком случае вычисления будут происходить только при выставленном соответствующем уровне лога. В языке Go для реализации ленивого вычисления в логер можно передать объект поддерживающий интерфейс Stringer.После того, как разобрались с использованием уровней логов, нужно ещё уметь связывать разрозненные сообщения, особенно это актуально для многопоточных приложений или связанных между собой отдельных сервисов, когда в логах все сообщения оказываются вперемешку.
Типичный формат строки сообщения в логе можно условно разделить на следующие составные части:
[system info] + [message] + [context]
Где:
system info
: метка времени, ид процесса, ид потока и другая служебная информацияmessage
: текст сообщенияcontext
: любая дополнительная информация, контекст может быть общим для сообщений в рамках какой то операции.
Для того, чтобы связать пары запрос\ответ часто используется http заголовок X-Request-ID
. Такой заголовок может сгенерировать клиент, или он может быть сгенерирован на стороне сервера. Добавив его в контекст каждой строчки лога появится возможность лёгким движением руки найти все сообщения возникшие в рамках выполнения конкретного запроса. А в случае распределенных систем, заголовок можно передавать дальше по цепочке сетевых вызовов.
Но с единым контекстом в рамках запроса возникает проблема с различными ORM, http клиентами или другими сервисами\библиотеками, которые живут своей жизнью.
reqLog := log.WithField("requestID", requestID)
После этого такой экземпляр логера можно передать как зависимость в другие объекты. Но отсутствие стандартизированного интерфейса логирования (например как psr-3 в php) провоцирует создателей библиотек хардкодить малосовместимые реализации логеров. Поэтому если вы пишите свою библиотеку на Go и в ней есть компонент логирования, не забудьте предусмотреть интерфейс для замены логера на пользовательский.
Резюмируя:
- Логируйте с избытком. Никогда заранее не известно сколько и какой информации в логах понадобится в критический момент.
- Восемь уровней логирования — вам действительно столько надо? По опыту должно хватить максимум 3-4, и то при условии, что для них настроены обработчики событий.
- По возможности используйте ленивые вычисления для вывод сообщений в лог
- Всегда добавляйте текущий контекст в каждое сообщение лога, как минимум requestID.
- По возможности настраивайте сторонние библиотеки таким образом, чтобы они использовали логер с текущим контекстом запроса.
Логирование или как вести летопись работы программы — NTA на vc.ru
NTA
26 фев 2020Написали программу с применением нейросети, но она выдает кучу ошибок? Где потом искать эти ошибки? Как структурировать полученную информацию?
5504 просмотров
Помочь с поиском ошибок может логирование — группа методов для сбора и сохранения информации о работе программы. Всю интересующую нас информацию мы можем записывать в текстовые файлы и потом их обрабатывать. К примеру, вот таким образом в случае деления на 0:
Тогда консоль нам покажет следующее:
А в логе с файлом увидим:
Конечно, реализовать самостоятельно такой способ — просто, и многие этим пользуются. Но у него тоже есть минус: если проект большой, надо не забывать придерживаться определенного формата их заполнения.
Но Python же один из самых дружелюбных языков.) Разработчики уже подумали о нас и создали хорошую библиотеку «logging».
Для работы с ней нам необходимо импортировать библиотеку logging и указать основные параметры. Всего параметров для настройки 6.
Так же существует 5 уровней логирования информации: от DEBUG (отладка) до critical (критичные ошибки).
На этом можно закончить с теорией, и перейдем к практике.
Теперь мы будем логировать нашу функцию деления уже с учетом модуля logging и попытаемся собрать максимум информации о ее работе. Давайте рассмотрим код нашего простенького скрипта, но уже с учетом использования логов.
Как мы видим он немного увеличился в размерах, но при этом, для записи также использует лишь одна строчка.
В начале мы создаем переменную, в которой указываем идентификатор лога. Это нужно для того, к примеру, чтобы мы не путались из какого скрипта записываем лог. Это делается строкой —
logger = logging.getLogger(‘Stat’) —
После – мы указываем уровень лога и имя файла, в который мы будем его записывать:
logger.setLevel(logging.INFO) file_name = logging.FileHandler(‘data.log’)
В конце нам надо создать формат записи, в котором мы укажем: время записи, имя скрипта, названия уровня и само сообщение. Остается только применить данный формат для нашего «логгера».
format_log = logging.Formatter(‘%(asctime)s — %(name)s — %(levelname)s — %(message)s’) file_name.setFormatter(format_log) logger.addHandler(file_name)
Вот, на этом и все) В дальнейшем мы можем использовать наш логгер простым вызовом logger.info(‘Division’) или в случае описания ошибки logger.error(error_text). По окончанию работы скрипта данные будут сохранены в файл ‘data.log’.
А теперь посмотрим, что мы получили в логе:
Запись со временем, уровнем и сообщением! Такой лог, во-первых – удобно читать, а, во-вторых – удобно обрабатывать!
Использование модуля «logger» на маленьких программах, может, и не заметно, а вот на больших польза становится очевидна. Особенно, если эти логи в дальнейшем нуждаются в обработке, например, для Process Mining-а.
Вот таким простым способом мы с вами научились делать понятную и удобную запись логов в нашем скрипте!
Как вести эффективные журналы, соблюдая несколько простых правил.

Журналы обычно недооценивают как часть процесса разработки. Мы действуем так, как будто наш код действителен с самого начала, но это далеко не так. Наш код подвержен ошибкам, особенно пока он находится в разработке. Мы не записываем нужные вещи или вообще не пишем журналы. Не делая этого, мы усложняем процесс поиска ошибок и отнимаем больше времени, тем самым снижая нашу производительность.
Хорошая новость заключается в том, что есть простое решение: вам просто нужно начать вести содержательные журналы с нужным объемом информации. «Легче сказать, чем сделать», — скажете вы. Оставайтесь с нами, и вы увидите, что это довольно легко, если следовать нескольким простым правилам.
Приложения обычно используют внешний файл для определения своего поведения.
Вы должны всегда регистрировать загруженные свойства приложения при запуске приложения.
Почему? Это распространенная ошибка при установке приложения в новой среде. У нас редко получается с первой попытки. Мы хотим знать, какие свойства приложения загружены, чтобы убедиться, что правильные свойства приложения загружаются при запуске приложения. Мы не хотим запускать приложение, а затем ждать, пока кто-нибудь предупредит нас, что приложение не работает должным образом из-за недопустимых значений свойств приложения.
Немедленно регистрируйте их и обязательно проверяйте после запуска приложения.
Уровень журнала — INFO
На предыдущем шаге мы записывали загруженные параметры приложения. Но мы не зарегистрировали фактические параметры, которые используются для создания реальных клиентов. Зарегистрируйте их во время построения клиента, чтобы предоставить информацию о фактических используемых параметрах.
Почему? Бывают ситуации, когда мы помещаем правильное значение свойства в файл свойств, но не используем правильный параметр для построения клиента. Мы хотели бы знать, какой URL-адрес мы собираемся использовать для определенного клиента в приложении. Мы не хотим запускать тест только для того, чтобы узнать, что мы используем неправильный URL. Мы хотим узнать об этом как можно скорее, а запуск приложения — как раз вовремя.
Уровень журнала — ИНФОРМАЦИЯ
Большинство наших приложений предоставляют какой-либо API для запуска определенных действий. Запишите имя метода и аргументы метода для каждого предоставленного метода. Регистрируйте каждый вызов API.
Почему? Если есть проблема со связью между двумя службами, вы, как вызываемый абонент, захотите узнать:
- API, который был вызван
- Параметры, которые были переданы
Эта информация наряду с состоянием базы данных имеет решающее значение для процесс устранения ошибок. Состояние базы данных является постоянным, и вы можете получить к нему доступ все время, но вызов метода не будет, если вы не сделаете его постоянным в журналах. Поместите информацию в журнал с самого начала, чтобы свести к минимуму время, необходимое для устранения ошибки.
Уровень журнала — ИНФОРМАЦИЯ (отладка, если аргументы метода большие)
Аналогично предыдущему правилу, для каждого обращения к сторонней системе регистрируйте URL-адрес, вызываемый с отправленным запросом.
Почему? Если есть проблема со связью между двумя службами, вызываемый запросит у вас следующую информацию:
- Целевой URL/тема
- Отправленные аргументы метода.
Первое, что сделает вызываемый, это просмотрит журналы, чтобы увидеть, что было вызвано, и есть ли несоответствие между отправленными и полученными параметрами. Поместите эту информацию в журнал с самого начала, чтобы свести к минимуму время, необходимое для устранения ошибки.
Уровень журнала:
- INFO для вызываемого URL
- DEBUG для запроса и ответа
Комментариев в коде следует избегать, насколько это возможно. Вместо этого вы должны поместить журналы в код, где вы обычно размещаете комментарии. Таким образом, вы объясните свое намерение разработчику, если оно недостаточно понятно из кода, и тестировщику, тестирующему ваше приложение.
Почему? Тестер должен понимать логику приложения, просто просматривая логи. В большинстве случаев они определят ошибку, просто взглянув на выходные данные журналов. Конечно, это предполагает, что вы достаточно вошли в систему.
Уровень журнала — INFO или DEBUG в зависимости от уровня предоставленной информации
Пути журнала, используемые вашим приложением, если в вызове API доступно несколько путей. Зарегистрируйте любой пройденный путь, почему он был пройден, и запишите параметры, которые заставили вас пойти по этому конкретному пути.
Почему? Когда приложение ведет себя не так, как вы ожидали, у вас будет вся необходимая информация, чтобы отследить, где ваша логика пошла по неверному пути.
Уровень журнала — INFO или DEBUG в зависимости от уровня предоставленной информации
Записывать трассировку стека всех исключений. Не просто помещайте сообщение об ошибке в журналы.
Почему? Исключением является то, что не должно происходить в вашем коде. Когда это произойдет, вы захотите узнать, на какой линии он сломался. Сделав это, вы узнаете точный номер строки, из-за которой ваше приложение сломалось. Обязательно запишите всю трассировку стека. Помните, когда дело доходит до исключений, любая информация полезна.
Уровень журнала — ОШИБКА
На эту тему можно было бы написать больше, но если вы будете следовать перечисленным выше правилам, вы сделаете большой шаг к тому, чтобы стать лучшим разработчиком.
Спасибо за внимание!
The Writing Log — Writing Commons
Вместо того, чтобы ждать этого иллюзорно большого отрезка времени и вместо того, чтобы откладывать до последней минуты, чтобы начать исследования и писать, вы можете обеспечить свой успех, используя небольшие отрезки времени для выполнения своих исследований и написание целей.
Исследования показали, что запойное письмо имеет серьезные недостатки по сравнению с обычным письмом. Во-первых, запойное письмо имеет тенденцию стимулировать маниакально-депрессивное поведение (Бойс). Сторонники запойного письма могут наслаждаться приливом адреналина, ожидая до последней минуты, чтобы исследовать и писать, а затем лихорадочно излагать слова в своих мыслях. Тем не менее, как только проект представлен, люди часто чувствуют эмоциональное разочарование, особенно если они допоздна пытались выполнить задание. Во-вторых, запойное письмо не обеспечивает авторам эмоциональной и интеллектуальной дистанции, необходимой им для критического отношения к нашим идеям и изложению. Как все мы, кто когда-либо выпивал, знаем, что у нас могут возникнуть трудности с критикой черновиков, которые мы только что сочинили. Напротив, по прошествии некоторого времени после того, как мы завершили набросок, мы испытали удивление, обнаружив большое количество проблем в наших черновиках. В-третьих, если запойное написание приводит к менее эффективному конечному продукту, то мы, вероятно, столкнемся с дополнительной критикой со стороны читателей.
Наконец, и это может быть наиболее важным моментом, запойное письмо может привести к большему эмоциональному и физическому стрессу.
Сидеть перед монитором до тех пор, пока все слова не начнут танцевать вместе, яростно печатать на клавиатуре до тех пор, пока руки не свело судорогой и не образовался тоннель плодолистика, напрягая шею и спину из-за неподвижного сидения в течение длительного времени — все эти действия, связанные с запойным письмом, могут усугубляет нашу неприязнь к дополнительному письму в будущем, тем самым обеспечивая непрерывный цикл обширной прокрастинации и переедания. Ценность регулярного письма в отличие от запойного письма, такого как рассказ о черепахе и зайце, возможно, лучше всего выражается в здравом смысле: «Найдите занятого человека, если хотите что-то сделать». Успешные исследователи и писатели усвоили, что импульс необходим для успеха, а импульс усиливается регулярным ежедневным письмом. Короче говоря, как пошутил один мудрый автор: «Вдохновение — это искусство прижимать штаны к стулу перед текстовым процессором».
Таблица 1: Рекомендации по ведению ежедневного письма
|
Таблица 2: А.
Goals
Поначалу вы можете сомневаться в ежедневных звонках Bowhatsantice. Некоторым из вас, возможно, говорили другие профессора, что на них работает запойное писательство. И вполне возможно, что запойное писательство может привести к прекрасной прозе (сразу на ум приходит «Франкенштейн» Мэри Шелли). Короче говоря, вы будете смотреть на изменение образа жизни. Вы получите много преимуществ от регулярного письма. Хотя вы, возможно, никогда не полюбите писать, вы узнаете — как только вы наберете обороты — что можете найти свой голос, развивать идеи с большим авторитетом и создавать более эффективные документы с меньшими усилиями и за меньшее время.
В Таблице 2 выше приведен образец листа журнала, который вы можете использовать для поддержки регулярного написания с вашей стороны. Как и в случае с любой другой «новой привычкой», которую вы пытаетесь выработать, рекомендуется попробовать записывать свою работу в течение как минимум 21 дня, прежде чем даже задуматься о том, полезна ли эта стратегия. Вначале заглушите критический голос внутри себя, который говорит, что эта техника просто не сработает.
Записывая свою работу, вы сможете увидеть, как небольшие отрезки времени, потраченные на написание, могут привести к большим достижениям. Вы также можете вознаградить себя, отметив, как много различных действий, таких как поиск источника в библиотеке, обсуждение идеи с другом, поход в поле или лабораторию, являются неотъемлемой частью писательства.
Причина записи даты, отработанных часов и количества написанных и удаленных слов достаточно очевидна. (Например, записывая наши истинные рабочие графики, мы менее склонны преувеличивать свои письменные нагрузки и лучше понимаем, сколько времени на самом деле требуется для завершения проекта.) Что, однако, может быть менее очевидным, так это необходимость следите за «классом письма», «письменной/исследовательской деятельностью» или «ощущением себя как писателя».
«Класс письма» относится к наблюдению Максин Хейрстон о том, что разные письменные продукты, вероятно, потребуют разных процессов написания. Хейрстон описывает письмо «класса 1» как рутинное написание сообщений — что-то вроде заметок, которые вы могли бы написать соседу по комнате о продуктах, которые нужно купить в магазине. В отличие от письма класса 1, письмо класса 2 может потребовать одной или двух исправлений, но в целом эта форма письма относится к тем видам письма, которые мы регулярно делаем как часть нашей профессиональной и личной жизни. Напротив, письмо «Класса 3» является спекулятивным, открытым, и, вероятно, потребует тщательного пересмотра. Когда мы пишем в классе 3, мы открываем для себя смысл по мере того, как сочиняем (в отличие от записи того, что уже поняли), позволяя нашему мышлению и письму созреть и вырасти. Определив класс письма, которым вы пытаетесь заниматься, вы сможете лучше понять свое писательское поведение. В результате вы с большей вероятностью будете менее требовательны к себе, когда застрянете в блокпосте. Другими словами, если вы чувствуете разочарование и неуверенность в том, как действовать дальше, вы можете столкнуться со знанием того, что такие чувства типичны для письма класса 3. Кроме того, если вы обнаружите, что все, что вы пишете, относится к категории 2 класса, то есть если вы всегда точно знаете, что хотите сказать и как вы хотите это сказать, тогда вы можете извлечь пользу, осознавая, что вам, возможно, придется отпустить ситуацию. немного, будьте более гибкими и старайтесь больше писать в классе 3.
В свою очередь, запись вашей «Писательской/исследовательской деятельности» может помочь вам лучше понять, что нужно для успешного исследования и написания. Например, многие писатели сообщают, что запись своей деятельности помогает им увидеть, что они действительно работают над проектом, когда им кажется, что они стоят на месте. Например, может казаться, что мы ничего не добились в нашем проекте, но затем, когда мы садимся записывать связанные действия, такие как разговор с друзьями об идее, телефонные звонки для сбора информации для проекта , проведя поиск по базе данных — мы видим, что действительно участвовали в проекте. Что еще более важно, записывая действия, которые вы выполняете, вы можете лучше убедиться, что не станете одержимы одним конкретным занятием. Например, если вы предпочитаете проводить исследования, а не писать, вы можете попасть в ловушку, потратив больше времени, чем необходимо, на исследования и меньше времени на написание. (В конце концов, в нашем информационном мире, где каждую минуту публикуются десятки статей, можно буквально провести всю жизнь, анализируя исследовательский вопрос, не написав. ) К сожалению, нельзя дать точный процент, чтобы указать, сколько времени следует потратить на исследование, а не письмо. Каждый документ, который вы пишете, может предъявлять к вам разные требования, особенно когда документы адресованы разным аудиториям и целям.
Настоятельно рекомендуется отслеживать ваши «Чувства о себе как о писателе». Это демонстрирует, насколько пагубными, насколько экспансивными могут быть негативные мысли. Как мы все знаем, написание может быть трудной работой, окруженной самокритикой, критикой других и ограничениями нашего ума и расписания. К сожалению, мы можем быть парализованы молчанием, если будем прислушиваться к негативным голосам внутри себя — голосам, которые говорят, что проект не стоит продолжения или что мы не способны просто выразить сложные отношения. Если вы обнаружите, что постоянно записываете негативные мысли о своих исследованиях и писательских процессах, а также о своем писательском потенциале, мы предлагаем вам записать свои негативные мысли на странице. Часто, как только ужасы записаны, мы видим, насколько они нелогичны, и начинаем заменять их более позитивными мыслями. Вы также можете найти полезным поделиться своими журналами с другими авторами, которые хотят (и готовы) обсуждать свои процессы написания.
Ведьте Еженедельный журнал записи гибко и позитивно. Например, когда вы записываете количество слов, написанных и исправленных, не зацикливайтесь на попытках дать точное количество слов. Вместо этого используйте текстовый процессор для подсчета слов перед тем, как писать, а затем подсчитывайте количество слов в файле после того, как вы закончили писать за день. Не беспокойтесь о точном подсчете количества удаленных слов. В конце концов, ваш учитель не работает в IRS. Помните, прежде всего, что Еженедельник предназначен для того, чтобы помочь вам обрести свой голос как ученого и исследователя. Журнал не предназначен для того, чтобы быть листом вины или своего рода записью, которую, по вашему мнению, заключенный должен вести, чтобы стать лучше.