ASP.NET Core имеет встроенную поддержку логгирования, что позволяет применять логгирование с минимальными вкраплениями кода в функционал приложения.
Для логгирования данных нам необходим объект ILogger<T>. По умолчанию среда ASP NET Core через механизм внедрения зависимостей уже предоставляет нам такой объект. Его можно получить как и любую другую зависимость в приложении. Также этот объект можно получить через свойство Logger объекта WebApplication.
Например, используем встроенный логгер для логгирования на консоль приложения:
var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.Run(async (context) => { // пишем на консоль информацию app.Logger.LogInformation($"Processing request {context.Request.Path}"); await context.Response.WriteAsync("Hello World!"); }); app.Run();
В данном случае через свойство app.Logger получаем встроенный логгер и с помощью его метода
logger.LogInformation
передаем на консоль некоторую информацию.
При обращении к приложению с помощью следующего запроса http://localhost:xxxxx/hello на консоль будет выведена информация, переданная логгером:
При создании логгера для него указывается категория. Обычно в качестве категории логгера выступает класс, в котором используется логгер. В этом случае логгер типизируется классом-категории. Например, логгер, для которого в качестве категории выступает класс Program:
ILogger<Program>
В чем смысл категории? Категория задает текстовую метку, с которой ассоциируется сообщение логгера, и в выводе лога мы ее можем увидеть.
Где это может быть полезно? Например, у нас есть несколько классов middleware, где ведется логгирование. Указывая в качестве категории текущий класс, в последствии в логе мы можем увидеть, в каком классе именно было создано данное сообщение лога. Поэтому, как правило, в качестве категории указывается текущий класс, но в принципе это необязательно.
Поскольку логгер добавляется в сервисы приложения, то мы можем получить его как и любой другой сервис через систему внедрения зависимостей. Например:
var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.Map("/hello", (ILogger<Program> logger) => { logger.LogInformation($"Path: /hello Time: {DateTime.Now.ToLongTimeString()}"); return "Hello World"; }); app.Run();
В данном случае при обращении по адресу "/hello" сработает конечная точка, в обработчике которой через механизм внедрения зависимостей можно получить объект логгера. Стоит учитывать, что в этом случае для логгера надо определить категорию. Здесь в качестве категории применяется класс Program (неявный класс, в котором и запускается приложение).
В самом обработчике логгер выводит на консоль путь запроса и время запроса:
При настройке логгирования мы можем установить уровень детализации информации с помощью одного из значений перечисления LogLevel. Всего мы можем использовать следующие значения:
Trace
: используется для вывода наиболее детализированных сообщений. Подобные сообщения могут нести важную информацию о
приложении и его строении, поэтому данный уровень лучше использовать при разработке, но никак не при публикации
Debug
: для вывода информации, которая может быть полезной в процессе разработки и отладки приложения
Information
: уровень сообщений, позволяющий просто отследить поток выполнения приложения
Warning
: используется для вывода сообщений о неожиданных событиях, например, ошибках, которые не останавливают выполнение приложения,
но в то же время должны быть иследованы
Error
: для вывода информации об ошибках и исключениях, которые возникли при текущей операции и которые не могут быть обработаны
Critical
: уровень критических ошибок, которые требуют немедленной реакции - ошибками операционной системы, потерей данных в бд,
переполнение памяти диска и т.д.
None
: вывод информации в лог не применяется
Для вывода соответствующего уровня информации у объекта ILogger
определены соответствующие методы расширения:
LogDebug()
LogTrace()
LogInformation()
LogWarning()
LogError()
LogCritical()
Так, в примере выше для вывода информации на консоль использовался метод LogInformation()
.
Вывод сообщений уровня Trace по умолчанию отключен.
Каждый такой метод имеет несколько перегрузок, которые могут принимать ряд различных параметров:
string data
: строковое сообщение для лога
int eventId
: числовой идентификатор, который связан с логом. Идентификатор должен быть статическим и специфическим для
определенной части логгируемых событий.
string format
: строковое сообщения для лога, которое может содержать параметры
object[] args
: набор параметров для строкового сообщения
Exception error
: логгируемый объект исключения
Также для логгирования определен общий метод Log(), который позволяет определить уровень логгера через один из параметров:
logger.Log(LogLevel.Information, $"Requested Path: {context.Request.Path}");
При стандартном логгировании на консоль для каждого уровня/метода определен своя метка и цветовой маркер, которые позволяют сразу выделить сообщение соответствующего уровня. Например, при запуске следующего кода:
var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.Run(async (context) => { var path = context.Request.Path; app.Logger.LogCritical($"LogCritical {path}"); app.Logger.LogError($"LogError {path}"); app.Logger.LogInformation($"LogInformation {path}"); app.Logger.LogWarning($"LogWarning {path}"); await context.Response.WriteAsync("Hello World!"); }); app.Run();
мы получим следующий лог на консоль: