最近处理一个日志功能,用log4net的配置不能完全满足要求,所以在其基础上简单封装了一下,支持以下功能:

1 零配置

内置默认配置,引用dll后不需要添加或修改任何配置文件也可以使用

2 动态指定文件路径和文件名

我们的需求是按请求来源和功能生成多个独立的日志文件,例如  /app编号/功能编号.txt 的结构,需要根据请求动态指定文件名称

3 按日期和大小自动分割文件,满足其中一个条件即可

来看实现

一、自定义读取配置文件的Appender

为了同时支持零配置和使用配置文件的方式,采用自定义一个用于读取配置项的Appender,初始化Logger时首先读取配置项中的同名Appender,如果存在使用配置参数,如果不存在则使用默认配置。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace Rainstorm.Log4net
{/// <summary>/// http://blog.csdn.net/autfish/// </summary>public class ReadParamAppender : log4net.Appender.AppenderSkeleton{private string _file;public string File{get { return this._file; }set { _file = value; }}private int _maxSizeRollBackups;public int MaxSizeRollBackups{get { return this._maxSizeRollBackups; }set { _maxSizeRollBackups = value; }}private bool _appendToFile = true;public bool AppendToFile{get { return this._appendToFile; }set { _appendToFile = value; }}private string _maximumFileSize;public string MaximumFileSize{get { return this._maximumFileSize; }set { _maximumFileSize = value; }}private string _layoutPattern;public string LayoutPattern{get { return this._layoutPattern; }set { _layoutPattern = value; }}private string _datePattern;public string DatePattern{get { return this._datePattern; }set { _datePattern = value; }}private string _level;public string Level{get { return this._level; }set { _level = value; }}protected override void Append(log4net.Core.LoggingEvent loggingEvent){}}
}

二、动态创建Logger工厂类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Concurrent;
using System.Configuration;using log4net;
using log4net.Appender;
using log4net.Core;
using log4net.Layout;
using log4net.Repository;
using log4net.Repository.Hierarchy;[assembly: log4net.Config.XmlConfigurator(Watch = true)]
namespace Rainstorm.Log4net
{/// <summary>/// http://blog.csdn.net/autfish/// </summary>public static class CustomRollingFileLogger{private static readonly ConcurrentDictionary<string, ILog> loggerContainer = new ConcurrentDictionary<string, ILog>();private static readonly Dictionary<string, ReadParamAppender> appenderContainer = new Dictionary<string, ReadParamAppender>();private static object lockObj = new object();//默认配置private const int MAX_SIZE_ROLL_BACKUPS = 20;private const string LAYOUT_PATTERN = "%d [%t] %-5p %c  - %m%n";private const string DATE_PATTERN = "yyyyMMdd\".txt\"";private const string MAXIMUM_FILE_SIZE = "256MB";private const string LEVEL = "debug";//读取配置文件并缓存static CustomRollingFileLogger(){IAppender[] appenders = LogManager.GetRepository().GetAppenders();for (int i = 0; i < appenders.Length; i++){if (appenders[i] is ReadParamAppender){ReadParamAppender appender = (ReadParamAppender)appenders[i];if (appender.MaxSizeRollBackups == 0){appender.MaxSizeRollBackups = MAX_SIZE_ROLL_BACKUPS;}if (appender.Layout != null && appender.Layout is log4net.Layout.PatternLayout){appender.LayoutPattern = ((log4net.Layout.PatternLayout)appender.Layout).ConversionPattern;}if (string.IsNullOrEmpty(appender.LayoutPattern)){appender.LayoutPattern = LAYOUT_PATTERN;}if (string.IsNullOrEmpty(appender.DatePattern)){appender.DatePattern = DATE_PATTERN;}if (string.IsNullOrEmpty(appender.MaximumFileSize)){appender.MaximumFileSize = MAXIMUM_FILE_SIZE;}if (string.IsNullOrEmpty(appender.Level)){appender.Level = LEVEL;}lock(lockObj){appenderContainer[appenders[i].Name] = appender;}}}}public static ILog GetCustomLogger(string loggerName, string category = null, bool additivity = false){return loggerContainer.GetOrAdd(loggerName, delegate(string name){RollingFileAppender newAppender = null;ReadParamAppender appender = null;if (appenderContainer.ContainsKey(loggerName)){appender = appenderContainer[loggerName];newAppender = GetNewFileApender(loggerName, string.IsNullOrEmpty(appender.File) ? GetFile(category, loggerName) : appender.File, appender.MaxSizeRollBackups,appender.AppendToFile, true, appender.MaximumFileSize, RollingFileAppender.RollingMode.Composite, appender.DatePattern, appender.LayoutPattern);}else{newAppender = GetNewFileApender(loggerName, GetFile(category, loggerName), MAX_SIZE_ROLL_BACKUPS, true, true, MAXIMUM_FILE_SIZE, RollingFileAppender.RollingMode.Composite, DATE_PATTERN, LAYOUT_PATTERN);}log4net.Repository.Hierarchy.Hierarchy repository = (log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository();Logger logger = repository.LoggerFactory.CreateLogger(repository, loggerName);logger.Hierarchy = repository;logger.Parent = repository.Root;logger.Level = GetLoggerLevel(appender == null ? LEVEL : appender.Level);logger.Additivity = additivity;logger.AddAppender(newAppender);logger.Repository.Configured = true;return new LogImpl(logger);});}//如果没有指定文件路径则在运行路径下建立 Log\{loggerName}.txtprivate static string GetFile(string category, string loggerName){if (string.IsNullOrEmpty(category)){return string.Format(@"Log\{0}.txt", loggerName);}else{return string.Format(@"Log\{0}\{1}.txt", category, loggerName);}}private static Level GetLoggerLevel(string level){if (!string.IsNullOrEmpty(level)){switch (level.ToLower().Trim()){case "debug":return Level.Debug;case "info":return Level.Info;case "warn":return Level.Warn;case "error":return Level.Error;case "fatal":return Level.Fatal;}}return Level.Debug;}private static RollingFileAppender GetNewFileApender(string appenderName, string file, int maxSizeRollBackups, bool appendToFile = true, bool staticLogFileName = false, string maximumFileSize = "5MB", RollingFileAppender.RollingMode rollingMode = RollingFileAppender.RollingMode.Composite, string datePattern = "yyyyMMdd\".txt\"", string layoutPattern = "%d [%t] %-5p %c  - %m%n"){RollingFileAppender appender = new RollingFileAppender{LockingModel = new FileAppender.MinimalLock(),Name = appenderName,File = file,AppendToFile = appendToFile,MaxSizeRollBackups = maxSizeRollBackups,MaximumFileSize = maximumFileSize,StaticLogFileName = staticLogFileName,RollingStyle = rollingMode,DatePattern = datePattern};PatternLayout layout = new PatternLayout(layoutPattern);appender.Layout = layout;layout.ActivateOptions();appender.ActivateOptions();return appender;}}
}

