环境:
- window 10 x64
- vs2019
- .net core3.1
一、为什么要做一个输出到本地文件的日志输出组件?
- 第一:微软提供了一个很好的日志输出框架,也提供了基本的控制台输出组件,但没有提供输出到文件的日志组件,很是遗憾;
- 第二:第三方日志组件(如:NLog、Serialog、Log4net)功能虽然比较全,但也引入了其他大量的概念和规则。而对于中小型项目来说,他们仅需要输出到本地文件即可,所以在使用的便捷上总是差强人意。
- 第三:第三方日志组件在某些功能上也不尽如人意,比如:是否能将日志消息按照日志类别输出到不同文件中?在程序工作时,是否占用日志文件?是否能排除某个类别的日志文件不输出?
- 第四:练手。
二、想要实现一个怎样的效果?
- 不引入新的规则概念;
- 不引入额外的配置文件;
- 实现非占用文件式输出并提供按照日志类别过滤输出到不同的文件;
- 力求轻量级;
三、这个日志组件的实现思路和代码来源
关于日志框架和第三方日志组件(日志记录提供程序)的知识,请查看:
《.netcore入门31:.net core中的日志框架》
至于实现思路则是大量参考控制台输出组件的源码(Microsoft.Extensions.Logging.Console
)。
四、动手编写
源码地址:https://gitee.com/jackletter/jackletter.microsoft.extensions.logging.file
五、使用方法
第一步: 安装包
<ItemGroup>
<PackageReference Include="Jackletter.Filelog" Version="1.0.0" />
</ItemGroup>
第二步:修改Program.cs
文件,引入组件
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(loggingBuilder =>
{
loggingBuilder.ClearProviders();
loggingBuilder.AddConsole();
//一行代码即可引入
loggingBuilder.AddFile();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
第三步: 配置appsettings
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
},
"File": {
"IncludeScopes": false,
"InternalLogFile": "logs/internal-#datetime{yyyy-MM-dd}#.log",
"LogLevel": {
"Default": "Trace",
"Microsoft": "Debug"
},
"Writers": [
{
"Path": "logs/system-info-#datetime{yyyy-MM-dddddd}#.log",
"FirstInclude": [ "Microsoft", "System" ]
},
{
"Path": "logs/app-#datetime{yyyy-MM-dd}#.log",
"FirstInclude": [ "*" ],
"SecondExclude": [ "Microsoft", "System" ]
}
]
}
},
"AllowedHosts": "*"
}
上面的配置,File
节点表示的是Jackletter.FileLog
的配置内容。
其中,"IncludeScopes"
、"LogLevel"
属于日志框架中的内容,Jackletter.FileLog
仅使用"InternalLogFile"
和"Writers"
作为配置内容。
"InternalLogFile"
:表示日志组件内部使用的日志,这里仅记录Jackletter.FileLog
工作时产生的异常或其他调试信息;Writers
:表示要输出的文件路径集合,Path
表示路径信息,其中可以包含日期格式串(如:#datetime{yyyyMMdd}
)、日志级别格式串(如:#level#
)。
"FirstInclude"
:表示该输出路径要引入支持的日志类别(默认不支持任何日志类别,所以要先引入)。
SecondExclude
:表示要从FirstInclude
引入的日志类别中排除的日志类别。
第四步:写测试代码
namespace SimpleFileLog.Controllers
{
[ApiController]
[Route("[controller]")]
public class HomeController : ControllerBase
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
[HttpGet]
public string Get()
{
_logger.LogTrace("trace");
_logger.LogDebug("debug");
_logger.LogInformation("info");
_logger.LogWarning("warn");
_logger.LogError("error");
_logger.LogCritical("critical");
using (_logger.BeginScope("测试日志的Scope"))
{
_logger.LogTrace("scope-trace");
_logger.LogDebug("scope-debug");
_logger.LogInformation("scope-info");
_logger.LogWarning("scope-warn");
_logger.LogError("scope-error");
_logger.LogCritical("scope-critical");
}
_logger.LogTrace("Scope已经结束了。。。");
//throw new Exception("测试异常日志");
return "ok";
}
}
}
第五步:运行看效果