文章目录
1.日志框架-日志框架最佳姿势
- 引用程序包
- Microsoft.Extensions.Logging
- Microsoft.Extensions.Logging.Console
- Microsoft.Extensions.Logging.Debug
- Microsoft.Extensions.Logging.TraceSource
// 控制台程序
static void Main(string[] args)
{
// 读取文件配置
IConfigurationBuilder configBuilder = new ConfigurationBuilder();
configBuilder .AddJsonFile("appsettings.json",optional:false,reloadOnChange:true);
var config = configBuilder.Build();
// 将实例注册到容器
IServiceCollection serviceCollection = new ServiceCollection();
//如果直接这样注册,那么容器将不会管理注册实例的生命周期
//serviceCollection.AddSingleton< IConfiguration>(config);
//用工厂模式将配置对象注册到容器管理
serviceCollection.AddSingleton< IConfiguration>(p=>config);
serviceCollection.AddLogging(builder=>
{
builder.AddConfiguration(config.GetSection("Logging"));
builder.AddConsole();
});
IServiceProvider service = serviceCollection.BuildServiceProvider();
// 日志对象获取
ILoggerFactory loggerFactory = service.GetService< ILoggerFactory>();
// 创建日志记录器
var alogger = loggerFactory.CreateLogger("alogger");
alogger.LogDebug(100,"mess");// 100为定义的事件ID
alogger.LogInformation("hello");
}
// 配置文件
{
"Logging":{
"LogLevel":{
"Default":"Debug",
"Microsoft":"Warning",
"Microsoft.Hosting.Lifetime":"Information"
}
},
"Console":{
"LogLevel":{
"Default":"Information",
"Program":"Trace",
"alogger":"Trace"
}
}
}
- 日志需要避免记录敏感信息,如密码、密码
⑴ alogger.LogInformation(“Message Time is {dateTime}”,DateTime.Now);
⑵ alogger.LogInformation($@“Message Time is {DateTime.Now}”);
如上所示,上述两句代码执行结果是相同的,但是具体执行逻辑是不同的。
第⑴行代码的字符串拼接是发生在LogInformation内部的Console输出时产生,
而第⑵行代码的字符串拼接发生在向LogInformation传递参数之前。
如果日志输出级别设置为None时,虽然两行代码的输出都是空,但是第⑴行代码的字符串拼接不会发生,而第⑵行的字符串拼接还是发生了,这是对服务器性能的一个比较大的消耗,这里需要避免
2.日志作用域-解决不同请求之间的日志干扰
2.1 作用域场景
- 一个事务包含多条操作
- 复杂流程的日志关联,如工作流流程记录日志
- 调用链追踪与请求处理过程对应时
static void Main(string[] args)
{
// 读取文件配置
IConfigurationBuilder configBuilder = new ConfigurationBuilder();
configBuilder.CommandLine(args);
configBuilder .AddJsonFile("appsettings.json",optional:false,reloadOnChange:true);
var config = configBuilder.Build();
// 将实例注册到容器
IServiceCollection serviceCollection = new ServiceCollection();
//用工厂模式将配置对象注册到容器管理
serviceCollection.AddSingleton< IConfiguration>(p=>config);
serviceCollection.AddLogging(builder=>
{
builder.AddConfiguration(config.GetSection("Logging"));
builder.AddConsole();
builder.AddDebug();// 日志输出到VS调试信息框中
});
IServiceProvider service = serviceCollection.BuildServiceProvider();
var logger = service.GetService<ILogger<Program>();
// 如果想要输出ScopeId需要在配置文件中设置IncludeScopes属性为true,如下配置文件所示
// 配置如果发生修改,会同步热更新
using(logger.BeginSope("ScopeId:{scopeId}",Guid.NewGuid()))
{
logger.LogInformation("Inofo");
logger.logError("Error");
logger.LogTrace("Trace");
}
Console.ReadKey();
}
// 配置文件
{
"Logging":{
"LogLevel":{
"Default":"Debug",
"Microsoft":"Warning",
"Microsoft.Hosting.Lifetime":"Information"
}
},
"Console":{
"IncludeScopes":true,
"LogLevel":{
"Default":"Information",
"Program":"Trace",
"alogger":"Trace"
}
}
}
3 结构化日志组件Serilog:记录对查询分析友好的日志
3.1 结构化日志的好处
- 易于检索
- 易于分析统计
3.2 使用场景举例
- 实现日志告警
- 实现上下文的关联
- 实现与追踪系统集成
// asp web程序
//应用程序包 Serilog.AspNetCore
public class Program
{
// 读取配置
public static IConfiguration Configuration{get;} = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsetting.json",optional:false,reloadOnChange:true)
.AddJsonFile($"appsetting.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")??"Production"}.json",optional:false,reoladOnChange:true)
.AddEnvironmentVariable()
.Build();
public static int Main(string[] args)
{
// 将配置传递给Serilog的初始化过程
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(Configuration)
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.WriteTo.Console(new RenderedCompactJsonFormatter())
.WriteTo.File(formatter:new CompactJsonFormatter(),"logs\\myapp.txt",rollingInterval:RollingInterval.Day)
.CreateLogger();
try
{
Log.Infotmation("Start web host");
CreateHostBuilder(args).Builde().Run();
return0;
}catch(Exception ex)
{
Log.Fatal(ex,"Host terminated unexpectedly");
return 1;
}finally{
Log.CloseAndFlush();
}
}
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UserSerilog(dispose:true);
}
// 配置文件
{
"Logging":{
"LogLevel":{
"Default":"Debug",
"Microsoft":"Warning",
"Microsoft.Hosting.Lifetime":"Information"
}
},
"Serilog":{
"MinimumLevel":{
"Default":"Information",
"Override":{
"Microsoft":"Error",
"System":"Information"
}
}
},
"AlloweHost":"*"
}