三、使用方法

3.1 零配置

ILog logger = CustomRollingFileLogger.GetCustomLogger("pay", "10001");
logger.Debug("debug message");

将在运行目录下生成 Log\10001\pay.txt

按日期分割日志文件,如果文件超过256M,也进行分割

3.2 使用配置文件

修改App.config/Web.config,添加或修改项

<configSections><section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/></configSections><log4net><appender name="pay" type="Rainstorm.Log4net.ReadParamAppender"><param name="file" value="D:\\log\\pay.txt"/><param name="appendToFile" value="true"/><param name="maxSizeRollBackups" value="100"/><param name="maximumFileSize" value="2MB"/><param name="datePattern" value="yyyyMMdd'.txt'"/><param name="level" value="debug"/><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%d - %m%n"/></layout></appender><root><level value="INFO"/><appender-ref ref="pay"/></root></log4net>
ILog logger = CustomRollingFileLogger.GetCustomLogger("pay");
logger.Debug("debug message");

配置项均为可选项,具体含义如下:

file

文件路径

appendToFile

如果同名文件已存在,是否在文件中追加日志

maxSizeRollBackups

在发生文件分割时,最多保留的历史文件个数

maximumFileSize

设置按文件大小分割的阈值

datePattern

按日期分割时文件重命名规则

level

logger输出等级

layout

日志输出格式

转载于:https://www.cnblogs.com/autfish/p/5557560.html

