c# log4net 日志的使用
参考:C# log4net的使用。输出的日志内容添加文件名和行号。_log4net 发布 输出的文件中行号-CSDN博客
1.NuGet增加log4net
2.增加log4net.config文件
log4net.config的内容如下,没有的功能可以搜一搜,设置 log4net.config的属性 复制到输出目录 设为始终复制
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/> </configSections> <!--(高) OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL (低)--> <log4net> <!--调试信息--> <logger name="InfoLog"> <level value="ALL" /> <appender-ref ref="InfoAppender" /> </logger> <!--错误信息--> <logger name="ErrorLog"> <level value="ALL" /> <appender-ref ref="ErrorAppender" /> </logger> <!--Info日志附加介质--> <appender name="InfoAppender" type="log4net.Appender.RollingFileAppender"> <!--日志路径--> <param name= "File" value= "Logs\"/> <!--是否是向文件中追加日志--> <param name= "AppendToFile" value= "true"/> <!--log保留天数--> <param name= "MaxSizeRollBackups" value= "100"/> <!--写到一个文件--> <staticLogFileName value="false"/> <!--单个文件大小。单位:KB|MB|GB--> <maximumFileSize value="200MB"/> <!--最多保留的文件数,设为"-1"则不限--> <maxSizeRollBackups value="-1"/> <!--日志文件名格式--> <param name= "DatePattern" value= "yyyyMM\\yyyyMMdd'_InfoLog.log'"/> <!--不以独占方式记录日志,仅在记录每个日志的最短时间内锁定,因为部署到服务器上遇到了文件被占用无法下载日志--> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <!--日志根据日期滚动--> <param name= "RollingStyle" value= "Date"/> <!--日志文本格式--> <layout type="log4net.Layout.PatternLayout"> <!--%d 时间,等价于 date--> <!--%t 线程--> <!--%-5p 日志级别--> <!--%C 出错类,等价于 class,可以使用:%class{1},如果给出了精度说明符, 则只会打印类名中最右边的组件的相应数量。默认情况下,类名以完全限定形式输出。--> <!--%L 出错行--> <!--%M 方法名,等价于 method--> <!--%m 日志信息,等价于 message--> <!--%n 换行--> <!--这种情况输出的类名方法名输出的是封装的类名<LogHelper>方法名每有意义--> <!--<param name="ConversionPattern" value="**********%d 线程[%t] 日志级别[%p] **********%n类名:%C 方法名:%M - 第 [%L] 行%n消息:%m%n%n" />--> <param name="ConversionPattern" value="**********%d 线程[%t] 日志级别[%p]**********%n消息:%m%n%n"/> </layout> </appender> <!--Error日志附加介质--> <appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender"> <!--日志路径--> <param name= "File" value= "Logs\"/> <!--是否是向文件中追加日志--> <param name= "AppendToFile" value= "true"/> <!--log保留天数--> <param name= "MaxSizeRollBackups" value= "100"/> <!--日志文件名是否是固定不变的--> <param name= "StaticLogFileName" value= "false"/> <!--日志文件名格式--> <param name= "DatePattern" value= "yyyyMM\\yyyyMMdd'_ErrorLog.log'"/> <!--日志根据日期滚动--> <param name= "RollingStyle" value= "Date"/> <param name="MaxFileSize" value="1"/> <!--日志文本格式--> <layout type="log4net.Layout.PatternLayout"> <!--%d 时间,等价于 date--> <!--%t 线程--> <!--%-5p 日志级别--> <!--%C 出错类,等价于 class,可以使用:%class{1},如果给出了精度说明符, 则只会打印类名中最右边的组件的相应数量。默认情况下,类名以完全限定形式输出。--> <!--%L 出错行--> <!--%M 方法名,等价于 method--> <!--%m 日志信息,等价于 message--> <!--%n 换行--> <!--这种情况输出的类名方法名输出的是封装的类名<LogHelper>方法名每有意义--> <!--<param name="ConversionPattern" value="**********%d 线程[%t] 日志级别[%p] **********%n类名:%C 方法名:%M - 第 [%L] 行%n消息:%m%n%n" />--> <param name="ConversionPattern" value="**********%d 线程[%t] 日志级别[%p]**********%n消息:%m%n%n"/> </layout> </appender> </log4net> </configuration>
3.创建LogHelper.cs类
using System.Diagnostics; using System.IO; using log4net; [assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4net\\log4net.config", Watch = true)] namespace TestLog4net.Log4net { /// <summary> /// 日志助手类 /// </summary> internal class LogHelper { private static ILog InfoLog = LogManager.GetLogger("InfoLog"); private static ILog ErrorLog = LogManager.GetLogger("ErrorLog"); //Debug Info Warn Error方法 在日志里体现在日志级别上 /// <summary> /// 写日志 /// </summary> /// <param name="message">日志信息</param>
public static void WriteInfoLog(string message)
{
InfoLog.Info(AppendClassLine(message));
}
/// <summary> /// 写错误日志 /// </summary> /// <param name="message">日志信息</param> public static void WriteErrorLog(string message) { ErrorLog.Error(AppendClassLine(message)); } /// <summary> /// 给日志信息附加所在文件名和行 /// </summary> /// <param name="msg">日志信息</param> /// <returns>附加后的日志信息</returns> static string AppendClassLine(string msg) { string logStr = msg; try { //测试了一下这个new StackTrace(true) 10w次耗时1.3秒,性能可以接收啊 //这个原理是读pdb文件,也许大项目读这个文件会更耗时 StackTrace st = new StackTrace(true); StackFrame sf = st.GetFrame(2); logStr = $"{msg} [{Path.GetFileName(sf.GetFileName())}:{sf.GetFileLineNumber().ToString()}]"; } catch { logStr = $"{msg} [没找到文件名和所在行]"; } return logStr; } } }
这里的new StackTrace(true)性能测试代码如下
using System; using System.Diagnostics; namespace ConsoleApp1 { internal class Program { static void Main(string[] args) { const int iterations = 100000; // 测试 new StackTrace(false) 的性能 var stopwatch1 = Stopwatch.StartNew(); for (int i = 0; i < iterations; i++) { var stackTrace = new StackTrace(false); } stopwatch1.Stop(); Console.WriteLine($"new StackTrace(false) 耗时: {stopwatch1.ElapsedMilliseconds} 毫秒"); // 测试 new StackTrace(true) 的性能 var stopwatch2 = Stopwatch.StartNew(); for (int i = 0; i < iterations; i++) { var stackTrace = new StackTrace(true); } stopwatch2.Stop(); Console.WriteLine($"new StackTrace(true) 耗时: {stopwatch2.ElapsedMilliseconds} 毫秒"); } } }
4.日志调用
using TestLog4net.Log4net; namespace TestLog4net { internal class Program { static void Main(string[] args) { LogHelper.WriteInfoLog("info日志"); LogHelper.WriteErrorLog("error日志"); } } }
5.日志效果
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
2022-02-14 C# 读写opc ua服务器,浏览所有节点,读写节点,读历史数据,调用方法,订阅,批量订阅操作(转载)
2022-02-14 使用KEPServerv6进行OPC_UA的服务器搭建(转载)