在 .NET Core Logging中使用 Trace和TraceSource
本文介绍了在.NET Core中如何在组件设计中使用Trace和TraceSource。
在以下方面会提供一些帮助:
1.你已经为.NET Framework和.NET Core / .NET Standard构建了组件,而且你更喜欢保留Trace和TraceSource。
2.你有使用跟踪和TraceSource的第三方组件。
3.你正在将一个复杂的.NET Framework应用程序迁移到.NET Core,并且目前还不想更改跟踪和日志记录设计。
4.你将保持跟踪和日志记录的分离和易用。
5.可部署的程序不会托管在Linux中。
目标读者是那些在.NET Framework编程方面有丰富经验的程序员,这里讨论的知识是 .NET Core和.NET Framework 。
在.NET生态系统中使用特定的技术堆栈会产生一些困惑,因为有很多选择,比如应该使用哪种类型的运行时?在这篇文章中,我们将试图把这些要点都说清楚。
在.NET Core中,默认的跟踪和日志被升级为 ILogger<T>,相应的日志记录器对象被通过 .NET Core的依赖注入实例化。ILogger<T> 可以与System.Diagnostics.TraceSource比较。ILoggerProvider对象可以与System.Diagnostics.TraceListener比较。
在.NET Core上为一个复杂的应用程序编程期间,我发现关于在.NET Core中使用Trace和TraceSource的文章很少,而几乎所有的文章和示例都是关于 ILogger<T>的。我可以通过谷歌找到如何使用ILogger并立即注入Program,Startup和控制器,而我一直在寻找例子使ILogger组件远离项目。
Logger
接下来的代码示例包含多个项目,每个项目代表一个简单的场景和一个技术解决方案。
日志记录不包含在.NET Core运行时和启动逻辑中,也不包含在控制台应用程序的脚手架代码中。为了使用日志,Microsoft.Extensions.Logging是必不可少的。
但是,仅此包不足以将日志记录到控制台。相反,使用Microsoft.Extensions.Logging.Console:

这个package包括Microsoft.Extensions.Logging。此外,通常你不会在代码中切换编码,而是在配置文件中,通常在.NET Core中,使用的是JSON配置文件,因此你需要Microsoft.Extensions.Configuration.Json。
LoggerFactory
代码示例:ConsoleAppLoggerFactory
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; namespace ConsoleAppLoggerDemo
{
class Program
{
static void Main(string[] args)
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false, true)
.Build(); using var loggerFactory = LoggerFactory.Create(
builder =>
{
builder.AddConfiguration(configuration.GetSection("Logging"));
builder.AddConsole();
}
); var logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("1111logger information"); //settings in appsettings.json filters this out
logger.LogWarning("2222logger warning"); var fooLogger = loggerFactory.CreateLogger<FooService>();
IFooService fooService = new FooService(fooLogger);
fooService.DoWork();
}
} public interface IFooService
{
void DoWork();
} public class FooService : IFooService
{
private readonly ILogger logger; public FooService(ILogger<FooService> logger)
{
this.logger = logger;
} public void DoWork()
{
logger.LogInformation("3333Doing work.");
logger.LogWarning("4444Something warning");
logger.LogCritical("5555Something critical");
}
}
}
appsettings.json
{
"Logging": {
"Console": {
"disableColors": false
},
"LogLevel": {
"Default": "Information",
"Microsoft": "Information",
"ConsoleAppLoggerDemo.FooService": "Warning",
"ConsoleAppLoggerDemo.Program": "warning"
}
}
}
这对于非常简单的场景来说已经足够好了,但是,在复杂的应用程序中,你可能想要利用.net Core中内置的依赖注入,如下所述。
向ServiceCollection注入Logger
代码示例:ConsoleAppAddLogging
在ServiceCollection中构建并注册了ILoggerFactory的一个实例,因此该工厂随后通过以下两种方式创建 ILogger<Program>:
serviceProvider.GetService<ILoggerFactory>().CreateLogger<Program>();
或者
serviceProvider.GetService<ILogger<Program>>();
当FooService通过依赖注入实例化时,定义的ILogger<FooService>被实例化和注入。
using Microsoft.Extensions.Logging;
using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleAppLoggerDemo
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World! from console");
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false, true)
.Build();
using var serviceProvider = new ServiceCollection()
.AddSingleton<IFooService, FooService>()
.AddLogging(builder =>
{
builder.AddConfiguration(configuration.GetSection("Logging"));
builder.AddConsole();
})
.BuildServiceProvider();
ILogger<Program> logger = serviceProvider.GetService<ILogger<Program>>();
//logger = serviceProvider.GetService<ILoggerFactory>().CreateLogger<Program>(); // Factory first. This works too.
IFooService fooService = serviceProvider.GetService<IFooService>();
logger.LogInformation("1111logger information");
logger.LogWarning("2222logger warning");
fooService.DoWork();
}
}
public interface IFooService
...
}
Trace 和 TraceSource
System.Diagnostics.Trace 和 System.Diagnostics.TraceSource是为分离跟踪和日志而设计的,通过附加的跟踪监听器实现日志记录。
代码示例:ConsoleAppTraceListener
. net Framework中许多TraceListener派生类在. net Core上都是可用的,但是像IisTraceListener这样的东西在. net Core上是不可用的。
在. net Framework中,应用程序可以初始化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);
}
因此,你必须在应用程序启动代码中实例化跟踪侦听器并初始化Trace和TraceSources对象。还不算太坏,不过事情会继续发展,越来越多的第三方组件可能会使用ILogger<T>接口用于跟踪和日志记录。考虑到各种因素和权衡,最好在TraceSource和ILogger<T>之间建立一座桥梁,这样使用Trace和TraceSource的遗留组件可以向ILogger<T>发送跟踪消息。
LoggerTraceListener
这是一个辅助TraceListener,可以将Trace和TraceSource连接到ILogger。
代码示例:ConsoleAppTrace
由于Trace和TraceSource只有侦听器与日志记录接口,因此这里有LoggerTraceListener来侦听跟踪并写入ILogger<T>,它最终将跟踪发送给记录器提供程序。
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:
using var serviceProvider = new ServiceCollection()
.AddSingleton<IFooService, FooService>()
.AddLogging(builder =>
{
builder.AddConfiguration(configuration.GetSection("Logging"));
builder.AddConsole();
})
.BuildServiceProvider();
ILogger<Program> logger = serviceProvider.GetService<ILogger<Program>>();
IFooService fooService = serviceProvider.GetService<IFooService>();
logger.LogInformation("1111logger information");
logger.LogWarning("2222logger warning");
fooService.DoWork();
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中开发了一些具体的日志提供程序,这可能是基于业务愿景和设计。
有相当多的第三方日志提供商:
· NLog
· Log4net
· Serilog
我认为Serilog 是最好的。
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false, true)
.Build();
Serilog.Log.Logger = new Serilog.LoggerConfiguration()
.Enrich.FromLogContext()
.ReadFrom.Configuration(configuration)
.CreateLogger();
using var serviceProvider = new ServiceCollection()
.AddLogging(builder => builder.AddSerilog())
.AddSingleton<IFooService, FooService>()
.BuildServiceProvider();
var logger = serviceProvider.GetService<ILogger<Program>>();
var fooService = serviceProvider.GetService<IFooService>();
try
{
Log.Information("Starting up");
logger.LogInformation("1111logger information");
logger.LogWarning("2222logger 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",
"ConsoleAppLoggerDemo.FooService": "Warning",
"ConsoleAppLoggerDemo.Program": "Warning"
}
},
"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上,在代码中或通过加载配置文件进行配置是应用程序程序员的职责。
欢迎关注我的公众号——码农译站,如果你有喜欢的外文技术文章,可以通过公众号留言推荐给我。

