.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

     public static class FileLoggerExtensions
{
//add 日志文件创建规则,分割规则,格式化规则,过滤规则 to appsettings.json
public static ILoggerFactory AddFile(this ILoggerFactory factory, IConfiguration configuration)
{
return AddFile(factory, new FileLoggerSettings(configuration));
}
public static ILoggerFactory AddFile(this ILoggerFactory factory, FileLoggerSettings fileLoggerSettings)
{
factory.AddProvider(new FileLoggerProvider(fileLoggerSettings));
return factory;
}
}

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

public class FileLoggerProvider : ILoggerProvider, Idisposable

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

     public class FileLoggerProvider : ILoggerProvider, IDisposable
{
FileLoggerSettings _configuration;
readonly ConcurrentDictionary<string, InitLoggerModel> _loggerKeys = new ConcurrentDictionary<string, InitLoggerModel>();
readonly ConcurrentDictionary<string, FileLogger> _loggers = new ConcurrentDictionary<string, FileLogger>(); public FileLoggerProvider(FileLoggerSettings configuration)
{
_configuration = configuration;
_configuration.ChangeToken.RegisterChangeCallback(p =>
{
//appsettings.json changed. reload settings.
_configuration.Reload(); //update loggers settings form new settings
foreach (var item in this._loggers.Values)
{
InitLoggerModel model = new InitLoggerModel();
InitLoggerSettings(item.Name, model);
InitLogger(model, item);
} }, null);
}
public ILogger CreateLogger(string categoryName)
{
var loggerKey = this._loggerKeys.GetOrAdd(categoryName, p =>
{
InitLoggerModel model = new InitLoggerModel();
InitLoggerSettings(categoryName, model);
return model;
});
var key = loggerKey.FileDiretoryPath + loggerKey.FileNameTemplate;
return this._loggers.GetOrAdd(key, p =>
{
var logger = new FileLogger(categoryName);
InitLogger(loggerKey, logger);
return logger;
});
} private static void InitLogger(InitLoggerModel model, FileLogger logger)
{
logger.FileNameTemplate = model.FileNameTemplate;
logger.FileDiretoryPath = model.FileDiretoryPath;
logger.MinLevel = model.MinLevel;
} class InitLoggerModel
{
public LogLevel MinLevel { get; set; }
public string FileDiretoryPath { get; set; }
public string FileNameTemplate { get; set; } public override int GetHashCode()
{
return this.MinLevel.GetHashCode() + this.FileDiretoryPath.GetHashCode() + this.FileNameTemplate.GetHashCode();
}
public override bool Equals(object obj)
{
var b = obj as InitLoggerModel;
if (b == null)
return false;
return this.MinLevel == b.MinLevel && this.FileDiretoryPath == b.FileDiretoryPath && this.FileNameTemplate == b.FileNameTemplate;
} }
private void InitLoggerSettings(string categoryName, InitLoggerModel model)
{
model.MinLevel = LogLevel.Debug;
var keys = this.GetKeys(categoryName);
foreach (var item in keys)
{
var switchV = _configuration.GetSwitch(item);
if (switchV.Item1)
{
model.MinLevel = switchV.Item2;
break;
}
}
model.FileDiretoryPath = this._configuration.DefaultPath;
foreach (var item in keys)
{
var switchV = _configuration.GetDiretoryPath(item);
if (switchV.Item1)
{
model.FileDiretoryPath = switchV.Item2;
break;
}
}
model.FileNameTemplate = this._configuration.DefaultFileName;
foreach (var item in keys)
{
var switchV = _configuration.GetFileName(item);
if (switchV.Item1)
{
model.FileNameTemplate = switchV.Item2;
break;
}
}
} IEnumerable<string> GetKeys(string categoryName)
{
while (!String.IsNullOrEmpty(categoryName))
{
// a.b.c
//--result
// a.b.c,a.b,a,Default
yield return categoryName;
var last = categoryName.LastIndexOf('.');
if (last <= )
{
yield return "Default";
yield break;
}
System.Diagnostics.Debug.WriteLine(categoryName + "--" + last);
categoryName = categoryName.Substring(, last);
}
yield break; }
public void Dispose()
{
}
}

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

