Как Использовать Свойство Exception.data Для Регистрации Дополнительной Информации Об Исключениях

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

Поэтому стоит добавить более подробную информацию об исключениях.

Один из способов — добавить дополнительную информацию в тело сообщения об исключении.

Как в коде ниже.

  
  
  
  
  
   

try { return await _ordersRepository.Get(id, cancellationToken); } catch (Exception exception) { throw new Exception($"Unable to get order info, user {userName}, order id {id}", exception); }

Но при таком подходе сложно создавать сообщения.

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

Нам следует избегать отправки пользователю такой информации, как идентификаторы.

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

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

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

Класс исключений .

NET Framework имеет свойство Данные , который уже обеспечивает хранение дополнительной информации в виде набора заданных пар ключ-значение.

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

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

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

Половина классов исключений .

NET Framework имеют свойства, которые не регистрируются — вы можете добавить эти данные в свойство Exception.Data вашего нового исключения.

Свойство Внутреннее исключение будет содержать ссылку на исходное исключение.

Код ниже демонстрирует, как использовать свойство Exception.Data.

try { return await _ordersRepository.Get(id, cancellationToken); } catch (Exception exception) { const string message = "Unable to get order info"; var yourException = new YourAppException(message, exception); yourException.Data[nameof(userName)] = userName; yourException.Data[nameof(id)] = id; throw yourException; }

Упс.

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



try { return await _ordersRepository.Get(id, cancellationToken); } catch (Exception exception) { throw exception.With("Unable to get order info") .

DetailData(nameof(userName), userName) .

DetailData(nameof(id), id); }

Давайте рассмотрим пример настройки Макет Нлога для регистрации свойства Exception.Data.

${shortdate} ${time} [${level:uppercase=true}]: ${message:withException=true}${when:when=length('${exception:format=Data}')>0:Inner=${newline}--- Exception Data ---${newline}${exception:format=Data:exceptionDataSeparator=,\r\n}}

Как это выглядит в консоли.



Как использовать свойство Exception.Data для регистрации дополнительной информации об исключениях

Этот пример отлично работает, если вы добавляете простые структуры: NLog вызывает ToString() для записи значений в цели.

Следовательно, мы можем правильно закладывать объекты только в том случае, если они правильно переопределяют метод ToString().

Но переопределить ToString для всех классов практически невозможно.

Самый простой способ представить объект в виде строки — сериализовать его в JSON. Код ниже добавляет класс C#, который делает это.



/// <summary> /// Defines a value/json pair to represent an exception data value as JSON /// </summary> public record ExceptionDataEntry { private static readonly JsonSerializerOptions SerializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, Converters = {new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)}, WriteIndented = true }; private ExceptionDataEntry(in object value, in string json) { Value = value; Json = json; } public object Value { get; } public string Json { get; } public static ExceptionDataEntry FromValue(in object value) { if (value == null) { throw new ArgumentNullException(nameof(value)); } var json = JsonSerializer.Serialize(value, SerializerOptions); return new ExceptionDataEntry(value, json); } /// <summary> /// Represents an exception data value as JSON /// </summary> /// <returns></returns> public override string ToString() { return Json; } }

И этот код добавляет расширение.



public static YourAppException DetailData(this YourAppException exception, in string key, in object value) { try { exception.Data[key] = ExceptionDataEntry.FromValue(value); } catch { // ignored, because we use it inside another exception catch block // so, we should avoid throwing a new exception to keep the original exception } return exception; }

Как это будет выглядеть в консоли в нашем примере.



Как использовать свойство Exception.Data для регистрации дополнительной информации об исключениях

Я надеюсь, что этот подход к использованию Exception.Data для регистрации дополнительной информации поможет вам в поддержке приложений.

Если у вас есть идеи, как улучшить предложенный подход, пишите в комментариях.

Спасибо =) Теги: #программирование #C++ #мониторинг #ведение журнала #.

NET #отладка #обработка ошибок #журналы #ведение журнала #Exception #NLog #Exception

Вместе с данным постом часто просматривают: