目录
介绍
背景
使用代码
基本的
文件中配置
跟踪(Trace)和跟踪源(TraceSource)
内置跟踪侦听器
LoggerTraceListener
Harmony中的Trace,TraceSource和Logger提供程序
兴趣点
本文介绍如何在.NET Core的组件设计中使用Trace和TraceSource。如果满足以下条件,这可能会很有用:
而目标读者是那些具有.NET Framework编程经验的程序员,此处讨论的知识是.NET Core 3.0和.NET Framework 2.0的最新知识,而.NET Framework 4.8是.NET Framework的最新主要版本。
在.NET Core中,默认的跟踪和日志记录已升级为ILogger
在.NET Core编程的复杂业务的应用程序中,我发现有很少的文章是在.NET Core中使用Trace和TraceSource的,几乎所有关于ILogger
这些代码示例包含多个项目,每个项目代表一个简单的场景和一个技术解决方案。
代码示例:ConsoleApp0
大概您已经阅读了.NET Core和ASP.NET Core中的日志记录。日志未包含在.NET Core运行时和启动逻辑中,也未包含在控制台应用程序的脚手架代码中。要使用日志记录,需要包Microsoft.Extensions.Logging。
但是,仅此程序包不足以记录到控制台。而是使用Microsoft.Extensions.Logging.Console:
并且此软件包包括Microsoft.Extensions.Logging。
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
namespace ConsoleApp0
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World! from console");
ILogger logger;
IFooService fooService;
using (var serviceProvider = new ServiceCollection()
.AddSingleton()
.AddLogging(cfg =>
{
cfg.AddConsole();
})
.BuildServiceProvider())
{
logger = serviceProvider.GetService>();
fooService = serviceProvider.GetService();
}
logger.LogInformation("logger information");
logger.LogWarning("logger warning");
fooService.DoWork();
}
}
public interface IFooService
{
void DoWork();
}
public class FooService : IFooService
{
private readonly ILogger logger;
public FooService(ILogger logger)
{
this.logger = logger;
}
public void DoWork()
{
logger.LogInformation("Doing work.");
logger.LogWarning("Something warning");
logger.LogCritical("Something critical");
}
}
}
这是执行效果:
并且您可以通过重载AddConsole()来在代码中进行进一步的配置。
.AddLogging(cfg => { cfg.AddConsole(cfg=> cfg.DisableColors=true); })
.BuildServiceProvider())
代码示例:ConsoleApp1
您可能更喜欢通过外部配置文件配置组件和服务,并且通常使用appsettings.json。因此,需要包Microsoft.Extensions.Configuration.Json。
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false, true)
.Build();
ILogger logger;
IFooService fooService;
using (var serviceProvider = new ServiceCollection()// thanks to
// https://thecodebuzz.com/logging-in-net-core-console-application/
.AddSingleton()
.AddLogging(cfg =>
{
cfg.AddConfiguration(configuration.GetSection("Logging"));
cfg.AddConsole();
})
.BuildServiceProvider())
{
logger = serviceProvider.GetService>();
//logger = serviceProvider.GetService().
CreateLogger(); // Factory first. This works too.
fooService = serviceProvider.GetService();
}
而appsettings.json内容如下:
{
"Logging": {
"Console": {
"disableColors": false
},
"LogLevel": {
"Default": "Information",
"Microsoft": "Information",
"ConsoleApp1.FooService": "Warning",
"ConsoleApp1.Program": "Debug"
}
}
}
提示
在阅读了appsettings.json中的Logging部分之后,通过DI .NET Core运行时配置控制台记录器提供程序以及诸如“Microsoft”和“ConsoleApp1.FooService”之类的记录器。
System.Diagnostics.Trace和System.Diagnostics.TraceSource设计用于分离跟踪和日志记录,并且通过附加的跟踪侦听器实现日志记录。
代码示例:ConsoleAppTraceListener
.NET Framework上的许多TraceListener派生类.NET Core上可用,但是像IisTraceListener这样的类在.NET Core 上不可用。
在.NET Framework上,应用程序可以通过app.config初始化Trace和TraceSource,并实例化跟踪侦听器,app.config在执行应用程序代码的第一行之前加载。
在.NET Core上,您仍可以使用各种跟踪侦听器,例如ConsoleTraceListener,因为.NET Core默认情况下不会加载配置文件,并且内置配置不关心跟踪侦听器。
using (var listener = new TextWriterTraceListener("c:\\temp\\mylog.txt"))
using (var consoleListener = new ConsoleTraceListener())
{
Trace.Listeners.Add(listener);
Trace.Listeners.Add(consoleListener);
因此,您必须实例化跟踪侦听器,并在应用程序startup代码中进行初始化Trace和TraceSources对象。不错,但是事情还在继续,有越来越多的第三方组件可以与ILogger
代码示例:ConsoleAppTrace
由于Trace和TraceSource只有侦听器与日志连接,因此这里的LoggerTraceListener侦听跟踪并写入ILogger
public class LoggerTraceListener : TraceListener
{
private readonly ILogger logger;
public LoggerTraceListener(ILogger logger)
{
this.logger = logger;
}
public override void Write(string message)
{
logger.LogInformation(message);
}
public override void WriteLine(string message)
{
logger.LogInformation(message);
}
public override void WriteLine(string message, string category)
{
logger.LogInformation(category + ": " + message);
}
public override void TraceEvent
(TraceEventCache eventCache, string source, TraceEventType eventType, int id)
{
switch (eventType)
{
case TraceEventType.Critical:
logger.LogCritical(id, source);
break;
case TraceEventType.Error:
logger.LogError(id, source);
break;
case TraceEventType.Warning:
logger.LogWarning(id, source);
break;
case TraceEventType.Information:
logger.LogInformation(id, source);
break;
case TraceEventType.Verbose:
logger.LogTrace(id, source);
break;
case TraceEventType.Start:
logger.LogInformation(id, "Start: " + source);
break;
case TraceEventType.Stop:
logger.LogInformation(id, "Stop: " + source);
break;
case TraceEventType.Suspend:
logger.LogInformation(id, "Suspend: " + source);
break;
case TraceEventType.Resume:
logger.LogInformation(id, "Resume: " + source);
break;
case TraceEventType.Transfer:
logger.LogInformation(id, "Transfer: " + source);
break;
default:
throw new InvalidOperationException("Impossible");
}
}
应用程序启动(startup):
ILogger logger;
using (var serviceProvider = new ServiceCollection()
.AddLogging(cfg =>
{
cfg.AddConfiguration(configuration.GetSection("Logging"));
cfg.AddConsole();
})
.BuildServiceProvider())
{
logger = serviceProvider.GetService>();
}
logger.LogInformation("logger information");
logger.LogWarning("logger warning");
using (var listener = new LoggerTraceListener(logger))
{
System.Diagnostics.Trace.Listeners.Add(listener);
TraceSources.Instance.InitLoggerTraceListener(listener);
TraceLover.DoSomething();
TraceSourceLover.DoSomething();
}
现在,Trace和TraceSource的日志介质是由哪些日志提供程序附加到ILogger决定的。
代码示例:ConsoleappSeriLog
微软在.NET Core中开发了很少的具体记录器提供程序,这很可能是根据业务愿景而设计的。周围有很多第三方记录器提供程序:
有一篇很好的文章比较了这三个:
整体上我同意Serilog是最好的。
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false, true)
.Build();
Serilog.Log.Logger = new Serilog.LoggerConfiguration()
.Enrich.FromLogContext()
//.WriteTo.Console() I prefer plugging through the config file
.ReadFrom.Configuration(configuration)
.CreateLogger();
Microsoft.Extensions.Logging.ILogger logger;
IFooService fooService;
var services = new ServiceCollection();
services.AddLogging(configure => configure.AddSerilog());
using (var serviceProvider = services
.AddSingleton()
.BuildServiceProvider())
{
logger = serviceProvider.GetService>();
fooService = serviceProvider.GetService();
}
try
{
Log.Information("Starting up");
logger.LogInformation("logger information");
logger.LogWarning("logger warning");
fooService.DoWork();
using (var listener = new LoggerTraceListener(logger))
{
System.Diagnostics.Trace.Listeners.Add(listener);
TraceSources.Instance.InitLoggerTraceListener(listener);
TraceLover.DoSomething();
TraceSourceLover.DoSomething();
}
}
catch (Exception ex)
{
Log.Fatal(ex, "Application start-up failed");
}
finally
{
Log.CloseAndFlush();
}
而appsettings.json内容如下:
{
"TraceSource": {
"WebApi": {
"SourceLevels": "Information"
},
"HouseKeeping": { "SourceLevels": "Warning" },
"DbAudit": {
"SourceLevels": "Warning"
}
},
"Serilog": {
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Information",
"System": "Warning",
"ConsoleApp1.FooService": "Warning",
"ConsoleApp1.Program": "Information"
}
},
"WriteTo": [
{
"Name": "Console"
},
{
"Name": "File",
"Args": {
"path": "%PROGRAMDATA%/my/logs/CloudPosApi_Test.log",
"outputTemplate": "{Timestamp:MM-dd HH:mm:ss.fff zzz}
[{Level}] {ThreadId} {Message}{NewLine}{Exception}",
"rollingInterval": "Day"
}
}
]
}
}
在.NET Framework上,运行时将在执行应用程序代码的第一行之前加载app.config并将设置应用于某些内置组件。默认情况下,其他组件(例如SMTPClient和System.Diagnostics)会读取app.config。
在.NET Core上,应用程序程序员负责以代码形式或通过加载配置文件进行配置。
即使我已经为.NET Core编写了几年的组件,但我刚刚开始开发复杂的.NET Core商业应用程序已有几个月了,而我绝不是精通.NET Core编程的人。请指出我在本文中可能犯的一些错误。在代码示例中,有一个有关TraceSourceLoggerProvider的示例,尚不可用。令人惊讶的是,截至2020年1月8日,TraceSourceLoggerProvider在346个Google搜索结果(实际上少于60个)中,似乎没有例子。我有一个问题,你知道如何使用TraceSourceLoggerProvider吗?