博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.Net Core Logger 实现log写入本地文件系统
阅读量:7241 次
发布时间:2019-06-29

本文共 10312 字,大约阅读时间需要 34 分钟。

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

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

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

logger框架主要几个类:LoggerFactoryLoggerLoggerProvider

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

实现我们自己的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
_loggerKeys = new ConcurrentDictionary
(); 5 readonly ConcurrentDictionary
_loggers = new ConcurrentDictionary
(); 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
GetKeys(string categoryName)104 {105 while (!String.IsNullOrEmpty(categoryName))106 {107 // a.b.c108 //--result109 // a.b.c,a.b,a,Default110 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 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
(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func
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 try104 {105 _sw.Flush();106 _sw.Dispose();107 }108 catch109 {110 }111 }112 }113 }
View Code

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

转载地址:http://spfbm.baihongyu.com/

你可能感兴趣的文章
Axios库简单封装
查看>>
Oracle遇到的一些问题
查看>>
RabbitMQ入门-高效的Work模式
查看>>
以后要把flex用起来
查看>>
获取messagedialog用户点击的按钮
查看>>
ios中Pldatabase的用法(3)
查看>>
【BFS】POJ 3414
查看>>
团队作业——Beta冲刺3
查看>>
equal height
查看>>
一个appium 博客
查看>>
关于windows下安装mysql数据库出现中文乱码的问题
查看>>
有人认为,“中文编程”是解决中国程序员编程效率的秘密武器,请问它是一个“银弹”么?...
查看>>
053、overlay是如何隔离的?(2019-03-20周三)
查看>>
python+selenium常见问题解决方式
查看>>
看来人工智能不可阻挡,将和网络与计算机一样服务于各行各业!
查看>>
Python之路--------->Python-字符编码
查看>>
Sql学习内容
查看>>
微信公众号教程(2)微信公众平台后台介绍
查看>>
微信公众号教程(5)自动回复操作案例
查看>>
ACE服务端编程2:ACE跨平台之数据类型和宽字符
查看>>