.NET 扩展 官方 Logger 实现将日志保存到本地文件

  • .NET 扩展 官方 Logger 实现将日志保存到本地文件已关闭评论
  • 184 次浏览
  • A+
所属分类:.NET技术
摘要

.NET 项目默认情况下 日志是使用的 ILogger 接口,默认提供一下四种日志记录程序:

.NET 项目默认情况下 日志是使用的 ILogger 接口,默认提供一下四种日志记录程序:

  • 控制台
  • 调试
  • EventSource
  • EventLog

这四种记录程序都是默认包含在 .NET 运行时库中。关于这四种记录程序的详细介绍可以直接查看微软的官方文档 https://docs.microsoft.com/zh-cn/dotnet/core/extensions/logging-providers

今天给大家分享自己实现一个日志记录程序,继承自  ILogger 接口,实现将日志记录到本地的 txt 文件中,并包含一个自动清理过期日志的功能任务。

类库的整体代码结构如下:

.NET 扩展 官方 Logger 实现将日志保存到本地文件

 

 Models 文件夹中存放 LoggerSetting.cs 是 该模块注入服务时需要的配置参数

namespace Logger.LocalFile.Models {     public class LoggerSetting     {         /// <summary>         /// 保存天数         /// </summary>         public int SaveDays { get; set; } = 7;     } }

 

Tasks 文件夹中存放的 LogClearTask.cs 是用于自动清理过期日志的任务,会在日志服务注入的同时启动,会通过配置的保存天数参数,定期删除超过实现的日志文件

using Common; using Logger.LocalFile.Models; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options;  namespace Logger.LocalFile.Tasks {     public class LogClearTask : BackgroundService     {          private readonly int saveDays;           public LogClearTask(IOptionsMonitor<LoggerSetting> config)         {             saveDays = config.CurrentValue.SaveDays;         }          protected override async Task ExecuteAsync(CancellationToken stoppingToken)         {             while (!stoppingToken.IsCancellationRequested)             {                 try                 {                      string basePath = Directory.GetCurrentDirectory().Replace("\", "/") + "/Logs/";                      if (Directory.Exists(basePath))                     {                         List<string> logPaths = IOHelper.GetFolderAllFiles(basePath).ToList();                          var deleteTime = DateTime.UtcNow.AddDays(-1 * saveDays);                          if (logPaths.Count != 0)                         {                             foreach (var logPath in logPaths)                             {                                 var fileInfo = new FileInfo(logPath);                                  if (fileInfo.CreationTimeUtc < deleteTime)                                 {                                     File.Delete(logPath);                                 }                              }                         }                     }                  }                 catch                 {                 }                  await Task.Delay(1000 * 60 * 60 * 24, stoppingToken);             }         }      } }

 

ILoggingBuilderExtensions 是应用注入服务的扩展方法,内容如下

using Logger.LocalFile.Models; using Logger.LocalFile.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging;  namespace Logger.LocalFile {      public static class ILoggingBuilderExtensions     {          public static void AddLocalFileLogger(this ILoggingBuilder builder, Action<LoggerSetting> action)         {             builder.Services.Configure(action);             builder.Services.AddSingleton<ILoggerProvider, LocalFileLoggerProvider>();             builder.Services.AddSingleton<IHostedService, LogClearTask>();         }     } }

 

LocalFileLogger 是日志的保存执行方法,内容如下

using Common; using Microsoft.Extensions.Logging; using System.Text;  namespace Logger.LocalFile {     public class LocalFileLogger : ILogger     {         private readonly string categoryName;         private readonly string basePath;          public LocalFileLogger(string categoryName)         {             this.categoryName = categoryName;              basePath = Directory.GetCurrentDirectory().Replace("\", "/") + "/Logs/";              if (Directory.Exists(basePath) == false)             {                 Directory.CreateDirectory(basePath);             }         }          public IDisposable BeginScope<TState>(TState state)         {             return default!;         }          public bool IsEnabled(LogLevel logLevel)         {             if (logLevel != LogLevel.None)             {                 return true;             }             else             {                 return false;             }         }          public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)         {             if (IsEnabled(logLevel))             {                 if (state != null && state.ToString() != null)                 {                     var logContent = state.ToString();                      if (logContent != null)                     {                         if (exception != null)                         {                             var logMsg = new                             {                                 message = logContent,                                 error = new                                 {                                     exception?.Source,                                     exception?.Message,                                     exception?.StackTrace                                 }                             };                              logContent = JsonHelper.ObjectToJson(logMsg);                         }                          var log = new                         {                             CreateTime = DateTime.UtcNow,                             Category = categoryName,                             Level = logLevel.ToString(),                             Content = logContent                         };                          string logStr = JsonHelper.ObjectToJson(log);                          var logPath = basePath + DateTime.UtcNow.ToString("yyyyMMddHH") + ".log";                          File.AppendAllText(logPath, logStr + Environment.NewLine, Encoding.UTF8);                      }                 }             }         }     } }

 

LocalFileLoggerProvider 是Logger执行方法向外部的供应者,内容如下:

using Microsoft.Extensions.Logging; using System.Collections.Concurrent;  namespace Logger.LocalFile {     public class LocalFileLoggerProvider : ILoggerProvider     {         private readonly ConcurrentDictionary<string, LocalFileLogger> loggers = new();          public ILogger CreateLogger(string categoryName)         {             return loggers.GetOrAdd(categoryName, new LocalFileLogger(categoryName));         }          public void Dispose()         {             loggers.Clear();             GC.SuppressFinalize(this);         }     } }

 

当我们其他项目想要使用我们这个 Logger.LocalFile 类库时,只要添加该类库的引用,然后在启动服务时进行注入即可,注入方法如下:

Web 项目注入方式

//注册本地文件日志服务 builder.Logging.AddLocalFileLogger(options => { options.SaveDays = 7; });

 

控制台项目注入方式

.ConfigureLogging((hostContext, builder) =>                 {                     //注册本地文件日志服务                     builder.AddLocalFileLogger(options => { options.SaveDays = 7; });                 })                 .Build();

 

Web 项目直接在 builder 后面编写注入就可以,控制台项目需要先 .ConfigureLogging 才可以,这是两者的区别。

这样就注入了我们自己编写的日志记录程序,项目运行时会在项目的 Logs 文件夹中产生日志文件,如下图

.NET 扩展 官方 Logger 实现将日志保存到本地文件

 

 .NET 扩展 官方 Logger 实现将日志保存到本地文件

  

至此 .NET 扩展 官方 Logger 实现将日志保存到本地文件就讲解完了,有任何不明白的,可以在文章下面评论或者私信我,欢迎大家积极的讨论交流,有兴趣的朋友可以关注我目前在维护的一个 .net 基础框架项目,项目地址如下