.NET Framework 使用Log4net日志类

新建一个Log4netHelper类如下

public class Log4netHelper
{
    /// <summary>
    /// 这段代码实现了一个使用 log4net 记录日志的类 Logger。该类使用 BlockingCollection 实现了线程安全的日志队列,并通过初始化 ILoggerRepository 和 Hierarchy 实例来支持自定义配置选项。在此基础上,Logger 还提供了一个 AppendLog 方法,可以将指定的日志消息添加到队列中,并将其写入到日志文件中。同时,Logger 还提供了一个定时任务,用于定期删除过期的日志文件,以解决磁盘空间问题。通过这些功能,Logger 类可以实现高效、可靠、线程安全的日志记录,并能够满足复杂的应用程序日志记录需求。
    /// </summary>
    public class Logger
    {
        // 使用BlockingCollection实现线程安全的日志队列
        private BlockingCollection<LogItem> logMessages;
        private ILog logger;

        /// <summary>
        /// 初始化日志
        /// </summary>
        /// <param name="name">日志文件存储路径</param>
        /// <param name="delday">过期天数</param>
        public Logger(string name, int delday = 7)
        {
            logMessages = new BlockingCollection<LogItem>();

            // 初始化ILoggerRepository和ILHierarchy实例
            var repository = LogManager.CreateRepository(name);
            // 获取Hierarchy实例
            var hierarchy = (Hierarchy)repository;

            // 获取FileAppender实例
            List<RollingFileAppender> appenderList = hierarchy.GetAppenders().OfType<RollingFileAppender>().Where(app => app.Name.Equals(name)).ToList();
            RollingFileAppender appender = appenderList.FirstOrDefault();
            if (appender == null)
            {
                //创建PatternLayout对象,并设置转换格式,可以使用的格式化参数有: 
                //   %date 输出日志发生的时间,可以像C#中的DateTime.ToString方法一样格式化,例如:%date{yyyyMMddHHmmss}
                //   %level 输出日志级别,如:INFO、DEBUG、WARN等
                //   %class 输出完全限定的类型名称
                //   %method 输出调用日志记录方法的方法名
                //   %line 输出源文件中调用日志记录方法的行号
                //   %logger 输出日志记录器名称
                //   %message 输出日志消息
                //   %newline 输出平台特定的换行符
                //   %exception 输出异常信息
                var layout = new PatternLayout("[%date{yyyy-MM-dd HH:mm:ss,fff}] 【%-5level】 %message %newline");
                layout.ActivateOptions();

                // 创建RollingFileAppender对象,并设置日志文件路径、文件名、日志滚动策略、最大日志文件大小等参数
                appender = new RollingFileAppender
                {
                    Name = name,
                    File = $"Log4net\\{name}\\",// 日志文件存储路径和文件名
                    AppendToFile = false,// 每次启动应用程序时,是否在日志文件后追加新的日志消息
                    LockingModel = new MinimalLock(),//最小锁定模式,以允许多个进程可以写入同一个文件
                    Encoding = Encoding.UTF8,//使用Unicode编码,不加utf-8编码格式,中文字符将显示成乱码
                                             //当日志文件达到MaximumFileSize大小,就自动创建备份文件。备份文件的多少由MaxSizeRollBackups决定。
                    MaximumFileSize = "50MB",// 单个日志文件的最大大小
                    MaxSizeRollBackups = 10,// 最多产生的日志文件数,超过则只保留最新的n个。设定值value = "-1"为不限文件数
                    StaticLogFileName = false,//是否只写到一个txt文件中
                    RollingStyle = RollingFileAppender.RollingMode.Composite,// 按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])
                    DatePattern = "yyyy-MM-dd/HH'.log'",//按日期产生文件夹,按时间产生文件[在日期方式与混合方式下使用]
                    Layout = layout//信息日志布局
                };
                appender.ActivateOptions();
                hierarchy.Root.AddAppender(appender);// 将Appender添加到Hierarchy中
            }

            hierarchy.Root.Level = Level.All;

            // 配置Hierarchy对象,并记得在使用完Logger实例后要调用ILoggerRepository.Shutdown()方法来释放资源
            hierarchy.Configured = true;

            // 获取指定名称的Logger实例
            logger = LogManager.GetLogger(repository.Name, name);

            // 初始化日志消息队列(缓冲策略使用先进先出的ConcurrentQueue策略)
            logMessages = new BlockingCollection<LogItem>(new ConcurrentQueue<LogItem>());

            //写日志线程
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    try
                    {
                        foreach (LogItem item in logMessages.GetConsumingEnumerable())
                        {
                            switch (item.Level)
                            {
                                case LogLevel.Info:
                                    logger.Info(item.Message);
                                    break;
                                case LogLevel.Warning:
                                    logger.Warn(item.Message);
                                    break;
                                case LogLevel.Error:
                                    logger.Error(item.Message);
                                    break;
                                case LogLevel.Debug:
                                    logger.Debug(item.Message);
                                    break;
                                case LogLevel.Fatal:
                                    logger.Fatal(item.Message);
                                    break;
                            }
                        }
                    }
                    catch { }

                    Task.Delay(1).Wait();
                }
            });

            //定时删过期日志
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    try
                    {
                        if (logger.Logger.Repository.GetAppenders()[0] is FileAppender appender1)
                        {
                            string filePath = Directory.GetParent(Path.GetDirectoryName(appender1.File)).FullName;
                            TimeDelLog(filePath, delday);
                        }
                    }
                    catch (Exception ex)
                    {
                        logger.Error($"删除过期日志失败:{ex}");
                    }

                    Task.Delay(60 * 1000).Wait();
                }
            });
        }

        /// <summary>
        /// 将指定的日志消息添加到队列中
        /// </summary>
        /// <param name="message">日志消息</param>
        /// <param name="logLevel">日志级别(默认为Info级别)</param>
        public void AppendLog(string message, LogLevel logLevel = LogLevel.Info)
        {
            logMessages.Add(new LogItem
            {
                Level = logLevel,
                Message = message
            });
        }

        /// <summary>
        /// 删除过期文件
        /// </summary>
        /// <param name="logDirectory">文件夹目录</param>
        /// <param name="daysToKeep">过期时间</param>
        public void TimeDelLog(string logDirectory, int daysToKeep)
        {
            try
            {
                DirectoryInfo dir = new DirectoryInfo(logDirectory);
                if (!dir.Exists) return;

                string[] dirs = Directory.GetDirectories(logDirectory);
                foreach (string dirName in dirs)
                {
                    DirectoryInfo item = new DirectoryInfo(dirName);
                    var cutoff = DateTime.Now.AddDays(-1 * daysToKeep);
                    if (item.CreationTime < cutoff)
                    {
                        item.Delete(true);
                    }
                }
            }
            catch //(Exception ex)
            {
                //Log.Warn($"Failed to clean log files. {ex.Message}");
            }
        }
    }

    /// <summary>
    /// 日志级别
    /// </summary>
    public enum LogLevel
    {
        Info, Warning, Error, Debug, Fatal
    }

    /// <summary>
    /// 表示一个待写入日志的条目
    /// </summary>
    public class LogItem
    {
        public LogLevel Level { get; set; }
        public string Message { get; set; }
    }
}

