Log4net库的使用

Log4net库是.Net下一个开源日志记录组件。网络上大部分讲述这个库都是介绍怎么配置log4Net.config配置文件。这么做最大的缺点就是配置太繁琐。有很多功能是用户不了解的,因为毕竟做工程嘛,是给别人用的。用户觉得需要什么配置信息,我们给暴露什么就好了。把整个配置文件都暴露给用户,显然用户也会一脸懵逼。这都什么玩意。所以结合自身的需求以及用户体验感来考虑,设计了一个封装Log4net的一个库。

Log4net在配置中有一点不懂的是,如果我想每天生成一个新的文件(前提是我的程序一直在输出log,不退出,不重启),直接在配置文件中配置就可以了吗?每天生成新文件是Log4net已经内部做好了,还是在程序开始加载配置文件的时候才会检查呢?我尝试更改系统的日期,发现没有生成新的文件。我理解是Log4net提供了每个文件最大size,因此这种做法也是新建文件了。不知是我测试的不对,还是理解的不对,如果有人知道,欢迎评论区留言交流。因此采用了21世纪最笨的方法,自己搞。

官网地址:https://logging.apache.org/log4net/

源代码:https://github.com/apache/logging-log4net/

我的需求是:

1、将尽量少的配置放在配置文件中,供用户选择。(存放路径,记录天数,日志等级)

2、我需要每天生成一个log。

明确了需求后,我们得到了一个配置文件如下:>

XML 复制代码
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
    <!--日志等级-->
    <LogLevel>0</LogLevel>
    <!--日志目录-->
    <LogFilePath>D:\Log\</LogFilePath>
    <!--日志存在天数-->
    <LogFileExistDay>10</LogFileExistDay>
</appSettings>

有了配置文件,我们需要一个类存放配置参数

cs 复制代码
public class Parameter
    {
        /// <summary>
        /// 日志等级
        /// </summary>
        public enum LogLevelEnum
        {
            Debug = 0,
            Info = 1,
            Warn = 2,
            Error = 3,
            Fatal = 4
        }

        /// <summary>
        /// 当前保存日志等级
        /// </summary>
        public LogLevelEnum LogLevel;

        /// <summary>
        /// 日志存放路径
        /// </summary>
        public string LogFilePath;

        /// <summary>
        /// 日志存放天数
        /// </summary>
        public int LogFileExistDay;
    }

提供一个类解析这个配置文件:

cs 复制代码
class LogHelper
    {
        public static Parameter ReadXml()
        {
            Parameter parameter = new Parameter();
            try
            {
                XmlDocument doc = new XmlDocument();
                string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.xml");
                doc.Load(path);
                var node = doc.SelectSingleNode("appSettings");
                parameter.LogLevel = (Parameter.LogLevelEnum)Enum.Parse(typeof(Parameter.LogLevelEnum), node.SelectSingleNode("LogLevel").InnerText);
                parameter.LogFilePath = node.SelectSingleNode("LogFilePath").InnerText;
                parameter.LogFileExistDay = int.Parse(node.SelectSingleNode("LogFileExistDay").InnerText);
            }
            catch (Exception ex)
            {
                CommonLogger.Info(ex.ToString());
            }
            return parameter;
        }
    }

然后我们就能写封装Log4Net的类了,类叫做CommonLog。使用此类需要先调用初始化函数;读取用户的配置信息;然后初始化log;检查log存放的天数(删除超过天数的log);启动线程(每天生成一个新的log)。

初始化函数:

cs 复制代码
public static void Init()
        {
            //读取XML配置信息
            parameter = LogHelper.ReadXml();
            //初始化日志
            InitLog();
            //日志清除
            DeleteLog();
            Thread thread = new Thread(MonitorDay);
            thread.Start();
        }

初始化log,这里将配置文件的信息放在程序中。其中LockingModel 需要配置,否则会出现问题。具体参考:https://blog.csdn.net/dragon_ton/article/details/77840138

cs 复制代码
public static void InitLog()
        {
            // 命令行日志格式
            var patternLayout = new PatternLayout
            {
                ConversionPattern = "%date %-5level %message%newline"
            };
            patternLayout.ActivateOptions();

            // 文档日志
            var roller = new RollingFileAppender
            {
                StaticLogFileName = false,
                File = parameter.LogFilePath,
                AppendToFile = true,
                RollingStyle = RollingFileAppender.RollingMode.Date,
                MaxSizeRollBackups = parameter.LogFileExistDay,
                DatePattern = "yyyy-MM-dd'.log'",
                MaximumFileSize = "10KB",
                //下面这句话必须要有,如果没有,会出现生成多个log的情况
                LockingModel = new FileAppender.MinimalLock(),
                Layout = patternLayout
            };
            roller.ActivateOptions();

            // 命令行日志
            //var consoleAppender = new ConsoleAppender
            //{
            //    Name = "console",
            //    Layout = patternLayout
            //};
            //consoleAppender.ActivateOptions();

            Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
            hierarchy.Root.Level = Level.All;
            hierarchy.Root.AddAppender(roller);
            //hierarchy.Root.AddAppender(consoleAppender);
            hierarchy.Configured = true;
        }