原文链接:https://www.codeproject.com/Articles/5255953/Use-Trace-and-TraceSource-in-NET-Core-Logging
在 .NET Core Logging中使用 Trace和TraceSource的更多相关文章
- Asp.net core logging 日志
1 基本概念 Dotnet core 一个重要的特征是 Dependency injection ,中文一般是依赖注入,可以简单理解为一个集合,在应用程序启动时,定义各种具体的实现类型并将其放到集合中 ...
- .Net Core 项目中的包引用探索(使用VSCode)
本文组织有点乱,先说结论吧: 1 在 project.json 文件中声明包引用. 而不是像以前那样可以直接引用 dll. 2 使用 dotnet restore 命令后,nuget 会把声明的依赖项 ...
- 通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[下]:管道是如何构建起来的?
在<中篇>中,我们对管道的构成以及它对请求的处理流程进行了详细介绍,接下来我们需要了解的是这样一个管道是如何被构建起来的.总的来说,管道由一个服务器和一个HttpApplication构成 ...
- ASP.NET Core MVC 中的 [Controller] 和 [NonController]
前言 我们知道,在 MVC 应用程序中,有一部分约定的内容.其中关于 Controller 的约定是这样的. 每个 Controller 类的名字以 Controller 结尾,并且放置在 Contr ...
- Core管道中的处理流程3
通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[下]:管道是如何构建起来的? 在<中篇>中,我们对管道的构成以及它对请求的处理流程进行了详细介绍,接下 ...
- 如何在ASP.NET Core应用中实现与第三方IoC/DI框架的整合?
我们知道整个ASP.NET Core建立在以ServiceCollection/ServiceProvider为核心的DI框架上,它甚至提供了扩展点使我们可以与第三方DI框架进行整合.对此比较了解的读 ...
- ASP.NET Core MVC 中设置全局异常处理方式
在asp.net core mvc中,如果有未处理的异常发生后,会返回http500错误,对于最终用户来说,显然不是特别友好.那如何对于这些未处理的异常显示统一的错误提示页面呢? 在asp.net c ...
- ASP.NET Core中的缓存[1]:如何在一个ASP.NET Core应用中使用缓存
.NET Core针对缓存提供了很好的支持 ,我们不仅可以选择将数据缓存在应用进程自身的内存中,还可以采用分布式的形式将缓存数据存储在一个“中心数据库”中.对于分布式缓存,.NET Core提供了针对 ...
- 006.Adding a controller to a ASP.NET Core MVC app with Visual Studio -- 【在asp.net core mvc 中添加一个控制器】
Adding a controller to a ASP.NET Core MVC app with Visual Studio 在asp.net core mvc 中添加一个控制器 2017-2-2 ...
随机推荐
- 辅助调用函数【call,apply,bind】
函数也是对象,每个函数都有自己的方法. e.g. var jane = { name:'Jane', sayHelloTo:function(name) { 'use strict'; console ...
- 风炫安全WEB安全学习第十八节课 使用SQLMAP自动化注入(二)
风炫安全WEB安全学习第十八节课 使用SQLMAP自动化注入(二) –is-dba 当前用户权限(是否为root权限) –dbs 所有数据库 –current-db 网站当前数据库 –users 所有 ...
- day119:MoFang:宠物的状态改动&宠物粮道具的使用&宠物死亡处理
目录 1.宠物的状态改动 2.宠物粮道具的使用 3.宠物死亡处理 1.宠物的状态改动 1.在setting表中为每个宠物配置生命周期时间 因为宠物有多个,每个宠物会有不同的初始生命的饥饿时间,所以我们 ...
- day121:MoFang:植物的状态改动(幼苗→成长期)&植物的浇水功能
目录 1.当果树种植以后在celery的异步任务中调整浇水的状态 2.客户端通过倒计时判断时间,显示浇水道具 3.客户端判断当前种植物状态控制图标的显示和隐藏 4.当用户单击浇水图标, 则根据当前果树 ...
- 详解线程池的作用及Java中如何使用线程池
服务端应用程序(如数据库和 Web 服务器)需要处理来自客户端的高并发.耗时较短的请求任务,所以频繁的创建处理这些请求的所需要的线程就是一个非常消耗资源的操作.常规的方法是针对一个新的请求创建一个新线 ...
- 【Linux】centos7中 root家目录中perl5文件夹无法删除问题解决
由于新项目上线,安装了一些perl的一些包 但是发现,在/root下有一个perl5/的文件夹,删除后,重新登录又会出现,很是烦人,而且他还没有内容,就是一个空文件 那么着手搞掉他 环境:centos ...
- 【Oracle】 并行查询
所谓并行执行,是指能够将一个大型串行任务(任何DML,一般的DDL)物理的划分为叫多个小的部分,这些较小的部分可以同时得到处理.何时使用并行执行:1.必须有一个非常大的任务 2.必须有充足的资源(CP ...
- 【Oracle】常见等待事件处理
1.查看数据库中需要关注的等待事件: select sw.seq#,sw.sid||','||s.serial# sids,s.username,sw.event,sw.P1,sw.p2,sw.p3, ...
- 【Oracle】win7安装报错
在WIN7上安装oracle 10g时,提示如下信息: 正在检查操作系统要求... 要求的结果: 5.0,5.1,5.2,6.0 之一 实际结果: 6.1 检查完成.此次检查的总体结果为: 失败 &l ...
- P2327 [SCOI2005]扫雷(递推)
题目链接: https://www.luogu.org/problemnew/show/P2327 题目描述 相信大家都玩过扫雷的游戏.那是在一个$n*m$的矩阵里面有一些雷,要你根据一些信息找出雷来 ...