Лучшие практики для регистрации и трассировки в .NET

53

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

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

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

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

Теперь, скажем, я хочу выполнять свою трассировку и ведение журнала, используя только стандартные классы .NET, которые находятся в System.Diagnosticsпространстве имен. Я подумал, что класс TraceSource лучше для работы, чем статический класс Trace, потому что я хочу различать уровни трассировки и, используя класс TraceSource, я могу передать параметр, информирующий тип события, в то время как используя класс Trace, я должен использовать Trace.WriteLineIfа затем проверять такие вещи, как SourceSwitch.TraceInformationи SourceSwitch.TraceErrors, и у него даже нет таких свойств, как TraceVerboseили TraceStart.

Имея это в виду, рассмотрите ли вы хорошую практику, чтобы сделать следующее:

  • При начале метода проследите событие «Пуск», которое должно представлять одну логическую операцию или конвейер, а также строковое представление значений параметров, переданных методу.
  • Отслеживание события «Информация» при вставке элемента в базу данных.
  • Проследите событие «Информация» при переходе по тому или иному пути в важном операторе if / else.
  • Проследите «Критическое» или «Ошибка» в блоке перехвата в зависимости от того, является ли это исправимой ошибкой.
  • Отслеживание события «Стоп» при завершении выполнения метода.

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

Примечание. Я нашел здесь полезную информацию, но все еще не то, что мне нужно: http://msdn.microsoft.com/en-us/magazine/ff714589.aspx

Levidad
источник
какой-нибудь пример приложения с полным исходным кодом, использующий хорошие шаблоны для регистрации?
Kiquenet
Честно говоря ... Если бы я работал с .NET, я бы, наверное, просто установил что-то вроде New Relic и сказал, что все готово. (Может быть, не очень хороший вариант, когда это было опубликовано)
svidgen

Ответы:

17

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

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

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

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

Отслеживание параметров также может быть плохой идеей . Вы должны думать, что отслеживать, в каждом конкретном случае. Например, действительно плохо отслеживать параметры метода void Authenticate(string userName, string plainPassword).

Отслеживание события «Информация» при вставке элемента в базу данных.

По-разному. Некоторые элементы должны быть прослежены, но не каждый элемент.

  • Например, представьте, что вы фактически вставляете элемент журнала в свою базу данных. Будете ли вы отслеживать журналы? А потом логировать следы? А потом отслеживать трассировку?
  • Другой пример: вы вставляете конфиденциальные данные. Это требует аудита. Поскольку вы проверяли вставку, зачем ее отслеживать?

Проследите событие «Информация» при переходе по тому или иному пути в важном операторе if / else.

Опять же, это зависит.

Отслеживание «Критическое» или «Ошибка» в блоке перехвата в зависимости от погоды - это исправимая ошибка.

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

Отслеживание события «Стоп» при завершении выполнения метода.

Смотрите первый пункт.

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

Подробный:

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

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

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

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

Предупреждение:

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

Примеры:

  • Пример 1: приложению не удалось открыть файл, который пользователь запросил открыть. Файл существует и не используется, права доступа установлены правильно, но что-то блокирует открытие файла. В этом случае вы обнаружите ошибку , так как ваше приложение не может справиться с этим делом и продолжает работать так, как ожидал пользователь (то есть фактически читает файл).

  • Пример 2: после проверки ошибки в первом примере вы обнаружите, что ошибка вызвана тем, что путь к файлу длиннее 259 символов. Таким образом, вы реорганизуете свой код для отлова PathTooLongException. Когда в следующий раз пользователь пытается открыть тот же файл, новая версия приложения показывает сообщение, объясняющее, что файл слишком длинный и должен быть перемещен в другую папку, чтобы сократить полный путь, чтобы открыть этот файл в это приложение. Вы также отслеживаете сообщение .

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

  • Пример 4: открытый файл отображается некорректно. Вы включаете подробную трассировку, где вы фактически видите, как данные загружаются из файла, а затем анализируются, шаг за шагом.

Арсений Мурзенко
источник
Один шаблон, который мы используем в своей работе, - это запись «KnownErrors» в качестве предупреждений и «UnknownErrors» в качестве ошибок. Может быть неуместно в зависимости от вашей инфраструктуры и того, как она работает с предупреждениями, но это хорошо работает для нас.
Андрей говорит восстановить Монику
5
 > say I want to do my tracing and logging using only the standard .NET classes

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

К сожалению, если вы хотите использовать, System.Diagnosticsвы должны знать заранее ( во время разработки ), какие потоки трассировки должны быть доступны. (В статье-примере это Transfer, Resume, Suspend, ...). Их можно настроить на Disabled, Debuglevel или Errorlevel.

Я предпочитаю иметь систему ведения журналов, где я могу решить во время выполнения на уровне классов / уровнях имен , насколько подробным должно быть ведение журналов. Например, все отладки и выше от MyNamespace.Business.*но нет MyNamespace.Business.Calculations.

Если вы используете log4net (или Common.logging), каждый класс получает свой собственный регистратор, так что вы можете легко решить, какие классы будут регистрироваться на каком уровне.

Поскольку операции с базами данных находятся в отдельном классе, больше нет необходимости в отдельном правиле

Trace an "Information" event when inserting an item into the database.

Вместо этого я предпочитаю иметь эти рекомендации:

  • Tracelevel должен показывать основной рабочий процесс
  • Отладочный уровень должен отображать подробные данные и обработку в рабочем процессе, включая решения в программном процессе с указанием причин (Создание нового элемента, поскольку элемент не существует в БД)
  • Информационный уровень для запуска / остановки служб и одна запись для каждого запускаемого рабочего процесса / действия с графическим интерфейсом
k3b
источник
Понятно, это хорошая информация, спасибо! Но, тем не менее, как я спрашиваю в своем первоначальном вопросе, не могли бы вы уточнить использование типов событий Verbose и Warning? А также, я прошу других людей внести свой вклад в их точку зрения, потому что эта тема заслуживает более глубокого изучения, чем я видел в Интернете.
Левидад
4

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

Он автоматически добавит понятия «начало» и «остановка» в качестве начала и конца истории.

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

Также больше информации об этом сообщении в блоге

Амит Яблоко
источник
1
обновленный ответ с дополнительной информацией
Amit Apple,