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

打印 上一主题 下一主题

主题 917|帖子 917|积分 2751

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

  • 控制台
  • 调试
  • EventSource
  • EventLog
这四种记录程序都是默认包含在 .NET 运行时库中。关于这四种记录程序的详细介绍可以直接查看微软的官方文档 https://docs.microsoft.com/zh-cn/dotnet/core/extensions/logging-providers
今天给大家分享自己实现一个日志记录程序,继承自  ILogger 接口,实现将日志记录到本地的 txt 文件中,并包含一个自动清理过期日志的功能任务。
类库的整体代码结构如下:

 
 Models 文件夹中存放 LoggerSetting.cs 是 该模块注入服务时需要的配置参数
  1. namespace Logger.LocalFile.Models
  2. {
  3.     public class LoggerSetting
  4.     {
  5.         /// <summary>
  6.         /// 保存天数
  7.         /// </summary>
  8.         public int SaveDays { get; set; } = 7;
  9.     }
  10. }
复制代码
 
Tasks 文件夹中存放的 LogClearTask.cs 是用于自动清理过期日志的任务,会在日志服务注入的同时启动,会通过配置的保存天数参数,定期删除超过实现的日志文件
  1. using Common;
  2. using Logger.LocalFile.Models;
  3. using Microsoft.Extensions.Hosting;
  4. using Microsoft.Extensions.Options;
  5. namespace Logger.LocalFile.Tasks
  6. {
  7.     public class LogClearTask : BackgroundService
  8.     {
  9.         private readonly int saveDays;
  10.         public LogClearTask(IOptionsMonitor<LoggerSetting> config)
  11.         {
  12.             saveDays = config.CurrentValue.SaveDays;
  13.         }
  14.         protected override async Task ExecuteAsync(CancellationToken stoppingToken)
  15.         {
  16.             while (!stoppingToken.IsCancellationRequested)
  17.             {
  18.                 try
  19.                 {
  20.                     string basePath = Directory.GetCurrentDirectory().Replace("\", "/") + "/Logs/";
  21.                     if (Directory.Exists(basePath))
  22.                     {
  23.                         List<string> logPaths = IOHelper.GetFolderAllFiles(basePath).ToList();
  24.                         var deleteTime = DateTime.UtcNow.AddDays(-1 * saveDays);
  25.                         if (logPaths.Count != 0)
  26.                         {
  27.                             foreach (var logPath in logPaths)
  28.                             {
  29.                                 var fileInfo = new FileInfo(logPath);
  30.                                 if (fileInfo.CreationTimeUtc < deleteTime)
  31.                                 {
  32.                                     File.Delete(logPath);
  33.                                 }
  34.                             }
  35.                         }
  36.                     }
  37.                 }
  38.                 catch
  39.                 {
  40.                 }
  41.                 await Task.Delay(1000 * 60 * 60 * 24, stoppingToken);
  42.             }
  43.         }
  44.     }
  45. }
复制代码
 
ILoggingBuilderExtensions 是应用注入服务的扩展方法,内容如下
  1. using Logger.LocalFile.Models;
  2. using Logger.LocalFile.Tasks;
  3. using Microsoft.Extensions.DependencyInjection;
  4. using Microsoft.Extensions.Hosting;
  5. using Microsoft.Extensions.Logging;
  6. namespace Logger.LocalFile
  7. {
  8.     public static class ILoggingBuilderExtensions
  9.     {
  10.         public static void AddLocalFileLogger(this ILoggingBuilder builder, Action<LoggerSetting> action)
  11.         {
  12.             builder.Services.Configure(action);
  13.             builder.Services.AddSingleton<ILoggerProvider, LocalFileLoggerProvider>();
  14.             builder.Services.AddSingleton<IHostedService, LogClearTask>();
  15.         }
  16.     }
  17. }
复制代码
 
LocalFileLogger 是日志的保存执行方法,内容如下
  1. using Common;
  2. using Microsoft.Extensions.Logging;
  3. using System.Text;
  4. namespace Logger.LocalFile
  5. {
  6.     public class LocalFileLogger : ILogger
  7.     {
  8.         private readonly string categoryName;
  9.         private readonly string basePath;
  10.         public LocalFileLogger(string categoryName)
  11.         {
  12.             this.categoryName = categoryName;
  13.             basePath = Directory.GetCurrentDirectory().Replace("\", "/") + "/Logs/";
  14.             if (Directory.Exists(basePath) == false)
  15.             {
  16.                 Directory.CreateDirectory(basePath);
  17.             }
  18.         }
  19.         public IDisposable BeginScope<TState>(TState state)
  20.         {
  21.             return default!;
  22.         }
  23.         public bool IsEnabled(LogLevel logLevel)
  24.         {
  25.             if (logLevel != LogLevel.None)
  26.             {
  27.                 return true;
  28.             }
  29.             else
  30.             {
  31.                 return false;
  32.             }
  33.         }
  34.         public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
  35.         {
  36.             if (IsEnabled(logLevel))
  37.             {
  38.                 if (state != null && state.ToString() != null)
  39.                 {
  40.                     var logContent = state.ToString();
  41.                     if (logContent != null)
  42.                     {
  43.                         if (exception != null)
  44.                         {
  45.                             var logMsg = new
  46.                             {
  47.                                 message = logContent,
  48.                                 error = new
  49.                                 {
  50.                                     exception?.Source,
  51.                                     exception?.Message,
  52.                                     exception?.StackTrace
  53.                                 }
  54.                             };
  55.                             logContent = JsonHelper.ObjectToJson(logMsg);
  56.                         }
  57.                         var log = new
  58.                         {
  59.                             CreateTime = DateTime.UtcNow,
  60.                             Category = categoryName,
  61.                             Level = logLevel.ToString(),
  62.                             Content = logContent
  63.                         };
  64.                         string logStr = JsonHelper.ObjectToJson(log);
  65.                         var logPath = basePath + DateTime.UtcNow.ToString("yyyyMMddHH") + ".log";
  66.                         File.AppendAllText(logPath, logStr + Environment.NewLine, Encoding.UTF8);
  67.                     }
  68.                 }
  69.             }
  70.         }
  71.     }
  72. }
复制代码
 
LocalFileLoggerProvider 是Logger执行方法向外部的供应者,内容如下:
  1. using Microsoft.Extensions.Logging;
  2. using System.Collections.Concurrent;
  3. namespace Logger.LocalFile
  4. {
  5.     public class LocalFileLoggerProvider : ILoggerProvider
  6.     {
  7.         private readonly ConcurrentDictionary<string, LocalFileLogger> loggers = new();
  8.         public ILogger CreateLogger(string categoryName)
  9.         {
  10.             return loggers.GetOrAdd(categoryName, new LocalFileLogger(categoryName));
  11.         }
  12.         public void Dispose()
  13.         {
  14.             loggers.Clear();
  15.             GC.SuppressFinalize(this);
  16.         }
  17.     }
  18. }
复制代码
 
当我们其他项目想要使用我们这个 Logger.LocalFile 类库时,只要添加该类库的引用,然后在启动服务时进行注入即可,注入方法如下:
Web 项目注入方式
  1. //注册本地文件日志服务
  2. builder.Logging.AddLocalFileLogger(options => { options.SaveDays = 7; });
复制代码
 
控制台项目注入方式
  1. .ConfigureLogging((hostContext, builder) =>
  2.                 {
  3.                     //注册本地文件日志服务
  4.                     builder.AddLocalFileLogger(options => { options.SaveDays = 7; });
  5.                 })
  6.                 .Build();
复制代码
 
Web 项目直接在 builder 后面编写注入就可以,控制台项目需要先 .ConfigureLogging 才可以,这是两者的区别。
这样就注入了我们自己编写的日志记录程序,项目运行时会在项目的 Logs 文件夹中产生日志文件,如下图

 
 
  
至此 .NET 扩展 官方 Logger 实现将日志保存到本地文件就讲解完了,有任何不明白的,可以在文章下面评论或者私信我,欢迎大家积极的讨论交流,有兴趣的朋友可以关注我目前在维护的一个 .net 基础框架项目,项目地址如下https://github.com/berkerdong/NetEngine.githttps://gitee.com/berkerdong/NetEngine.git
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

科技颠覆者

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表