Подтвердить что ты не робот

Какая у вас философия ведения журнала?

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

4b9b3361

Ответ 1

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

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

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

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

Регистрация протоколов

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

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

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

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

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

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

Ответ 2

Я работаю с критическими системами безопасности в реальном времени, и регистрация часто является единственным способом поймать редкие ошибки, которые появляются только каждые 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, но это можно изменить в поле через диалог отладки (или параметр registry/ini/cfg, где эти вещи будут сохранены).

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

Что мой мозг свалился...

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

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

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

Ответ 6

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

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

Ответ 7

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

Кроме того, это помогает вам сузить ТОЧНО, где происходит ошибка.

Ответ 8

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

Ответ 9

Запишите все и отпустите Grep.

Ответ 10

Я определяю множество уровней и передаю настройки с помощью config/invocation.

Ответ 11

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

Ответ 12

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

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

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

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

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

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

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