Какова ваша философия лесозаготовок? - PullRequest
22 голосов
/ 04 сентября 2008

Как Джефф Этвуд спросил : «Какова ваша философия ведения журнала? Должен ли весь код быть засорён вызовами .logthis() и .logthat()?

Ответы [ 12 ]

21 голосов
/ 04 сентября 2008

Моя философия лесозаготовок довольно легко описана в четырех частях:

Аудит или ведение журнала бизнес-логики

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

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

Регистрация программы

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

Как правило, это ведение журнала включается и выключается по мере необходимости для отладки сеансов.

Регистрация производительности

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

Ведение журнала безопасности

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

15 голосов
/ 14 февраля 2009

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

Я разрабатываю системы, которые способны регистрировать практически все, но я не включаю все по умолчанию. Отладочная информация отправляется в скрытое диалоговое окно отладки, которое ставит метки времени и выводит его в список (ограниченный до 500 строк перед удалением), и диалоговое окно позволяет мне остановить его, автоматически сохранить в файле журнала или перенаправить в подключенный отладчик, такой как DBWin32. Это отвлечение позволяет мне видеть вывод отладки из нескольких приложений, все аккуратно сериализованные, что иногда может быть спасением. Файлы журнала автоматически удаляются каждые N дней. Я использовал для использования числовых уровней ведения журнала (чем выше вы устанавливаете уровень, тем больше вы захватываете):

  • от
  • только ошибки
  • основной
  • подробно
  • все

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

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

#define DEBUG_ERROR          1
#define DEBUG_BASIC          2
#define DEBUG_DETAIL         4
#define DEBUG_MSG_BASIC      8
#define DEBUG_MSG_POLL       16
#define DEBUG_MSG_STATUS     32
#define DEBUG_METRICS        64
#define DEBUG_EXCEPTION      128
#define DEBUG_STATE_CHANGE   256
#define DEBUG_DB_READ        512
#define DEBUG_DB_WRITE       1024
#define DEBUG_SQL_TEXT       2048
#define DEBUG_MSG_CONTENTS   4096

Эта система ведения журнала поставляется с версией сборки, включенной и сохраняемой в файл по умолчанию. Уже слишком поздно выяснять, что вы должны были регистрироваться ПОСЛЕ возникновения ошибки, если эта ошибка возникает в среднем раз в шесть месяцев и у вас нет возможности ее воспроизвести.

Программное обеспечение обычно поставляется с включенными ERROR, BASIC, STATE_CHANGE и EXCEPTION, но это можно изменить в поле с помощью диалогового окна отладки (или настройки реестра / ini / cfg, где эти вещи сохраняются).

Да, и одно - моя система отладки генерирует один файл в день. Ваши требования могут отличаться. Но убедитесь, что ваш код отладки начинает каждый файл с датой, версией кода, который вы запускаете, и, если возможно, каким-то маркером для идентификатора клиента, местоположения системы или чего-либо еще. Вы можете получить кучу файлов журналов, поступающих с поля, и вам понадобится некоторая запись того, откуда и какая версия системы, на которой они работали, на самом деле в самих данных, и вы не можете доверять клиенту. / Инженер-полевой, чтобы сказать вам, какая у них версия - они могут просто сказать, какую версию, по их мнению, они получили. Хуже того, они могут сообщить версию exe, которая находится на диске, но старая версия все еще работает, потому что они забыли перезагрузить компьютер после замены. Пусть ваш код скажет вам сам.

Это мой мозг сброшен ...

4 голосов
/ 04 сентября 2008

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

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

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

1 голос
/ 14 февраля 2009

Зарегистрируйте их все и позвольте Grep отсортировать их.

1 голос
/ 04 сентября 2008

Если вы пишете программу, которая будет использоваться многими людьми, лучше всего иметь какой-то механизм выбора того, что будет зарегистрировано, а что нет. Одним из аргументов в пользу функций .logthis () является то, что в некоторых случаях они могут быть отличной заменой встроенных комментариев (если все сделано правильно).

Кроме того, это поможет вам точно выяснить, где происходит ошибка.

1 голос
/ 04 сентября 2008

