18 | 日志框架:聊聊记日志的最佳姿势

新建控制台应用程序👉命名LoggingSimpleDemo
image.png

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;

namespace LoggingSimpleDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // 利用之前的方式加载json配置
            var builder = new ConfigurationBuilder();
            builder.AddJsonFile("appsetting.json", false, true);
            var config = builder.Build();

            IServiceCollection servicesCollection = new ServiceCollection();
            // 使用工厂模式将配置对象注册到容器管理
            servicesCollection.AddSingleton<IConfiguration>(p => config);

            servicesCollection.AddLogging(builder => 
            {
                builder.AddConfiguration(config.GetSection("Logging"));
                builder.AddConsole();
            });
        }
    }
}

前三行代码,我们使用了之前的方式,加载json配置

利用IServiceCollection servicesCollection = new ServiceCollection()构建了一个容器

使用工厂模式将配置注册到容器管理servicesCollection.AddSingleton<IConfiguration>(p => config),因为使用servicesCollection.AddSingleton<IConfiguration>(config)这种方式,将config实例直接注入进去,容器是不会帮助我们管理这个对象的生命周期的。

servicesCollection.AddLogging(builder => 
{
    builder.AddConfiguration(config);
    builder.AddConsole();
});

我们可以看看servicesCollection.AddLogging()方法的定义
image.png
AddLogging往容器里注册了几个关键的对象,一个ILoggerFactory,一个ILogger的泛型模板,一个是Logger的过滤配置,最后configure就是我们整个注入的委托。

接下来看看我们的配置文件appsettings.josn

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "Console": {
      "LogLevel": {
        "Default": "Information",
        "Program": "Trace",
        "alogger": "Trace"
      }
    }
  }
}

配置文件里面有一节Logging,里面定义了Log的级别。
这里面Key就代表了我们的Logger的名称,Value就代表了我们Logger的级别。
下面一节Console指我们针对Console的输出提供程序,配置的日志级别。

日志级别定义

namespace Microsoft.Extensions.Logging
{
    // Defines logging severity levels.
    public enum LogLevel
    {
        Trace,
        Debug,
        Information,
        Warning,
        Error,
        Critical,
        None
    }
}

None代表不输出任何的日志

接下来继续看代码

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;

namespace LoggingSimpleDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // 利用之前的方式加载json配置
            var builder = new ConfigurationBuilder();
            builder.AddJsonFile("appsettings.json", false, true);
            var config = builder.Build();

            IServiceCollection servicesCollection = new ServiceCollection();
            // 使用工厂模式将配置对象注册到容器管理
            servicesCollection.AddSingleton<IConfiguration>(p => config);

            servicesCollection.AddLogging(builder =>
            {
                builder.AddConfiguration(config.GetSection("Logging"));
                builder.AddConsole();
            });
            // 将我们的容器Build出来
            IServiceProvider services = servicesCollection.BuildServiceProvider();
            // 从容器中获取ILoggerFactory
            ILoggerFactory loggerFactory = services.GetService<ILoggerFactory>();

            var alogger = loggerFactory.CreateLogger("alogger");
            alogger.LogDebug(10086, "Begin");
            alogger.LogInformation("Hello World!");
            var ex = new Exception("There is a bug");
            alogger.LogError(ex, "Error!");

            Console.ReadKey();
        }
    }
}

利用IServiceProvider services = servicesCollection.BuildServiceProvider();将我们的容器Build出来

ILoggerFactory loggerFactory = services.GetService<ILoggerFactory>();ILoggerFactory对象取出来。
ILoggerFactory里面有连个方法,一个是ILogger CreateLogger(string categoryName)输入的是Logger的名称,输出是一个ILogger对象,这个ILogger就代表我们的日志记录器。第二个方式就是void AddProvider(ILoggerProvider provider),一般我们不使用,直接在AddLogging里去注册。

利用var alogger = loggerFactory.CreateLogger("alogger");获取一个ILogger对象,这个Logger对象的名字叫alogger。
运行输出:image.png
其中,alogger[10086]10086EventID,是针对每一个记录的位置,实践,我们可以为它分配一个事件ID
如果我们把日志级别设置为Information

"alogger": "Information"

运行输出:image.png
可以看到,DeBug级别的日志是没有输出的。

这是使用CreateLogger的的方式来方式指定了Logger的名称,实际上我们可以借助容器来构造我们的Logger
通常情况下,我们会定义自己的类,新建类OrderService

using Microsoft.Extensions.Logging;
using System;

namespace LoggingSimpleDemo
{
    public class OrderService
    {
        private readonly ILogger<OrderService> _logger;

        public OrderService(ILogger<OrderService> logger)
        {
            _logger = logger;
        }

        public void ShowLog()
        {
            _logger.LogInformation("OrderService.Log.ShowTime : {time}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
        }
    }
}

这里,我们使用了一个小技巧:使用模板去记录日志_logger.LogInformation("xxx : {time}", DateTime.Now)
这样相比较使用插值运算符$_logger.LogInformation($"xxx : {DateTime.Now}"),虽然最终输出结果是一样的,但是我们字符串拼接的时机是不同的。使用模板方法,是在我们决定要输出的时候,也就是在LogInformation内部Console提供程序要输出的时候,才去做这个拼接动作。而使用第二种办法其实是将我们的字符串拼接好以后,输入给了LogInformation这个参数。如果说我们把日志等级改成None的话,模板的拼接动作是不会执行的,第二种怎么也会执行拼接的操作,这样字符串拼接操作累计下来,造成的损耗是非常大的。

然后将我们的类注入到容器里。

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;

namespace LoggingSimpleDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // 利用之前的方式加载json配置
            var builder = new ConfigurationBuilder();
            builder.AddJsonFile("appsettings.json", false, true);
            var config = builder.Build();