基于log4net的支持动态文件名、按日期和大小自动分割文件的日志组件相关推荐

  1. 基于gstreamer的支持动态获取多路流的rtsp server(笔记)

    上篇文章讲了streamer的rtsp推流的基本用法 下面讲搭建动态多路流的rtsp server.有两种方式能达到效果,一种采用main_loop_run运行在线程里,另一种则是创建factory等 ...

  2. 基于log4net的日志组件扩展封装,实现自动记录交互日志 XYH.Log4Net.Extend(微服务监控)...

    背景: 随着公司的项目不断的完善,功能越来越复杂,服务也越来越多(微服务),公司迫切需要对整个系统的每一个程序的运行情况进行监控,并且能够实现对自动记录不同服务间的程序调用的交互日志,以及通一个服务或 ...

  3. 【苹果iMessage推】日历推软件安装支持动态点窜任务状况、停息/规复任务,以及停止运转中任务

    推荐内容IMESSGAE相关 作者✈️@IMEAE推荐内容 iMessage苹果推软件 *** 点击即可查看作者要求内容信息 作者✈️@IMEAE推荐内容 1.家庭推内容 *** 点击即可查看作者要求 ...

  4. java selectcommand_“对于不返回任何基表信息的 SelectCommand 不支持动态SQL生成”-奇怪的错误,不知道原因! | 学步园...

    OleDbCommandBuilder更新Access数据库中遇到的问题 部分代码如下: //AccountQuery.aspx.cs protected void FormView1_ItemUpd ...

  5. SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例(转)...

    SpringBoot整合mybatis.shiro.redis实现基于数据库的细粒度动态权限管理系统实例 shiro 目录(?)[+] 前言 表结构 maven配置 配置Druid 配置mybatis ...

  6. ASP.NET使用log4Net日志组件教程(按日期与按日志大小切割)

    对于一个大型网站与系统来说,日志是必备的工具,通过日志你可以非常清楚程序的运行情况,及时得到反馈来解决问题,下面介绍ASP.NET版本的log4Net日志组件是个非常强大的工具,最新版本for .ne ...

  7. 从源码分析常见的基于Array的数据结构动态扩容机制

    本文的写作冲动来源于今晚看到的老赵的一则微博"大家知道System.Collections.Generic.List<T>是一种什么样的数据结构?内部的元素是怎么存放的?还有Di ...

  8. 基于QT ffmpeg的动态桌面壁纸

    基于QT ffmpeg的动态桌面壁纸 目前制作了一个基于QT ffmpeg的动态桌面壁纸,源码程序在github上 下面为链接: 动态壁纸软件 项目名为 DesktopDynamicWallpaper ...

  9. 分布式进阶(十九) 基于集群的动态反馈负载均衡策略

    一.动态WRR调度算法 这是一个目前普遍使用的调度算法,算法在WRR的基础上加入了根据服务器端的负载信息周期性地调整服务器性能权值的过程.其基本思想是:根据CPU利用率.内存利用率.磁盘使用情况.连接 ...

最新文章

  1. 学习《Linux设备模型浅析之设备篇》笔记(深挖一)
  2. SVM+二分类+多分类
  3. dataframe.sum()函数
  4. 关于编译PCL1.71
  5. 网络爬虫ip代理服务器【程序样例】
  6. java jacoco覆盖率报错_接口测试代码覆盖率(jacoco)方案分享
  7. 你的php网页乱码了吗
  8. C语言调用自定义交换函,C语言函数篇 - personal page of Msingwen - OSCHINA - 中文开源技术交流社区...
  9. 8192 oracle,ORA-39095: 转储文件空间已耗尽: 无法分配 8192 字节
  10. 第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明)(热身赛)
  11. 昨晚做了个flash
  12. unbuntu 18.04 LTS 版 安装Samba服务器
  13. C语言中关于float和double的输入输出格式
  14. win10专业版开机画面模糊_新买电脑看起来有点糊?一招教你解决Win10屏幕模糊问题...
  15. Ora-12514原因及处理方法
  16. android cursor循环,Android:Cursor.getColumnIndex()在行循环中是不变的吗?
  17. Kotlin自定义android 控件
  18. 关于我于Security Assistant Agent这个Bitch软件的点滴
  19. java如何读取ic卡_java读取IC卡设备
  20. 2017年愚人节思考

热门文章

  1. 有人问曹德旺:你经历的最大的困难是什么?
  2. 小车启动预热是原地预热,还是慢慢开动预热,哪种方式比较好?
  3. 闺女在大连上大学,一个月1500生活费她说少
  4. 竞价排名才是万恶之源
  5. 吸引人才的十大顶尖运营机制
  6. 客户让无数销售员卑躬屈膝的四大陷阱
  7. 成长有三方面,其中最重要的是
  8. 计算机程序员能做多久,这个行业有年龄限制吗?
  9. 学会用感情营销是最高的智慧
  10. Vue.js开发记录--用watch监听对象中属性的变化