Я начинаю с утверждения множества условий в моем коде (в C #, используя System.Diagnostics.Assert), но я добавляю логирование только там, где я нахожу, при отладке или нагрузке на систему, что мне действительно нужно найти способ следить за тем, что происходит внутри моего кода, без постоянного отладчика.

В противном случае я предпочитаю использовать возможность Visual Studio для помещения трассировок в код в качестве специальных точек останова (т. Е. Вы вставляете точку останова и щелкаете по ней правой кнопкой мыши, затем выбираете «При ударе ...» и сообщаете, что в этом случае отображать ). Нет необходимости перекомпилировать и легко включить / отключить трассировки на лету.

1 голос
/ 04 сентября 2008

Я предпочитаю вести себя намеренно, поскольку это означает, что данные журнала имеют смысл:

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

Использование какой-либо формы внедрения кода, профилирования или трассировки для создания журналов, скорее всего, приведет к созданию подробных, менее полезных журналов, в которые будет труднее углубиться. Однако они могут быть полезны в качестве средства отладки.

1 голос
/ 04 сентября 2008

Я беру то, что считаю традиционным подходом; некоторая регистрация, окруженная условными определениями. Для производственных сборок я отключаю определения.

0 голосов
/ 18 ноября 2015

Я использую ведение журнала как способ сузить проблемы, которые не воспроизводятся в наших модульных тестах, не говоря уже о повторении тех же шагов, которые предоставляет пользователь: те редкие сбои, которые появляются только на некотором очень удаленном оборудовании (а иногда, хотя и очень редко даже из-за сбоя драйвера или сторонней библиотеки вне нашего контроля).

Я согласен с комментарием, что все это должно быть уловлено нашей процедурой тестирования, но трудно найти кодовую базу с миллионами LOC, которая требует очень низкоуровневого, критичного к производительности кода, чтобы когда-либо соответствовать этим требованиям. Я не работаю с критически важным программным обеспечением, но я работаю в графической индустрии, где нам часто приходится делать все: от реализации распределителей памяти до использования кода GPU и SIMD.

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

В качестве примера случая, когда логирование спасло мою задницу, однажды у меня был этот странный пользователь с прототипом машины Intel, которая зависала. Мы перечислили минимальные требования к машинам, которые должны поддерживать SSE 4, но этот конкретный компьютер удовлетворял этим минимальным требованиям и все еще не поддерживал расширения Streaming SIMD после SSE 3, несмотря на то, что он был 16-ядерным. Обнаружение этого стало возможным благодаря просмотру его журнала, в котором был точно указан номер строки, в которой использовались инструкции SSE 4. Никто из нас в нашей команде не мог воспроизвести проблему, не говоря уже об одном другом пользователе, который участвовал в проверке отчета. В идеале мы должны были бы написать код для более старых версий SIMD или, по крайней мере, выполнить некоторые ветвления и проверки, чтобы убедиться, что оборудование соответствует минимальным требованиям, но мы хотели сделать твердое предположение, основанное на минимальных требованиях к оборудованию, для простоты и экономии. Здесь, возможно, можно утверждать, что это были наши минимальные системные требования, которые имели «сбой».

Учитывая то, как я здесь использую логи, мы получаем довольно большие логи. Однако цель заключается не в удобочитаемости - обычно важна последняя строка журнала, отправляемая с отчетом, когда пользователь сталкивается с каким-то сбоем, которого никто из нас в команде (не говоря уже о нескольких других пользователях в мире) может воспроизводить.

Тем не менее, один прием, который я регулярно использую, чтобы избежать чрезмерного спама в журналах, состоит в том, что часто разумно предположить, что часть кода, которая выполняется один раз успешно, также будет делать это впоследствии (не жесткая гарантия, но часто разумное предположение). Поэтому я часто использую функцию log_once для гранулярных функций, чтобы избежать затрат на регистрацию каждый раз, когда она вызывается.

Я не разбрасываю журналы повсюду (возможно, если бы у меня было время). Обычно я резервирую их больше всего для областей, которые кажутся наиболее опасными: код, вызывающий шейдеры GLSL, например (Поставщики графических процессоров здесь сильно различаются по возможностям и даже по тому, как они компилируют код), код с использованием встроенных функций SIMD, код очень низкого уровня, код, который неизбежно должен опираться на поведение, специфичное для ОС, предположения низкоуровневого кода, делающие предположения о представление POD (например: код, который принимает 8 бит на байт) - в тех случаях, когда мы также добавляем множество проверок утверждений и проверок работоспособности, а также пишем наибольшее количество модульных тестов. Как правило, этого достаточно, и ведение журнала спасло мою задницу много раз, и в противном случае я бы взял невоспроизводимый вопрос, и мне пришлось бы делать слепые удары по этой проблеме, требуя многих попыток отскакивания итераций для решения проблемы одного пользователя в мире, который может воспроизвести проблему.

0 голосов
/ 09 февраля 2011

Если вам действительно нужно войти в свою систему, тогда ваши тесты являются дерьмовыми или, по крайней мере, неполными и не очень тщательными. Все в вашей системе должно быть максимально черным ящиком. Обратите внимание, что базовые классы, такие как String, не нуждаются в регистрации - основная причина в том, что они очень хорошо протестированы и работают как подробно. Никаких сюрпризов.

...