您的位置:首页 > 教程 > 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