Ведение журнала и трассировка в приложениях .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
из Debug
System.Diagnostics
пространства имен — отличный способ обеспечить дополнительный контекст при запуске и отладке приложения.