以下是调用实例

Log4netHelper.Logger log4net1 = new Log4netHelper.Logger("log4netInfo");
Log4netHelper.Logger log4net2 = new Log4netHelper.Logger("log4net1");
Log4netHelper.Logger log4net3 = new Log4netHelper.Logger("log4net2");
Log4netHelper.Logger log4net4 = new Log4netHelper.Logger("log4net3");

log4net1.AppendLog($"启动服务成功");

Task.Factory.StartNew(() =>
{
    log4net2.AppendLog($"线程日志1开始");
    for (int k = 0; k < 50; k++)
    {
        log4net2.AppendLog($"【线程{Task.CurrentId}】这是第{k}条日志消息");
    }
    log4net2.AppendLog($"线程日志1结束");
}, TaskCreationOptions.LongRunning);
Task.Factory.StartNew(() =>
{
    log4net3.AppendLog($"线程日志2开始");
    for (int k = 0; k < 50; k++)
    {
        log4net3.AppendLog($"【线程{Task.CurrentId}】这是第{k}条日志消息");
    }
    log4net3.AppendLog($"线程日志2结束");
}, TaskCreationOptions.LongRunning);
Task.Factory.StartNew(() =>
{
    log4net4.AppendLog($"线程日志3开始");
    for (int k = 0; k < 50; k++)
    {
        log4net4.AppendLog($"【线程{Task.CurrentId}】这是第{k}条日志消息");
    }
    log4net4.AppendLog($"线程日志3结束");
}, TaskCreationOptions.LongRunning);

log4net1.AppendLog($"停止服务成功");

作者:是孤千羽吖!
转载请加上原文地址:https://blog.csdn.net/qianjue427/article/details/130839514?spm=1001.2014.3001.5501

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值