Delete log,检查日志日期,删除超过天数的日志:

cs 复制代码
public static void DeleteLog()
        {
            Task.Factory.StartNew(() =>
            {
                DirectoryInfo di = new DirectoryInfo(parameter.LogFilePath);
                if (!di.Exists)
                    di.Create();
                FileInfo[] fi = di.GetFiles("*.log");
                DateTime dateTime = DateTime.Now;
                foreach (FileInfo info in fi)
                {
                    TimeSpan ts = dateTime.Subtract(info.LastWriteTime);
                    if (ts.TotalDays > parameter.LogFileExistDay)
                    {
                        info.Delete();
                    }
                }
            });
        }

每天生成一个新的日志,MonitorDay

cs 复制代码
public static void MonitorDay() 
        {
            DateTime date = DateTime.Now;
            int oldDay = date.Day;
            while (true)
            {
                Thread.Sleep(500);
                date = DateTime.Now;
                int day = date.Day;
                if (day == oldDay)
                    continue;
                else
                {
                    oldDay = day;
                    InitLog();
                }
            }
        }

除了上述的东西之外,其余的就是根据日志等级来打印日志了。

cs 复制代码
public static void Debug(object messsage)
        {
            if ((int)parameter.LogLevel <= (int)Parameter.LogLevelEnum.Debug)
            {
                log.Debug(messsage);
            }
        }

        public static void Debug(string format, params object[] args)
        {
            if ((int)parameter.LogLevel <= (int)Parameter.LogLevelEnum.Debug)
            {
                log.DebugFormat(format, args);
            }
        }

        public static void Info(object message)
        {
            if ((int)parameter.LogLevel <= (int)Parameter.LogLevelEnum.Info)
            {
                log.Info(message);
            }
        }

        public static void Info(string format, params object[] args)
        {
            if ((int)parameter.LogLevel <= (int)Parameter.LogLevelEnum.Info)
            {
                log.InfoFormat(format, args);
            }
        }

        public static void Warn(object message)
        {
            if ((int)parameter.LogLevel <= (int)Parameter.LogLevelEnum.Warn)
            {
                log.Warn(message);
            }
        }

        public static void Warn(string format, params object[] args)
        {
            if ((int)parameter.LogLevel <= (int)Parameter.LogLevelEnum.Warn)
            {
                log.WarnFormat(format, args);
            }
        }

        public static void Error(object message)
        {
            if ((int)parameter.LogLevel <= (int)Parameter.LogLevelEnum.Error)
            {
                log.Error(message);
            }
        }

        public static void Error(object message, Exception exception)
        {
            if ((int)parameter.LogLevel <= (int)Parameter.LogLevelEnum.Error)
            {
                log.Error(message, exception);
            }
        }

        public static void Error(string format, params object[] args)
        {
            if ((int)parameter.LogLevel <= (int)Parameter.LogLevelEnum.Error)
            {
                log.ErrorFormat(format, args);
            }
        }

        public static void Fatal(object message)
        {
            if ((int)parameter.LogLevel <= (int)Parameter.LogLevelEnum.Fatal)
            {
                log.Fatal(message);
            }
        }

        public static void Fatal(object message, Exception exception)
        {
            if ((int)parameter.LogLevel <= (int)Parameter.LogLevelEnum.Fatal)
            {
                log.Fatal(message, exception);
            }
        }

        public static void Fatal(string format, params object[] args)
        {
            if ((int)parameter.LogLevel <= (int)Parameter.LogLevelEnum.Fatal)
            {
                log.FatalFormat(format, args);
            }
        }

至此,我们的库开发完成。欢迎留言交流。

相关推荐
周杰伦fans5 小时前
C# 中的 简单工厂模式 (Simple Factory)
c#·简单工厂模式
ajassi20006 小时前
开源 C# 快速开发(十一)线程
http·开源·c#
周杰伦fans14 小时前
C# 23种设计模式详解与示例
开发语言·设计模式·c#
xb113216 小时前
C#——方法的定义、调用与调试
开发语言·c#
code bean16 小时前
【C#】以 BlockingCollection 为核心的多相机 YOLO 检测任务处理框架
c#
时光追逐者18 小时前
一款专门为 WPF 打造的开源 Office 风格用户界面控件库
ui·开源·c#·.net·wpf
-可乐加冰吗20 小时前
SuperMap iObjects .NET 11i 二次开发(十五)—— 类型转换之面转点
visualstudio·c#·.net
ajassi200021 小时前
开源 C# 快速开发(十二)进程监控
开发语言·开源·c#
大飞pkz1 天前
【设计模式】代理模式
开发语言·设计模式·c#·代理模式