一、准备
尽管在asp.net core中几乎把所有能DI化的技术、知识和概念都依赖注入,不过本人还是想不让自己的项目那么DI化,完全没有必要“为了DI而DI”。这篇文章记录日志在asp.net core中的使用,以应用实战为主,不讲那么多大道理。
在asp.net core中框架提供了四种日志输出方式,即Console日志、Debug日志、EventSource日志和EventLog日志。前两种比较容易理解,EventSource提供程序写入名称为 Microsoft-Extensions-Logging 的跨平台事件源,EventLog提供程序将日志输出发送到 Windows 事件日志。本文主要分析记录Console日志、Debug日志和Log4net日志的使用(前两种无法输出到文件)。
日志类型
Trace=0,Debug=1,Information=2,Warning=3,Error=4,Critical=5,None=6
日志等级
None > Critical > Error > Warning > Information > Debug > Trace
二、实战
1.Console日志和Debug日志
1.1.准备
a)打开VS2022,创建Asp.net core WebApi项目
b)删除简化Program类代码,如下:
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); var app = builder.Build(); app.MapControllers(); app.Run();
1.2.依赖注入模式
1.2.1.Console日志
a)通过nuget工具安装依赖包。
1.Microsoft.Extensions.Logging:基础包
2.Microsoft.Extensions.Logging.Console:输出日志到控制台程序包
b)在Program文件中,配置日志。
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddLogging(logBuilder => { logBuilder.AddConsole(); }); var app = builder.Build(); app.MapControllers(); app.Run();
c)修改测试文件WeatherForecastController的方法Get。
public IEnumerable<WeatherForecast> Get() { _logger.LogTrace("LogTrace"); _logger.LogDebug("LogDebug"); _logger.LogInformation("LogInformation"); _logger.LogWarning("LogWarning"); _logger.LogError("LogError"); _logger.LogCritical("LogCritical"); return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = Random.Shared.Next(-20, 55), Summary = Summaries[Random.Shared.Next(Summaries.Length)] }) .ToArray(); }
d)通过VS运行调试程序,查看输出结果。
LogInformation
LogWarning
LogError
LogCritical
不出意外会输出上述四行结果,Why?请用1.4小节中配置文件,替换掉默认的配置信息就好。
1.2.2.Debug日志
a)通过nuget工具安装依赖包。
Microsoft.Extensions.Logging.Debug:输出日志到Debug程序包
b)在Program文件中,配置日志。
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddLogging(logBuilder => { logBuilder.AddConsole(); logBuilder.AddDebug(); }); var app = builder.Build(); app.MapControllers(); app.Run();
d)通过VS运行调试程序,此时就可以在VS的“输出”窗口中,看到日志的输出信息了。
1.2.3.小节
通过上述操作,你已经能够以依赖注入的方式使用框架内置的日志。如果你从.net framework升级到.net core的程序员,以及你理解DI/IOC的原理,不难看出所谓的依赖注入就是魔法糖。
1.3.工厂模式
在asp.net core中,不仅可以通过AddLogging()方法实现日志的配置和启用,还可以通过日志工厂进行操作。
使用日志工厂方式,appsettings.json配置文件中的日志配置数据就无效了,而以编写代码的方式设置日志输出等级就生效了。
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); var loggerFactory = LoggerFactory.Create(logBuilder => { logBuilder.ClearProviders(); logBuilder.AddConsole(); logBuilder.AddDebug(); logBuilder.SetMinimumLevel(LogLevel.Trace); }); ILogger _logger = loggerFactory.CreateLogger<Program>(); _logger.LogTrace("LogTrace"); _logger.LogDebug("LogDebug"); _logger.LogInformation("LogInformation"); _logger.LogWarning("LogWarning"); _logger.LogError("LogError"); _logger.LogCritical("LogCritical"); var app = builder.Build(); app.MapControllers(); app.Run();
1.4.配置文件
特别提示,asp.net core项目中,配置文件的日志配置数据的优先级要高于程序中编写代码,仅限于依赖注入模式。
{ "Logging": { "Console": { "LogLevel": { "Default": "Trace", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "Debug": { "LogLevel": { "Default": "Trace", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "EventSource": { "LogLevel": { "Microsoft": "Warning" } }, "EventLog": { "LogLevel": { "Microsoft": "Warning" } }, "LogLevel": { "Default": "Trace", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*" }
1.5.总结
通过上述两种方式,实现了日志输出到Console和Debug,但是框架并没有提供输出到硬盘文件的程序包,所以需要借助第三方的程序包实现将日志输出到文件的需求。
2.Log4net日志
不能把日志输出到文件中或写入到日志系统里,是无法保证系统安全稳定运行以及快速定位查找问题的,所以一定要实现在程序部署运行中,将日志输出到硬盘文件或专门的日志系统里的需求,所以此处用到了Log4net程序包。
2.1.依赖注入和工厂模式
在asp.net core中,使用log4net还是比较容易的,主要分为两步:第一安装程序包,第二设置配置文件,第三通过代码启用,如下:
2.1.1.安装程序包
1.log4net:基础包
2.Microsoft.Extensions.Logging.Log4Net.AspNetCore:适配AspNetCore程序的软件包
2.1.1.配置文件
1.特别说明:a)配置文件中<configuration>节点需要去掉;b)配置文件中包含了两种配置,一种适用于AspNetCore,一种是传统.net framework模式。
2.配置文件内容:注意配置文件要输出到根目录,因为程序包默认就是从根目录查找加载。
<?xml version="1.0" encoding="utf-8" ?> <log4net> <!--DIOC日志附加介质--> <!--根配置--> <root> <!--日志级别: NONE > FATAL > ERROR > WARN > INFO > DEBUG > ALL --> <priority value="ALL"/> <level value="ALL"/> <appender-ref ref="DiocAppender" /> </root> <!-- name属性指定其名称,type则是log4net.Appender命名空间的一个类的名称,意思是,指定使用哪种介质--> <appender name="DiocAppender" type="log4net.Appender.RollingFileAppender"> <!--日志输出到exe程序这个相对目录下--> <param name="File" value="logs\\diocs\\" /> <!--输出的日志不会覆盖以前的信息--> <param name="AppendToFile" value="true" /> <!--备份文件的个数--> <param name="MaxSizeRollBackups" value="50" /> <!--最小锁定模型以允许多个进程可以写入同一个文件--> <param name="MaxFileSize" value="10240" /> <!--当前日志文件的最大大小--> <param name="lockingModel" type="log4net.Appender.FileAppender+MinimalLock" /> <!--是否使用静态文件名--> <param name="StaticLogFileName" value="false" /> <!--日志文件名--> <param name="DatePattern" value="yyyyMMdd".txt"" /> <!--文件创建的方式,这里是以Date方式创建--> <param name="RollingStyle" value="Date" /> <!--输出级别在INFO和ERROR之间的日志--> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="ALL" /> <param name="LevelMax" value="FATAL" /> </filter> <!--信息日志布局--> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/> </layout> </appender> <!--错误日志类--> <logger name="logerror"> <!--日志类的名字--> <level value="ALL" /> <!--定义记录的日志级别--> <appender-ref ref="ErrorAppender" /> </logger> <!--信息日志类--> <logger name="loginfo"> <!--日志类的名字--> <level value="ALL" /> <!--定义记录的日志级别--> <appender-ref ref="InfoAppender" /> </logger> <!--错误日志附加介质--> <!-- name属性指定其名称,type则是log4net.Appender命名空间的一个类的名称,意思是,指定使用哪种介质--> <appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender"> <!--日志输出到exe程序这个相对目录下--> <param name="File" value="logs\\errors\\" /> <!--输出的日志不会覆盖以前的信息--> <param name="AppendToFile" value="true" /> <!--备份文件的个数--> <param name="MaxSizeRollBackups" value="50"/> <!--最小锁定模型以允许多个进程可以写入同一个文件--> <param name="MaxFileSize" value="10240" /> <!--当前日志文件的最大大小--> <param name="lockingModel" type="log4net.Appender.FileAppender+MinimalLock" /> <!--是否使用静态文件名--> <param name="StaticLogFileName" value="false" /> <!--日志文件名--> <param name="DatePattern" value="yyyyMMdd".txt"" /> <!--文件创建的方式,这里是以Date方式创建--> <param name="RollingStyle" value="Date" /> <!--错误日志布局--> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="[%t]异常类:%c [%x] 异常信息:%m%n" /> </layout> </appender> <!--信息日志附加介质--> <!-- name属性指定其名称,type则是log4net.Appender命名空间的一个类的名称,意思是,指定使用哪种介质--> <appender name="InfoAppender" type="log4net.Appender.RollingFileAppender"> <!--日志输出到exe程序这个相对目录下--> <param name="File" value="logs\\infos\\" /> <!--输出的日志不会覆盖以前的信息--> <param name="AppendToFile" value="true" /> <!--备份文件的个数--> <param name="MaxSizeRollBackups" value="50" /> <!--最小锁定模型以允许多个进程可以写入同一个文件--> <param name="MaxFileSize" value="10240" /> <!--当前日志文件的最大大小--> <param name="lockingModel" type="log4net.Appender.FileAppender+MinimalLock" /> <!--是否使用静态文件名--> <param name="StaticLogFileName" value="false" /> <!--日志文件名--> <param name="DatePattern" value="yyyyMMdd".txt"" /> <!--文件创建的方式,这里是以Date方式创建--> <param name="RollingStyle" value="Date" /> <!--信息日志布局--> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%m%n" /> </layout> </appender> </log4net>
2.1.2.程序代码
a)依赖注入模式
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddLogging(logBuilder => { logBuilder.AddConsole(); logBuilder.AddDebug(); logBuilder.AddLog4Net(); }); var app = builder.Build(); app.MapControllers(); app.Run();
b)工厂模式
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); var loggerFactory = LoggerFactory.Create(logBuilder => { logBuilder.ClearProviders(); logBuilder.AddConsole(); logBuilder.AddDebug(); logBuilder.AddLog4Net(); logBuilder.SetMinimumLevel(LogLevel.Trace); }); ILogger _logger = loggerFactory.CreateLogger<Program>(); _logger.LogTrace("LogTrace"); _logger.LogDebug("LogDebug"); _logger.LogInformation("LogInformation"); _logger.LogWarning("LogWarning"); _logger.LogError("LogError"); _logger.LogCritical("LogCritical"); var app = builder.Build(); app.MapControllers(); app.Run();
2.2.传统模式
说实话,俺是一个比较纯粹的人,不太喜欢黑魔法,所以使用传统方式记录日志,我更加喜欢。传统方式记录日志的过程没有改变,简单记录一下使用过程:
a)设置配置文件,操作如上,此处不再赘述。
b)创建Log4Writer类
public class Log4Writer { private static readonly log4net.ILog loginfo = log4net.LogManager.GetLogger("loginfo"); private static readonly log4net.ILog logerror = log4net.LogManager.GetLogger("logerror"); public static void WriteLog(string info) { if (loginfo.IsInfoEnabled) { loginfo.Info(info); } } public static void WriteLog(string info, Exception ex) { if (logerror.IsErrorEnabled) { logerror.Error(info, ex); } } }
c)创建Log4Helper类
public class LogHelper { private static object _objLocker = new object(); private static bool _isConfigure = false; public static void Configure() { if (!_isConfigure) { lock (_objLocker) { if (!_isConfigure) { _isConfigure = true; log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo("log4net.config")); } } } } }
d)在Program中启用log4net
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); var app = builder.Build(); app.MapControllers(); jks.core.test.log.LogHelper.Configure(); app.Run();
e)使用测试
public IEnumerable<WeatherForecast> Get() { Log4Writer.WriteLog("aaaaaaaaaaaaaaaaaaaaaaa"); return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = Random.Shared.Next(-20, 55), Summary = Summaries[Random.Shared.Next(Summaries.Length)] }) .ToArray(); }
2.3.特别说明
很多同学可能会问,为什么使用log4net,而不是其他第三方日志程序包?
第一,因为.net framework时就在用;第二,就是因为它比较独立;第三,我不仅仅需要将日志写入到硬盘文件里,还需要写入到专门的日志系统,且日志内容设计了固定的结构。
简单的说,使用日志工具记录日志到硬盘文件是次要的,记录到专门的日志系统才是主要的、核心的。
三、总结
通过上述内容的分析、实验和记录,应该能够在使用asp.net core中使用日志了吧?以及如何从.net framework升级到.net core。
好了,就此结束。
程序源码:https://gitee.com/kinbor/jks.core.test.log
标签:Log4net,logger,Log,2core,builder,var,日志,app,logBuilder From: https://www.cnblogs.com/Jkinbor/p/16969092.html