try
{
// Code
}
catch (Exception ex)
{
Logger.Log("Message", ex);
throw;
}
В случае библиотеки я должен даже зарегистрировать исключение? Я должен просто бросить его и позволить приложению регистрировать его? Мое беспокойство - то, что, если я регистрирую исключение в библиотеке, будет много дубликатов (потому что слой библиотеки зарегистрирует его, прикладной уровень зарегистрирует его, и что-либо промежуточное), но если я не зарегистрирую его в библиотеке, то будет трудно разыскать ошибки. Существует ли лучшие практики для этого?
I не будет регистрировать исключение, с которым я не собирался ничего делать, т.е. если оно просто проходит через обработчик исключений, как в вашем примере. Как вы уже упоминали, это добавляет много шума, который не обязательно помогает. Лучше регистрировать его в том месте, где вы действительно что-то с этим делаете, или, в случае библиотеки, на границе, где он переходит в код пользователя.
Тем не менее, я всегда пытаюсь войти в тот момент, когда я генерирую исключение и условие, которое вызвало исключение. Это гораздо полезнее, чтобы определить причину исключения; плюс, если условие, с которым вы столкнулись, достаточно плохое, чтобы вызвать исключение, я бы сказал, что это также гарантирует, что процессорное время будет тратить время на вывод «почему».
Исключения журнала также могут быть методом отладки приложения.
Вы должны зарегистрировать это, а также выбросить его, чтобы приложение имело доступ к нему для регистрации. В частности, если это библиотека, вам следует ее регистрировать, поскольку вы не должны предполагать, что приложение определенно ее зарегистрирует! (Может быть, а может и нет).
Используйте log4net . Шутки в сторону.
Используя такую стандартную и повсеместную библиотеку, вы получите рекомендации от людей, которые долгое время размышляли над этой самой проблемой. Решение состоит в том, что большинство библиотек журналов имеют несколько уровней ведения журналов.
В log4net, например, я могу сделать
ILog log = LogManager.GetLogger("some logger");
log.Debug("some debugging info");
log.Info("some message meaningful in the domain");
log.Warn("something might be occurring that merits your attention");
log.Error("Everything just went to hell")
Затем администратор приложения может установить различные уровни ведения журнала, которые он хочет видеть. Можно даже разрешить ему изменять эту конфигурацию во время выполнения. Фактически, с помощью надежной библиотеки журналов, такой как log4net, вы можете направлять разные уровни журналирования из разных источников в разные приложения. Например, вы можете иметь динамический файл со всеми сообщениями журнала за последнюю неделю, хранящимися на жестком диске, всю информацию, предупреждения и сообщения об ошибках, которые не происходят в вашем уровне доступа к данным, помещенные в базу данных, и все отправленные ошибки. вам по электронной почте.
Я думаю, что то, что вы описываете, довольно четко относится к уровню журнала «отладки».
Вы, конечно, можете реализовать уровни ведения журнала самостоятельно, но если кто-либо, использующий вашу библиотеку, заинтересован в просмотре всей отладочной информации, им придется изучить вашу систему в дополнение к той, которую они используют.Лучше стандартизировать.
Итак, передовой опыт:
Я предпочитаю оставлять протоколирование на самом высоком уровне клиента, или позволять клиенту включать/выключать протоколирование потенциально, предоставляя библиотеке TextWriter, на который библиотека должна протоколировать свои ошибки/выводы в случае, если она работает в среде, где у нее нет разрешения писать в свой обычный журнал.
Причина, по которой я предпочитаю вести журнал на более высоких уровнях, заключается в том, что более высокие уровни имеют больше контекстной информации и могут знать более подходящие способы сообщить/записать эти ошибки в журнал. Поскольку в наши дни исключения в любом случае содержат всю информацию о трассировке стека, я не думаю, что вы много выиграете, если будете вести журнал сразу после возникновения исключения. Однако нужно быть осторожным с исключениями, которые преобразуются в другие виды исключений, поэтому постоянно используйте InnerException, если вы преобразуете исключения в процессе их обработки, чтобы сохранить всю информацию об источнике ошибки.
Edit: Конечно, эта философия работает только в тех средах, где соблюдается другая моя философия: никогда не игнорировать исключения. Если клиент или какой-то промежуточный уровень отбрасывает исключения, то у вас есть другие проблемы, и, вероятно, вам придется, по крайней мере, установить по умолчанию журнал исключений на какой-то вывод, который генерируется, даже если клиент безответственен.