C# 使用ILogger接口编写日志

2980f37ce4b2326fb386df1c0a4ae6b3.png

.NET 有几种不同的日志记录和跟踪工具,还有许多不同的第三方日志记录程序。尝试将一个应用程序从一种日志记录技术更改为另一种日志记录技术不是一件容易的事情,因为日志记录 API 的使用分布在整个源代码中。要使日志记录独立于任何日志记录技术,可以使用接口。

c3451c3c8768fe510f253c6743e8800f.png

.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)

085df95ee28f0d61731a66c0288af847.png

除了 Log 方法之外,ILogger 接口还定义了 IsEnabled 方法,以基于 LogLevel检查日志记录是否启用,该接口也定义了方法 BeginScope,为日志记录返回可释放的作用域。ILogger 接口中的成员实际上是日志记录所需的全部。Log 方法有许多需要填充的参数。为了简化日志记录,在 LoggerExtensions 类中定义了 ILogger 接口的扩展方法。扩展方法,例如LogDebug、LogTrace、LogInformation、LogWarning、LogError、LogCritical 和 BeginScope 都有几个重载版本和易于使用的参数。

3dcfe9389d818e1ab33c5a1d4b1b0821.png

下面利用依赖注入,并使用包含的类 SampleController 作为一个泛型参数,注入ILogger 接口。泛型参数定义了日志记录器的类别。在泛型参数中,类别是由类名组成的,包括名称空间:

class SampleController
{
  private readonly ILogger<SampleController> _logger;
  public SampleController(ILogger<SampleController> logger) 
  {
    _logger = logger;
  }
  //...
}

a5ddf17149399c682aae1b2037807773.png

日志示例是使用了以下依赖项和名称空间:

依赖项

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

774f45012ef51b7a69ac2047f8134da5.png

ILogger 接口可以简单地用于调用扩展方法,如 LogInformation:

_logger.LogInformation("NetworkRequestSample started");

69a09d89baddfeb3a4d3bf396a2cc11a.png

扩展方法提供重载版本,来传递额外的参数、异常信息和事件ID。为了使用事件ID,应用程序定义了一个常量值列表:

class LoggingEvents
{
  public const int Injection = 2000; 
  public const int Networking = 2002;
}

e42f5fd78ba7bf6c775191e40375a728.png

接下来,使用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);
   }
}

66fb101d329840149985017af3953199.png

注意:

ILogger 扩展方法的一个重载版本需要给第一个参数使用 EventId。在示例代码中,传递一个 int。这是可能的,因为 EventId 结构实现了一个隐式运算符,来将 int 转换为 EventId。

将消息传递给 LogXX 方法时,可以提供任何数量的的对象,并将其放入格式消息字符串中。此格式字符串使用位置参数传入以下对象。不能使用可格式化的字符串 名因为格式字符串通常来自允许这些消息本地化的资源。

42aaec13dfb8dae079bf027549070ca1.png

35a7f273b5ace119d37ee7985b647a4c.png

 微信公众号 

DotNet讲堂

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
接口C#中有广泛的使用场景,以下是一些常见的示例: 1. 定义插件系统:接口可以用于定义插件的规范,插件开发者只需实现接口中定义的方法,即可实现自己的功能,并与主程序进行交互。 2. 多态性和抽象:通过接口,可以实现多态性和抽象,使得代码更加灵活和可扩展。例如,定义一个形状的接口,然后让各种不同的形状类实现该接口,可以方便地对这些形状进行统一的处理。 3. 数据库操作:在数据库操作中,接口可以用于定义数据访问层的规范,不同的数据库操作类可以实现同一个接口,从而实现对不同数据库的统一操作。 以下是一个使用场景示例: ``` interface ILogger { void Log(string message); } class ConsoleLogger : ILogger { public void Log(string message) { Console.WriteLine(message); } } class FileLogger : ILogger { public void Log(string message) { // 将日志信息写入文件 } } class DatabaseService { private ILogger logger; public DatabaseService(ILogger logger) { this.logger = logger; } public void InsertData() { // 插入数据的逻辑 logger.Log("数据插入成功"); } } ``` 在上面的示例中,定义了一个 ILogger 接口,以及两个实现类 ConsoleLogger 和 FileLogger。DatabaseService 类依赖于 ILogger 接口,通过构造函数注入具体的日志记录器实例。在 InsertData 方法中,插入数据成功后会调用 ILogger 接口的 Log 方法,根据具体的实现类来记录日志。 通过接口使用,可以方便地替换不同的日志记录器,实现了解耦和可扩展性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值