.Net Core Logger 实现log写入本地文件系统

简介: .net core 自带一个基础的logger框架Microsoft.Extensions.Logging。 微软默认实现了Microsoft.Extensions.Logging.Console.dll。

.net core 自带一个基础的logger框架Microsoft.Extensions.Logging。

微软默认实现了Microsoft.Extensions.Logging.Console.dll。控制台的日志输出和Microsoft.Extensions.Logging.Debug.dll调试输出。

下面我们写一个我们自己的本地文件输出模块demo,简单理解一下自带的这个logger系统。

logger框架主要几个类:LoggerFactory,Logger,LoggerProvider。

看名字就很好理解,都不需要解释。

实现我们自己的file logger只需要实现logger,loggerProvider即可。

第一步:入口。

loggerFactory.AddFile(this.Configuration.GetSection("FileLogging"));

为LoggerFactory扩张一个方法,提供增加日志写文件方式的入口。相关的配置来自appsettings.json

 1     public static class FileLoggerExtensions
 2     {
 3         //add 日志文件创建规则,分割规则,格式化规则,过滤规则 to appsettings.json
 4         public static ILoggerFactory AddFile(this ILoggerFactory factory, IConfiguration configuration)
 5         {
 6             return AddFile(factory, new FileLoggerSettings(configuration));
 7         }
 8         public static ILoggerFactory AddFile(this ILoggerFactory factory, FileLoggerSettings fileLoggerSettings)
 9         {
10             factory.AddProvider(new FileLoggerProvider(fileLoggerSettings));
11             return factory;
12         }
13     }
View Code

第二步:实现我们的logger提供程序,实现ILoggerProvider接口

public class FileLoggerProvider : ILoggerProvider, Idisposable

关键方法CreateLogger,创建真正写日志的logger。对当前的logger可以做适当的缓存,配置logger

  1     public class FileLoggerProvider : ILoggerProvider, IDisposable
  2     {
  3         FileLoggerSettings _configuration;
  4         readonly ConcurrentDictionary<string, InitLoggerModel> _loggerKeys = new ConcurrentDictionary<string, InitLoggerModel>();
  5         readonly ConcurrentDictionary<string, FileLogger> _loggers = new ConcurrentDictionary<string, FileLogger>();
  6 
  7         public FileLoggerProvider(FileLoggerSettings configuration)
  8         {
  9             _configuration = configuration;
 10             _configuration.ChangeToken.RegisterChangeCallback(p =>
 11             {
 12                 //appsettings.json changed. reload settings.
 13                 _configuration.Reload();
 14 
 15                 //update loggers settings form new settings
 16                 foreach (var item in this._loggers.Values)
 17                 {
 18                     InitLoggerModel model = new InitLoggerModel();
 19                     InitLoggerSettings(item.Name, model);
 20                     InitLogger(model, item);
 21                 }
 22 
 23             }, null);
 24         }
 25         public ILogger CreateLogger(string categoryName)
 26         {
 27             var loggerKey = this._loggerKeys.GetOrAdd(categoryName, p =>
 28              {
 29                  InitLoggerModel model = new InitLoggerModel();
 30                  InitLoggerSettings(categoryName, model);
 31                  return model;
 32              });
 33             var key = loggerKey.FileDiretoryPath + loggerKey.FileNameTemplate;
 34             return this._loggers.GetOrAdd(key, p =>
 35             {
 36                 var logger = new FileLogger(categoryName);
 37                 InitLogger(loggerKey, logger);
 38                 return logger;
 39             });
 40         }
 41 
 42         private static void InitLogger(InitLoggerModel model, FileLogger logger)
 43         {
 44             logger.FileNameTemplate = model.FileNameTemplate;
 45             logger.FileDiretoryPath = model.FileDiretoryPath;
 46             logger.MinLevel = model.MinLevel;
 47         }
 48 
 49         class InitLoggerModel
 50         {
 51             public LogLevel MinLevel { get; set; }
 52             public string FileDiretoryPath { get; set; }
 53             public string FileNameTemplate { get; set; }
 54 
 55             public override int GetHashCode()
 56             {
 57                 return this.MinLevel.GetHashCode() + this.FileDiretoryPath.GetHashCode() + this.FileNameTemplate.GetHashCode();
 58             }
 59             public override bool Equals(object obj)
 60             {
 61                 var b = obj as InitLoggerModel;
 62                 if (b == null)
 63                     return false;
 64                 return this.MinLevel == b.MinLevel && this.FileDiretoryPath == b.FileDiretoryPath && this.FileNameTemplate == b.FileNameTemplate;
 65             }
 66 
 67         }
 68         private void InitLoggerSettings(string categoryName, InitLoggerModel model)
 69         {
 70             model.MinLevel = LogLevel.Debug;
 71             var keys = this.GetKeys(categoryName);
 72             foreach (var item in keys)
 73             {
 74                 var switchV = _configuration.GetSwitch(item);
 75                 if (switchV.Item1)
 76                 {
 77                     model.MinLevel = switchV.Item2;
 78                     break;
 79                 }
 80             }
 81             model.FileDiretoryPath = this._configuration.DefaultPath;
 82             foreach (var item in keys)
 83             {
 84                 var switchV = _configuration.GetDiretoryPath(item);
 85                 if (switchV.Item1)
 86                 {
 87                     model.FileDiretoryPath = switchV.Item2;
 88                     break;
 89                 }
 90             }
 91             model.FileNameTemplate = this._configuration.DefaultFileName;
 92             foreach (var item in keys)
 93             {
 94                 var switchV = _configuration.GetFileName(item);
 95                 if (switchV.Item1)
 96                 {
 97                     model.FileNameTemplate = switchV.Item2;
 98                     break;
 99                 }
100             }
101         }
102 
103         IEnumerable<string> GetKeys(string categoryName)
104         {
105             while (!String.IsNullOrEmpty(categoryName))
106             {
107                 // a.b.c
108                 //--result
109                 // a.b.c,a.b,a,Default
110                 yield return categoryName;
111                 var last = categoryName.LastIndexOf('.');
112                 if (last <= 0)
113                 {
114                     yield return "Default";
115                     yield break;
116                 }
117                 System.Diagnostics.Debug.WriteLine(categoryName + "--" + last);
118                 categoryName = categoryName.Substring(0, last);
119             }
120             yield break;
121 
122         }
123         public void Dispose()
124         {
125         }
126     }
View Code

