.Net?Core使用Logger實(shí)現(xiàn)log寫(xiě)入本地文件系統(tǒng)
.net core 自帶一個(gè)基礎(chǔ)的logger框架Microsoft.Extensions.Logging。
微軟默認(rèn)實(shí)現(xiàn)了Microsoft.Extensions.Logging.Console.dll??刂婆_(tái)的日志輸出和Microsoft.Extensions.Logging.Debug.dll調(diào)試輸出。
下面我們寫(xiě)一個(gè)我們自己的本地文件輸出模塊demo,簡(jiǎn)單理解一下自帶的這個(gè)logger系統(tǒng)。
logger框架主要幾個(gè)類(lèi):LoggerFactory,Logger,LoggerProvider。
看名字就很好理解,都不需要解釋。
實(shí)現(xiàn)我們自己的file logger只需要實(shí)現(xiàn)logger,loggerProvider即可。
第一步:入口。
loggerFactory.AddFile(this.Configuration.GetSection("FileLogging"));
為L(zhǎng)oggerFactory擴(kuò)張一個(gè)方法,提供增加日志寫(xiě)文件方式的入口。相關(guān)的配置來(lái)自appsettings.json
public static class FileLoggerExtensions
{
//add 日志文件創(chuàng)建規(guī)則,分割規(guī)則,格式化規(guī)則,過(guò)濾規(guī)則 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;
}
}第二步:實(shí)現(xiàn)我們的logger提供程序,實(shí)現(xiàn)ILoggerProvider接口
public class FileLoggerProvider : ILoggerProvider, Idisposable
關(guān)鍵方法CreateLogger,創(chuàng)建真正寫(xiě)日志的logger。對(duì)當(dāng)前的logger可以做適當(dāng)?shù)木彺?,配置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 <= 0)
{
yield return "Default";
yield break;
}
System.Diagnostics.Debug.WriteLine(categoryName + "--" + last);
categoryName = categoryName.Substring(0, last);
}
yield break;
}
public void Dispose()
{
}
}第三步:實(shí)現(xiàn)我們的logger,實(shí)現(xiàn)ILogger接口。真正將log寫(xiě)入file
public class FileLogger : Ilogger
public class FileLogger : ILogger
{
static protected string delimiter = new string(new char[] { (char)1 });
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 提高效率 隊(duì)列寫(xiě)!??!
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判斷是否需要?jiǎng)?chuàng)建文件。提高效率?。?!
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 = 0;
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
{
}
}
}
}到此這篇關(guān)于.Net Core使用Logger實(shí)現(xiàn)log寫(xiě)入本地文件系統(tǒng)的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- ASP.NET?Core使用自定義日志中間件
- ASP.NET?Core記錄日志
- ASP.Net?Core中的日志與分布式鏈路追蹤
- ASP.NET Core使用NLog記錄日志
- ASP.NET Core使用Log4net實(shí)現(xiàn)日志記錄功能
- ASP.NET Core使用NLog輸出日志記錄
- .Net Core 使用NLog記錄日志到文件和數(shù)據(jù)庫(kù)的操作方法
- .net core日志系統(tǒng)相關(guān)總結(jié)
- .net core日志結(jié)構(gòu)化
- .NET Core3.0 日志 logging的實(shí)現(xiàn)
- .NET Core下使用Log4Net記錄日志的方法步驟
- Asp.Net Core用NLog記錄日志操作方法
相關(guān)文章
三種方法讓Response.Redirect在新窗口打開(kāi)
通過(guò)設(shè)置form的target屬性同樣可以讓Response.Rederect所指向的url在新的窗口打開(kāi),下面為大家介紹三種具體的實(shí)現(xiàn)方法2013-10-10
ASP.NET下對(duì)cookies的操作實(shí)現(xiàn)代碼
ASP.NET下對(duì)cookies的操作實(shí)現(xiàn)代碼,需要的朋友可以參考下。2011-10-10
Asp.net簡(jiǎn)單實(shí)現(xiàn)給圖片增加文字水印
這篇文章主要介紹了Asp.net簡(jiǎn)單實(shí)現(xiàn)給圖片增加文字水印,需要的朋友可以參考下2014-12-12
.Net Core實(shí)現(xiàn)選擇數(shù)據(jù)熱更新讓服務(wù)感知配置的變化
這篇文章主要介紹了.Net Core實(shí)現(xiàn)選擇數(shù)據(jù)熱更新讓服務(wù)感知配置的變化,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
ASP.NET Core擴(kuò)展庫(kù)之實(shí)體映射使用詳解
這篇文章主要介紹了ASP.NET Core擴(kuò)展庫(kù)之實(shí)體映射使用詳解,幫助大家更好的理解和學(xué)習(xí)使用.net技術(shù),感興趣的朋友可以了解下2021-03-03
DataList 中動(dòng)態(tài)綁定服務(wù)器子控件的代碼
DataList 中動(dòng)態(tài)綁定服務(wù)器子控件的代碼...2007-09-09
Asp.Net各種超時(shí)問(wèn)題總結(jié)
在數(shù)據(jù)庫(kù)或者請(qǐng)求操作時(shí),如果選擇的時(shí)間段過(guò)短或操作數(shù)據(jù)量過(guò)大,就會(huì)遇到"請(qǐng)求超時(shí)"的的問(wèn)題,網(wǎng)絡(luò)上提供很多解決方案,但普遍不完善,根據(jù)個(gè)人經(jīng)驗(yàn)及參考網(wǎng)絡(luò)解決方案,先將其匯總2013-02-02
關(guān)于dotnet?替換?ASP.NET?Core?的底層通訊為命名管道的?IPC?庫(kù)的問(wèn)題
這篇文章主要介紹了dotnet?替換?ASP.NET?Core?的底層通訊為命名管道的?IPC?庫(kù),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02
Asp.net SignalR應(yīng)用并實(shí)現(xiàn)群聊功能
這篇文章主要為大家分享了Asp.net SignalR應(yīng)用并實(shí)現(xiàn)群聊功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04