public class FileLogger : Ilogger

     public class FileLogger : ILogger
{
static protected string delimiter = new string(new char[] { (char) });
public FileLogger(string categoryName)
{
this.Name = categoryName;
}
class Disposable : IDisposable
{
public void Dispose()
{
}
}
Disposable _DisposableInstance = new Disposable();
public IDisposable BeginScope<TState>(TState state)
{
return _DisposableInstance;
}
public bool IsEnabled(LogLevel logLevel)
{
return this.MinLevel <= logLevel;
}
public void Reload()
{
_Expires = true;
} public string Name { get; private set; } public LogLevel MinLevel { get; set; }
public string FileDiretoryPath { get; set; }
public string FileNameTemplate { get; set; }
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
if (!this.IsEnabled(logLevel))
return;
var msg = formatter(state, exception);
this.Write(logLevel, eventId, msg, exception);
}
void Write(LogLevel logLevel, EventId eventId, string message, Exception ex)
{
EnsureInitFile(); //TODO 提高效率 队列写!!!
var log = String.Concat(DateTime.Now.ToString("HH:mm:ss"), '[', logLevel.ToString(), ']', '[',
Thread.CurrentThread.ManagedThreadId.ToString(), ',', eventId.Id.ToString(), ',', eventId.Name, ']',
delimiter, message, delimiter, ex?.ToString());
lock (this)
{
this._sw.WriteLine(log);
}
} bool _Expires = true;
string _FileName;
protected StreamWriter _sw;
void EnsureInitFile()
{
if (CheckNeedCreateNewFile())
{
lock (this)
{
if (CheckNeedCreateNewFile())
{
InitFile();
_Expires = false;
}
}
}
}
bool CheckNeedCreateNewFile()
{
if (_Expires)
{
return true;
}
//TODO 使用 RollingType判断是否需要创建文件。提高效率!!!
if (_FileName != DateTime.Now.ToString(this.FileNameTemplate))
{
return true;
}
return false;
}
void InitFile()
{
if (!Directory.Exists(this.FileDiretoryPath))
{
Directory.CreateDirectory(this.FileDiretoryPath);
}
var path = "";
int i = ;
do
{
_FileName = DateTime.Now.ToString(this.FileNameTemplate);
path = Path.Combine(this.FileDiretoryPath, _FileName + "_" + i + ".log");
i++;
} while (System.IO.File.Exists(path));
var oldsw = _sw;
_sw = new StreamWriter(new FileStream(path, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.Read), Encoding.UTF8);
_sw.AutoFlush = true;
if (oldsw != null)
{
try
{
_sw.Flush();
_sw.Dispose();
}
catch
{
}
}
}
}

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