第三步:实现我们的logger,实现ILogger接口。真正将log写入file

public class FileLogger : Ilogger

  1     public class FileLogger : ILogger
  2     {
  3         static protected string delimiter = new string(new char[] { (char)1 });
  4         public FileLogger(string categoryName)
  5         {
  6             this.Name = categoryName;
  7         }
  8         class Disposable : IDisposable
  9         {
 10             public void Dispose()
 11             {
 12             }
 13         }
 14         Disposable _DisposableInstance = new Disposable();
 15         public IDisposable BeginScope<TState>(TState state)
 16         {
 17             return _DisposableInstance;
 18         }
 19         public bool IsEnabled(LogLevel logLevel)
 20         {
 21             return this.MinLevel <= logLevel;
 22         }
 23         public void Reload()
 24         {
 25             _Expires = true;
 26         }
 27 
 28         public string Name { get; private set; }
 29 
 30         public LogLevel MinLevel { get; set; }
 31         public string FileDiretoryPath { get; set; }
 32         public string FileNameTemplate { get; set; }
 33         public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
 34         {
 35             if (!this.IsEnabled(logLevel))
 36                 return;
 37             var msg = formatter(state, exception);
 38             this.Write(logLevel, eventId, msg, exception);
 39         }
 40         void Write(LogLevel logLevel, EventId eventId, string message, Exception ex)
 41         {
 42             EnsureInitFile();
 43 
 44             //TODO 提高效率 队列写!!!
 45             var log = String.Concat(DateTime.Now.ToString("HH:mm:ss"), '[', logLevel.ToString(), ']', '[',
 46                   Thread.CurrentThread.ManagedThreadId.ToString(), ',', eventId.Id.ToString(), ',', eventId.Name, ']',
 47                   delimiter, message, delimiter, ex?.ToString());
 48             lock (this)
 49             {
 50                 this._sw.WriteLine(log);
 51             }
 52         }
 53 
 54         bool _Expires = true;
 55         string _FileName;
 56         protected StreamWriter _sw;
 57         void EnsureInitFile()
 58         {
 59             if (CheckNeedCreateNewFile())
 60             {
 61                 lock (this)
 62                 {
 63                     if (CheckNeedCreateNewFile())
 64                     {
 65                         InitFile();
 66                         _Expires = false;
 67                     }
 68                 }
 69             }
 70         }
 71         bool CheckNeedCreateNewFile()
 72         {
 73             if (_Expires)
 74             {
 75                 return true;
 76             }
 77             //TODO 使用 RollingType判断是否需要创建文件。提高效率!!!
 78             if (_FileName != DateTime.Now.ToString(this.FileNameTemplate))
 79             {
 80                 return true;
 81             }
 82             return false;
 83         }
 84         void InitFile()
 85         {
 86             if (!Directory.Exists(this.FileDiretoryPath))
 87             {
 88                 Directory.CreateDirectory(this.FileDiretoryPath);
 89             }
 90             var path = "";
 91             int i = 0;
 92             do
 93             {
 94                 _FileName = DateTime.Now.ToString(this.FileNameTemplate);
 95                 path = Path.Combine(this.FileDiretoryPath, _FileName + "_" + i + ".log");
 96                 i++;
 97             } while (System.IO.File.Exists(path));
 98             var oldsw = _sw;
 99             _sw = new StreamWriter(new FileStream(path, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.Read), Encoding.UTF8);
100             _sw.AutoFlush = true;
101             if (oldsw != null)
102             {
103                 try
104                 {
105                     _sw.Flush();
106                     _sw.Dispose();
107                 }
108                 catch
109                 {
110                 }
111             }
112         }
113     }
View Code

