.Net Core下怎么使用Logger实现log写入本地文件系统

发布时间:2022-10-21 10:04:51 作者:iii
来源:亿速云 阅读:203

本文小编为大家详细介绍“.Net Core下怎么使用Logger实现log写入本地文件系统”,内容详细,步骤清晰,细节处理妥当,希望这篇“.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 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 <= 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 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 提高效率 队列写!!!
            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写入本地文件系统”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注亿速云行业资讯频道。

推荐阅读:
  1. .NET下log4net怎么用
  2. Linux下如何搭建.net core环境

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

net core logger

上一篇:.Net Core日志记录器如何实现

下一篇:.Net Core中如何自定义日志组件

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》