zoukankan      html  css  js  c++  java
  • 在 .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默认情况下不会加载配置文件,而且内置配置不会关心跟踪监听器。

    1
    2
    3
    4
    5
    6
    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

    出处 :https://www.cnblogs.com/hhhnicvscs/p/14365192.html

    您的资助是我最大的动力!
    金额随意,欢迎来赏!
    款后有任何问题请给我留言。

    如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的推荐按钮。
    如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的关注我。(●'◡'●)

    如果你觉得本篇文章对你有所帮助,请给予我更多的鼓励,求打             付款后有任何问题请给我留言!!!

    因为,我的写作热情也离不开您的肯定支持,感谢您的阅读,我是【Jack_孟】!

  • 相关阅读:
    HDU 2112 HDU Today,最短路径算法,Dijkstra
    最小生成树,POJ和HDU几道题目的解题报告(基于自己写的模板)
    图基本算法 最小生成树 Prim算法(邻接表/邻接矩阵+优先队列STL)
    合并相同值得单元格(纵向)
    request.startAsync()不支持异步操作
    DIV强制不换行
    兼容各浏览器的css背景图片拉伸代码
    程序猿之八荣八耻
    使用JEECG过程中的问题汇总(持续更新)
    Firefox的缓存问题
  • 原文地址:https://www.cnblogs.com/mq0036/p/14367280.html
Copyright © 2011-2022 走看看