代码:https://github.com/czd890/NetCoreWebApp

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
前端开发 JavaScript 关系型数据库
使用 OpenAuth.Net 快速搭建 .NET 企业级权限工作流系统
使用 OpenAuth.Net 快速搭建 .NET 企业级权限工作流系统
482 0
|
Java 微服务 Spring
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录——使用Logger在项目中打印日志
本文介绍了如何在项目中使用Logger打印日志。通过SLF4J和Logback,可设置不同日志级别(如DEBUG、INFO、WARN、ERROR)并支持占位符输出动态信息。示例代码展示了日志在控制器中的应用,说明了日志配置对问题排查的重要性。附课程源码下载链接供实践参考。
1596 0
|
开发框架 .NET C#
ASP.NET Core Blazor 路由配置和导航
大家好,我是码农刚子。本文系统介绍Blazor单页应用的路由机制,涵盖基础配置、路由参数、编程式导航及高级功能。通过@page指令定义路由,支持参数约束、可选参数与通配符捕获,结合NavigationManager实现页面跳转与参数传递,并演示用户管理、产品展示等典型场景,全面掌握Blazor路由从入门到实战的完整方案。
861 6
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
1015 5
|
存储 人工智能 JSON
RAG Logger:专为检索增强生成(RAG)应用设计的开源日志工具,支持查询跟踪、性能监控
RAG Logger 是一款专为检索增强生成(RAG)应用设计的开源日志工具,支持查询跟踪、检索结果记录、LLM 交互记录和性能监控等功能。
897 7
RAG Logger:专为检索增强生成(RAG)应用设计的开源日志工具,支持查询跟踪、性能监控
|
前端开发 C# 开发者
.NET使用Umbraco CMS快速构建一个属于自己的内容管理系统
.NET使用Umbraco CMS快速构建一个属于自己的内容管理系统
404 12
|
SQL 小程序 API
如何运用C#.NET技术快速开发一套掌上医院系统?
本方案基于C#.NET技术快速构建掌上医院系统,结合模块化开发理念与医院信息化需求。核心功能涵盖用户端的预约挂号、在线问诊、报告查询等,以及管理端的排班管理和数据统计。采用.NET Core Web API与uni-app实现前后端分离,支持跨平台小程序开发。数据库选用SQL Server 2012,并通过读写分离与索引优化提升性能。部署方案包括Windows Server与负载均衡设计,确保高可用性。同时针对API差异、数据库老化及高并发等问题制定应对措施,保障系统稳定运行。推荐使用Postman、Redgate等工具辅助开发,提升效率与质量。
783 0
|
Web App开发 前端开发 调度
一款基于 .NET + Blazor 开发的智能访客管理系统
一款基于 .NET + Blazor 开发的智能访客管理系统
350 8
|
开发框架 JavaScript 前端开发
精选2款.NET开源的博客系统
精选2款.NET开源的博客系统
502 8
|
前端开发 JavaScript C#
基于.NET8+Vue3开发的权限管理&个人博客系统
基于.NET8+Vue3开发的权限管理&个人博客系统
383 7