新建一个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