.NET 有几种不同的日志记录和跟踪工具,还有许多不同的第三方日志记录程序。尝试将一个应用程序从一种日志记录技术更改为另一种日志记录技术不是一件容易的事情,因为日志记录 API 的使用分布在整个源代码中。要使日志记录独立于任何日志记录技术,可以使用接口。
.NET Core 在NuGet 包 Microsoft.Extensions.Logging 中嵌入了泛型 ILogger接口。这个接口定义了 Log 方法。Log 方法定义了参数,来指定 LogLevel(枚举值)、事件ID(使用结构 EventId)、泛型状态信息、记录异常信息的 Exception类型,以及用字符串确定输出格式的格式化程序:
void Log<TState>(LogLevel logLevel, EventId eventide, TState state, Exception exception, Func<TState, Exception, string> formatter)
除了 Log 方法之外,ILogger 接口还定义了 IsEnabled 方法,以基于 LogLevel检查日志记录是否启用,该接口也定义了方法 BeginScope,为日志记录返回可释放的作用域。ILogger 接口中的成员实际上是日志记录所需的全部。Log 方法有许多需要填充的参数。为了简化日志记录,在 LoggerExtensions 类中定义了 ILogger 接口的扩展方法。扩展方法,例如LogDebug、LogTrace、LogInformation、LogWarning、LogError、LogCritical 和 BeginScope 都有几个重载版本和易于使用的参数。
下面利用依赖注入,并使用包含的类 SampleController 作为一个泛型参数,注入ILogger 接口。泛型参数定义了日志记录器的类别。在泛型参数中,类别是由类名组成的,包括名称空间:
class SampleController
{private readonly ILogger<SampleController> _logger;public SampleController(ILogger<SampleController> logger) {_logger = logger;}//...
}
日志示例是使用了以下依赖项和名称空间:
依赖项
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Logging
Microsoft.Extensions.Logging.Configuration
Microsoft.Extensions.Logging.Console
Microsoft.Extensions.Logging.Debug
Microsoft.Extensions.Logging.EventSource
Microsoft.Extensions.Logging.Filter
名称空间
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Logging
Microsoft.Extensions.Logging.Console
System
System.Net.Http
System.Threading.Tasks
ILogger 接口可以简单地用于调用扩展方法,如 LogInformation:
_logger.LogInformation("NetworkRequestSample started");
扩展方法提供重载版本,来传递额外的参数、异常信息和事件ID。为了使用事件ID,应用程序定义了一个常量值列表:
class LoggingEvents
{public const int Injection = 2000; public const int Networking = 2002;
}
接下来,使用LogInformation和LogError扩展方法显示NetworkRequestSampleAsync 方法的开头、结束时间以及抛出异常时的错误信息:
public async Task NetworkRequestSampleAsync(string url)
{try{_logger.LogInformation(LoggingEvents.Networking,"NetworkRequestSampleAsync started with url {0}", url); var client = new HttpClient();string result = await client.GetStringAsync(url); _logger.LogInformation(LoggingEvents.Networking,"NetworkRequestSampleAsync completed, received {0} characters", result.Length);}catch (Exception ex){logger.LogError(LoggingEvents.Networking, ex,"Error in NetworkRequestSampleAsync, error message: {0},HResult: {1}",ex.Message, ex.HResult);}
}
注意:
ILogger 扩展方法的一个重载版本需要给第一个参数使用 EventId。在示例代码中,传递一个 int。这是可能的,因为 EventId 结构实现了一个隐式运算符,来将 int 转换为 EventId。
将消息传递给 LogXX 方法时,可以提供任何数量的的对象,并将其放入格式消息字符串中。此格式字符串使用位置参数传入以下对象。不能使用可格式化的字符串 名因为格式字符串通常来自允许这些消息本地化的资源。
微信公众号
DotNet讲堂