Ведение журнала и трассировка в приложениях .NET

Завершено

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

Трассировка — это способ мониторинга выполнения приложения во время его выполнения. Вы можете добавить инструментирование трассировки и отладки в приложение .NET при его разработке. Это инструментирование можно использовать во время разработки приложения и после его развертывания.

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

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

Запись данных в окна вывода

До этого момента мы использовали только консоль для вывода сведений пользователю приложения. Существуют другие типы приложений, созданных с помощью .NET, которые имеют пользовательские интерфейсы, такие как мобильные, веб-приложения и классические приложения, и нет видимой консоли. В этих приложениях System.Console журналы сообщений "за кулисами". Эти сообщения могут отображаться в окне вывода в Visual Studio или Visual Studio Code. Их также можно направить в системный журнал, например logcat в Android. В результате при использовании System.Console.WriteLine в приложении, не являющемся консольным, следует тщательно все обдумать.

Здесь можно использовать System.Diagnostics.Debug и System.Diagnostics.Trace в дополнение к System.Console. Debug и Trace являются частью System.Diagnostics и будут записывать данные в журнал только при присоединении соответствующего прослушивателя.

Вы можете выбрать любой из этих API стиля печати. Ниже описаны основные различия.

  • System.Console
    • Всегда включен и всегда записывает данные в консоль.
    • Полезно для сведений, которые могут потребоваться клиенту в выпуске.
    • Это самый простой подход. Он часто используется для краткосрочных и непредвиденных действий по отладке. Такой код отладки часто даже не попадает в систему управления версиями.
  • System.Diagnostics.Trace
    • Включается только при наличии определения TRACE.
    • Записывает данные в подключенные прослушиватели, по умолчанию это DefaultTraceListener.
    • Используйте этот API при создании журналов, которые будут включены в большинстве сборок.
  • System.Diagnostics.Debug
    • Включается только при определении DEBUG (в режиме отладки).
    • Передает данные в присоединенный отладчик.
    • Используйте этот API при создании журналов, которые будут включены только в сборках отладки.
Console.WriteLine("This message is readable by the end user.");
Trace.WriteLine("This is a trace message when tracing the app.");
Debug.WriteLine("This is a debug message just for developers.");

При проектировании стратегии трассировки и отладки подумайте о том, как должны выглядеть выходные данные. Несколько операторов записи, заполненных несвязанными сведениями, создают журнал, который трудно прочитать. С другой стороны, при использовании метода WriteLine для размещения связанных операторов на разных строках может быть сложно понять, какие сведения связаны друг с другом. Как правило, при использовании нескольких операторов Write имеет смысл объединить информацию из разных источников для создания единого информационного сообщения. Если необходимо создать одно полное сообщение, используйте инструкцию WriteLine.

Debug.Write("Debug - ");
Debug.WriteLine("This is a full line.");
Debug.WriteLine("This is another full line.");

Эти выходные данные выводятся из предыдущего журнала с Debug:

Debug - This is a full line.
This is another full line.

Определение констант TRACE и DEBUG

По умолчанию при запуске приложения в режиме отладки определяется константа DEBUG. Вы можете управлять этим, добавив DefineConstants запись в файл проекта в группу свойств. Ниже приведен пример включения TRACE для конфигураций Debug и Release наряду с DEBUG для конфигураций Debug.

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <DefineConstants>TRACE</DefineConstants>
</PropertyGroup>

Если при использовании Trace нет подключения к отладчику, необходимо настроить прослушиватель трассировки, например dotnet-trace.

Условная трассировка

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

if(count == 0)
{
    Debug.WriteLine("The count is 0 and this may cause an exception.");
}

Это можно переписать в одной строке кода:

Debug.WriteLineIf(count == 0, "The count is 0 and this may cause an exception.");

Эти условия также можно использовать с Trace флагами, которые определяются в приложении:

bool errorFlag = false;  
System.Diagnostics.Trace.WriteIf(errorFlag, "Error in AppendData procedure.");  
System.Diagnostics.Debug.WriteIf(errorFlag, "Transaction abandoned.");  
System.Diagnostics.Trace.Write("Invalid value for data request");

Проверка существования определенных условий

Утверждение или Assert инструкция проверяет условие, указанное в качестве аргумента инструкции Assert . Если условие оценивается true, действие не выполняется. Если условие оценивается, утверждение завершается falseошибкой. Если вы работаете с отладочной сборкой, программа переходит в режим прерывания.

Метод Assert можно использовать из Debug или Trace, которые находятся в пространстве имен System.Diagnostics. Методы класса Debug не включаются в окончательную версию (версию выпуска) программы, поэтому они не увеличивают ее размер и не уменьшают скорость ее выполнения.

Метод System.Diagnostics.Debug.Assert можно свободно использовать для проверки условий, которые должны выполняться, если код программы написан правильно. Например, предположим, что вы написали функцию с разделением целых чисел. По правилам математики делитель не может быть равен нулю. Вы можете проверить это условие с помощью утверждения:

int IntegerDivide(int dividend, int divisor)
{
    Debug.Assert(divisor != 0, $"{nameof(divisor)} is 0 and will cause an exception.");

    return dividend / divisor;
}

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

Примечание.

При использовании System.Diagnostics.Debug.Assert следите за тем, чтобы код в операторе Assert не изменял результаты программы в случае его удаления. В противном случае вы можете случайно допустить ошибку, которая проявится только в версии выпуска программы. Будьте особенно осторожны с операторами утверждения, которые содержат вызовы функций или процедур.

Использование и Trace из DebugSystem.Diagnostics пространства имен — отличный способ обеспечить дополнительный контекст при запуске и отладке приложения.