您的位置:首頁 > 教程 > ASP.NET > .Net?Core使用Logger實現log寫入本地文件系統

.Net?Core使用Logger實現log寫入本地文件系統

2022-06-15 18:50:37 來源:易采站長站 作者:

.Net?Core使用Logger實現log寫入本地文件系統

.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>

關鍵方法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 <= 0)
                {
                    yield return "Default";
                    yield break;
                }
                System.Diagnostics.Debug.WriteLine(categoryName + "--" + last);
                categoryName = categoryName.Substring(0, last);
            }
            yield break;

        }
        public void Dispose()
        {
        }
    }

第三步:實現我們的logger,實現ILogger接口。真正將log寫入file

public>

    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 提高效率 隊列寫?。?!
            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 = 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
                {
                }
            }
        }
    }

到此這篇關于.Net Core使用Logger實現log寫入本地文件系統的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支持易采站長站。

如有侵權,請聯系QQ:279390809 電話:15144810328

相關文章

  • [Asp.Net Core] 淺談Blazor Server Side

    [Asp.Net Core] 淺談Blazor Server Side

    在2016年, 本人就開始了一個內部項目, 其特點就是用C#構建DOM樹, 然后把DOM同步到瀏覽器中顯示. 并且在一些小工程中使用. 3年下來, 效果很不錯, 但因為是使用C#來構建控件樹, 在沒有特定
    2020-07-01
  • asp.net生成Excel并導出下載五種實現方法

    asp.net生成Excel并導出下載五種實現方法

    方法一 通過GridView(簡評:方法比較簡單,但是只適合生成格式簡單的Excel,且無法保留VBA代碼),頁面無刷新 aspx.cs部分 代碼如下: using System; using System.Collections; using System.Configuration; usi
    2019-05-16
  • Asp.Net Core用NLog記錄日志操作方法

    Asp.Net Core用NLog記錄日志操作方法

    需求 1.日志自動寫入到數據庫、寫入到文件 2.appsettings.json數據庫連接更改后,不需要去改NLog中的連接地址,啟動網站或項目時自動檢測變動然后去更改,以appsettings.json為準,保持同步
    2019-11-19
  • 使用vs2019加.net core 對WeiApi的創建過程詳解

    使用vs2019加.net core 對WeiApi的創建過程詳解

    vs2019創建webapi 1.創建新的項目 2.選擇.NET CORE的ASP .NET CORE WEB應用程序 3.定義項目名稱和存放地點 4.選擇API創建項目 5.刪除原本的無用的類 6.添加新的方法類 7.設置路由 using Microsoft.AspNe
    2020-07-03
  • 教你Asp.net下使用mysql數據庫的步驟

    教你Asp.net下使用mysql數據庫的步驟

    1. 首先需要安裝mysql, 易采站長站下載地址: //www.jb51.net/softs/2193.html 或者去mysql.com官網都可以,一路next,安裝好后,有個簡單配置,提示有個設置登錄密碼和服務名稱, 默認localhost,用
    2019-05-16
  • [Asp.Net Core]用Blazor Server Side實現圖片驗證碼

    [Asp.Net Core]用Blazor Server Side實現圖片驗證碼

    關于Blazor 由于在國內, Blazor一點都不普及, 在閱讀此文前, 建議讀者先翻看我之前寫的隨筆, 了解Blazor Server Side的特點. 在一段時間內, 我會寫一些解說分析型的 "為什么選擇 Blazor Server
    2020-07-01
  • 詳解ASP.NET Razor 語法

    詳解ASP.NET Razor 語法

    Razor 同時支持 C# (C sharp) 和 VB (Visual Basic)。 主要的 Razor C# 語法規則 Razor 代碼塊包含在 @{ ... } 中 內聯表達式(變量和函數)以 @ 開頭 代碼語句用分號結束 變量使用 var 關鍵字聲明 字符
    2020-07-07
  • .Net Core中使用ExceptionFilter過濾器的方法

    .Net Core中使用ExceptionFilter過濾器的方法

    .Net Core中有各種Filter,分別是AuthorizationFilter、ResourceFilter、ExceptionFilter、ActionFilter、ResultFilter??梢园阉麄兛醋魇?Net Core自帶的AOP的擴展封裝。 今天來看其中的一種:ExceptionFilter(用于
    2020-03-03
色七七影院_香港三级台湾三级在线播放_男人放进女人阳道猛进猛出