我们在实际项目开发的过程中,日志记录是一个非常重要的功能点,记录日志,可以帮我们很好的分析问题,定位问题,解决问题,一个完整的项目必须要有日志记录的模块。
-
Logging的使用
- 日志的级别,日志级别是指我们将系统产生的相关的日志信息设置的级别,级别越高,就告知我们越需要注意产生的问题,主要的级别有Trace、Debug、Informatica、Warning、Error、Critical,越往后级别越高。我们实际项目中一般根据不同的级别来设定不同的文件进行记录。
- 日志提供者(LoggingProvider),负责把日志输出到哪里,控制台,文件,数据库等。
Logging是 .Net自带的一款日志记录插件,我们运行它来进行日志记录行有以下步骤
a.在Nuget包管理中安装Microsoft.Extensions.Logging包和Microsoft.Extensions.Logging(此包是用来将日志输出到控制台使用),
b.DI 注入,将Logging日志服务通过DI注入到服务容器中,
c.在需要记录日志的功能模块中,通过构造函数注入ILoger<T> 服务的方式获取日志服务即可,T一般为当前类名,主要是为了定位在哪个类产生的日志。然后通过LogInformation(),LogError()等方法输出日志。
public class TestLoger
{
private readonly ILogger<TestLoger> _logger;
public TestLoger(ILogger<TestLoger> logger)
{
_logger = logger;
}
public void LogTest()
{
_logger.LogDebug("这是debug日志");
_logger.LogInformation("这是info日志");
_logger.LogWarning("这是warning日志");
_logger.LogError("这是error日志");
try
{
File.ReadAllText("..../232");
}
catch (Exception ex)
{
_logger.LogError(ex,"这是error日志");
}
}
}
class Program
{
static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
//服务注入
services.AddScoped<TestLoger>();
//日志服务注入
services.AddLogging(loggingBuilder =>
{
loggingBuilder.AddConsole();
loggingBuilder.SetMinimumLevel(LogLevel.Trace);
});
//
using (var sp = services.BuildServiceProvider())
{
var testLog = sp.GetService<TestLoger>();
testLog.LogTest();
}
}
}
运行结果如下:
NLog的使用
上面我们用了Logging实现将日志输出到控制台,但是在实际项目运维过程中,运维人员是不可能去通过控制台翻看程序运行日志,因为太不方便,并且控制台记录的信息,一旦控制台关闭,日志信息就很难找回来,所以,在现实运维中,一般把程序运行的日志通过文本文件的形式存储下来,并且一般规定以天为单位生成相应的日志记录文件,再细分一点,再根据日志的不同级别生成不同的文件,这样就能很大程度的方便运维人员快速定位到问题所在,所以,我们需要用到NLog这个专门用以记录日志并且按照一定规则生成日志文件的插件:
- NLog,NuGet安装:NLog.Extensions.Logging(using NLog.Extensions.Logging;)。项目根目录下建nlog.config,注意文件名的大小写(考虑linux).也可以是其他文件名,但是需要单独配置。
- 配置文件里面的<Targets>节点为设置日志输出的方式,<rules>为每种输出形式的具体输出级别设定等等,可以设置多个输出方式,包括文件,控制台等,
interLogFile:为全局日志输出目录
<target>里面的<name>节点:为定位的每种输出形式的名字,
<target>里面的<xsi:type>节点:为日志输出类型,可以设置为文件file或者控制台Console等
<target>里面的<fileName>节点:为输出日志文件的路径名称格式,可以设置为短日期+日志级别等等
<target>里面的<layout>节点:为日志文件中每条日志展示的内容和拼接方式
<rule>里面的<Logger> 的<minlevel>为日志输出的最低级别,<maxlevel>为日志输出的最高级别,<writeTo>为指向上面<Targets>里面定义的输出目标的name值,
- 在注入日志方法代码段里面增加logBuilder.AddNLog()
class Program
{
static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
//服务注入
services.AddScoped<TestLoger>();
//日志服务注入
services.AddLogging(loggingBuilder =>
{
loggingBuilder.AddConsole();
loggingBuilder.SetMinimumLevel(LogLevel.Trace);
loggingBuilder.AddNLog();
});
//
using (var sp = services.BuildServiceProvider())
{
var testLog = sp.GetService<TestLoger>();
testLog.LogTest();
}
}
}
运行程序之后,会发现在根目录下生成一个以时间,日志级别,具体类名命名的日志文件
打开文件查看日志内容,会发现里面的内容输出就是我们在nlog.config文件中定义的格式:
日志的分类、过滤
- 不同级别的日志,不同模块的日志记录到不同的地方,
- 为什么要日志过滤,项目不同阶段(比如刚上线和稳定后)需要记录的日志不同。严重的错误需要发送短信等等需求。
我们新建一个测试类TestLogerFilter,修改命名空间为System.TestLogFilter,模拟实现针对Ftp的操作日志
public class TestLogerFilter
{
private readonly ILogger<TestLogerFilter> _logger;
public TestLogerFilter(ILogger<TestLogerFilter> logger)
{
_logger = logger;
}
public void LogTest()
{
_logger.LogDebug("这是Ftp的debug日志");
_logger.LogInformation("这是Ftp的info日志");
_logger.LogWarning("这是Ftp的warning日志");
_logger.LogError("这是Ftp的error日志");
}
}
在nlog.config配置文件中增加一个针对这个类的日志输出target节点
运行程序后,会发现TestLogerFilter的日志单独形成了一个文件;
rules节点知识
1、rules节点下可以添加多个logger,每个logger都有名字(name属性),name是通配符格式的。
2、logger节点的minlevel属性和maxlewel属性,表示这个logger接受日志的最低级别和最高级别。3、日志输出时,会从上往下匹配rules节点下所有的logger,若发现当前日志的分类名和Level符合这个logger的name的通配符,就会把日志输出给这个logger。如果匹配多个logger,就把这条日志输出给多个logger。但是如果一个logger设置了final="true",那么如果匹配到这个logger,就不继续向下匹配其他1ogger了。
4、archiveAboveSize为“单个日志文件超过多少字节就把日志存档”,单位为字节,这样可以避免单个文件太大;
5、如果不设定maxArchiveFiles参数,则文件日志存档文件的数量会一直增加,而如果设定maxArchiveFiles参数后,则最多保存mmax系rchiveFiles指定数量个数的存档文件,旧的会被删掉;当然也可以不设置maxArchiveFiles参数;
6、而设置maxarchiveDays参数,这样可以设定保存若干天的日志存档;