.Net Core Logger 实现log写入本地文件系统的更多相关文章

  1. HTML5之本地文件系统API - File System API

    HTML5之本地文件系统API - File System API 新的HTML5标准给我们带来了大量的新特性和惊喜,例如,画图的画布Canvas,多媒体的audio和video等等.除了上面我们提到 ...

  2. React Native之本地文件系统访问组件react-native-fs的介绍与使用

    React Native之本地文件系统访问组件react-native-fs的介绍与使用 一,需求分析 1,需要将图片保存到本地相册: 2,需要创建文件,并对其进行读写 删除操作. 二,简单介绍 re ...

  3. [开源类库/项目] android保存崩溃时的错误信息log至本地【源码+jar包+使用说...

    不知大家是否经常遇到这种情况:自己的项目有时会在没有连接到电脑时发生崩溃,好不容易发现的bug结果连接到电脑时又复现不出来了:又或者自己写的一个功能在开机启动时产生小bug导致崩溃,而刚启动的机器想让 ...

  4. OC 将NSString写入本地文件

    最近在公司偶尔遇到一些不经常复现的bug,为了调试,只好把关键值记录到本地文件中,在遇到问题时,调出本地文件查看一下就可以很方便的知道是不是代码逻辑的错误或者问题考虑不够周全了. 废话不多说,流程在代 ...

  5. 数据迁移_把RAC环境备份的数据,恢复到另一台单机Oracle本地文件系统下

    数据迁移_把RAC环境备份的数据,恢复到另一台单机Oracle本地文件系统下 作者:Eric 微信:loveoracle11g 1.创建pfile文件 # su - ora11g # cd $ORAC ...

  6. 【翻译自mos文章】将expdp的dmp文件从asm磁盘组里边放到本地文件系统里边

    将expdp的dmp文件从asm磁盘组里边放到本地文件系统里边 參考原文: How To Extract Datapump File From ASM Diskgroup To Local Files ...

  7. OSSFS将OSS bucket 挂载到本地文件系统及注意事项

    OSSFS将OSS bucket 挂载到本地文件系统及注意事项 下载ossfs安装包 wget http://docs-aliyun.cn-hangzhou.oss.aliyun-inc.com/as ...

  8. 解决从linux本地文件系统上传文件到HDFS时的权限问题

    当使用 hadoop fs -put localfile /user/xxx 时提示: put: Permission denied: user=root, access=WRITE, inode=& ...

  9. QTreeWidget实现动态加载本地文件系统

    QT之前没有接触过,之所以做这个也是被临时拉去GoldenFarm组去做渲染的客户端:还别说,虽说是第一次,做出来的这个东西倒是挺让我满意的.先说一下具体需求,然后再上图吧: 渲染时在选择场景文件时, ...

随机推荐

  1. Qt 拷贝文件目录

    bool copyDir(const QString &source, const QString &destination, bool override) { QDir direct ...

  2. C# 视频编辑

    VidCoder VidCoder是一个开源免费的DVD/蓝光视频抓取和转码软件.使用HandBrake做为编码引擎.比Handbrake拥有更友好的用户界面. 可裁剪.剪切.字幕编辑.转码等. 官网 ...

  3. angular-JS模仿Form表单提交

    直接上示例代码,有不懂的欢迎留言: $http({ url: "http://localhost:10086/yuanxin/Conference/ImportExcelDataForBus ...

  4. 学C#之设计模式系列笔记(1)策略模式

    一.借鉴说明 1.<Head First Design Patterns>(中文名<深入浅出设计模式>) 2.维基百科,策略模式,https://zh.wikipedia.or ...

  5. JAVA Thread线程异常监控

    一.场景描述:单线程程序可以用try...catch捕获程序的异常,而在多线程程序的时候是无法使用try...catch捕获. 示例1:多线程发生异常,无法使用try...catch捕获问题 publ ...

  6. 【工匠大道】Mac下Java开发环境配置简述

    本文地址 原文地址 分享提纲: 1. 下载JDK1.7 2. 配置java_home 3 .安装tomcat 4 .安装eclipse或者myeclipse 5.  mysql安装 破解版下载请参考M ...

  7. Web项目从Oracle转为Mysql,fluentnhibernate-1.0和NHibernate2.1.0升级到NHibernate3.3的注意事项

    1.Oracel数据库没有字段自增长属性,要实现自增长通常是通过查询序列或者触发器来实现的. 设置自增长主键 alter table SUB_SUBSCRIPTION add primary key( ...

  8. java类与实例

    最近在看设计模式,感觉自己对java的三大特性的理解不够清晰,搞不清楚抽象类.接口.泛型的用处和优缺点.设计模式学了一半,想着还是停下来脑补一下java的基础,就从java对象开始吧. 一.java对 ...

  9. 你必须知道的HTTP错误

    发送网络请求有时失败,分析一下响应行,在响应的响应行内,你会发现响应行由三部分组成,用空格来隔开,HTTP/1.1 404 NOT FOUND,第一个是响应的HTTP的版本,第二个和第三个是状态值. ...

  10. iOS多线程之7.NSOperation的初识

    NSOperation和GCD一样,不用我们管理线程的生命周期,加锁等问题,只要把操作封装进NSOperation中,系统会自动帮我们创建线程,执行操作.而且他是面向对象的,我们看起来更容易理解,使用 ...