            IServiceCollection servicesCollection = new ServiceCollection();
            // 使用工厂模式将配置对象注册到容器管理
            servicesCollection.AddSingleton<IConfiguration>(p => config);

            servicesCollection.AddLogging(builder =>
            {
                builder.AddConfiguration(config.GetSection("Logging"));
                builder.AddConsole();
            });

            servicesCollection.AddSingleton<OrderService>();
            // 将我们的容器Build出来
            IServiceProvider services = servicesCollection.BuildServiceProvider();

            var orderService = services.GetService<OrderService>();
            orderService.ShowLog();

            Console.ReadKey();
        }
    }
}

运行输出:image.png
这样使用的好处是,我们不需要定义名字,它会自动的把类型的名称作为记录器的名字,如上LoggingSimpleDemo.OrderService
也就意味着我们可以使用这个名称来设置日志级别。
配置文件添加:"LoggingSimpleDemo.OrderService": "none"

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "Console": {
      "LogLevel": {
        "Default": "Information",
        "Program": "Trace",
        "alogger": "Information",
        "LoggingSimpleDemo.OrderService": "none"
      }
    }
  }
}

运行输出:image.png
可以看到我们将日志级别设为None之后,控制台什么都没打印出来。

注意:记录日志的时候不要把敏感信息输出出来。

推荐这些文章:

<2022年4月18号>

复习
CSS层叠样式表
CSS样式特点
1.叠加
2.继承
 
CSS继承属性
Color
Font-family
Font-style
Font-size
Font-weight
List-style
Text-align
 
 
CSS引入方式
 
CSS选择器
标签,类名,id,子代,后代,交叉,群组,通用,伪类
div#app{}
div.content{}
 
css叠加
有优先级按照优先级顺序,平级就最终按照最终应用
 
定位:position
1.静态定位 static默认无定位
2.相对定位 relative
3.绝...

ASP.NET Core 6框架揭秘实例演示[18]:HttpClient处理管道

我们知道ASP.NET的核心就是由中间件组成的请求处理管道,HttpClient也采用了类似的设计。HttpClient管道由一组HttpMessageHandler对象构成,这些HttpMessageHandler相当于ASPNET的中间件。如下这些示例演示帮助我们更清楚地认识HttpMessageHandler处理管道。

我们知道ASP.NET的核心就是由中间件组成的请求处理管道,HttpClient也采用了类似的设计。HttpClient管道由一组HttpMessageHandler对象构成,这些HttpMessageHandler相当于ASPNET的中间件。如下这些示例演示...

ssm框架搭建(1) pom.xml部分

Pom中的dependencies

<!-- SpringMVC这个版本的包里会导入spring的包 maven导入后检查是否存在依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
<!-- Serv...

15 | 选项框架:服务组件集成配置的最佳实践

特性

支持单例模式读取配置
支持快照
支持配置变更通知
支持运行时动态修改选项值

设计原则

接口分离原则(LSP),我们的类不应该依赖它不适用的配置
关注点分离(SOC),不同组件、服务、类之间的配置不应相互依赖或耦合

建议

为我们的服务设计XXXOptions
使用IOptions<XXXOptions>、IOptionsSnapshot<XXXOptions>、IOptionsMonitor<XXXOptions>作为服务构造函数的参数

示例
新建Web应用程序👉命名OptionsDemo👉模板选择API👉新建Services文件夹👉新建O...

ASP.NET Core 6框架揭秘实例演示[15]:针对控制台的日志输出

针对控制台的ILogger实现类型为ConsoleLogger,对应的ILoggerProvider实现类型为ConsoleLoggerProvider,这两个类型都定义在 NuGet包“Microsoft.Extensions.Logging.Console”中。ConsoleLogger要将一条日志输出到控制台上,首选要解决的是格式化的问题,具体来说是如何将日志消息的内容荷载和元数据(类别、等级和事件ID等)格式化成呈现在控制台上的文本。针对日志的格式化由ConsoleFormatter对象来完成。

针对控制台的ILogger实现类型为ConsoleLogger,对应的ILog...

SpringBoot 开发项目日志

1、创建的父项目以及子项目
<packing>pom<packing> 项目里没有java代码,也不执行任何代码,只是为了聚合工程或传递依赖用的
 
2、子项目想要使用父项目中的依赖,在子项目中需要配置正确的父项目
<parent>
<!-- <artifactId>guli_parent</artifactId>-->
<!-- <groupId>com.luobin</groupId>-->
<!-- <ver...

使用类做为Dictionary<T,K>的key需什么要求?

问题
<P>&nbsp;</P>

最佳回答
没有要求

...

文章标题:18 | 日志框架:聊聊记日志的最佳姿势
文章链接:https://www.dianjilingqu.com/50987.html
本文章来源于网络,版权归原作者所有,如果本站文章侵犯了您的权益,请联系我们删除,联系邮箱:saisai#email.cn,感谢支持理解。
THE END
< <上一篇
下一篇>>