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

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

[S901]SimpleConsoleFormatter格式化器(源代码)
[S902]SystemdConsoleFormatter格式化器(源代码)
[S903]JsonConsoleFormatter格式化器(源代码)
[S904]改变ConsoleLogger的标准输出和错误输出(源代码)
[S905]自定义控制台日志的格式化器(源代码)

[S901]SimpleConsoleFormatter格式化器

下面的代码演示了如何使用SimpleConsoleFormatter来格式化控制台输出的日志。我们利用命令行参数控制是否采用单行文本输出和着色方案。在调用ILoggingBuiler接口的AddConsole扩展方法对ConsoleLoggerProvider对象进行注册之后,我们接着调用它的AddSimpleConsole扩展方法将SimpleConsoleFormatter作为格式化器,并利用作为参数的Action<SimpleConsoleFormatterOptions>委托根据命令行参数的对SimpleConsoleFormatterOptions配置选项进行了相应设置(S901)。

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;var configuration = new ConfigurationBuilder().AddCommandLine(args).Build();
var singleLine = configuration.GetSection("singleLine").Get<bool>();
var colorBebavior = configuration.GetSection("color").Get<LoggerColorBehavior>();var logger = LoggerFactory.Create(builder => builder.AddConsole().AddSimpleConsole(options =>{options.SingleLine = singleLine;options.ColorBehavior = colorBebavior;})).CreateLogger<Program>();
var levels = (LogLevel[])Enum.GetValues(typeof(LogLevel));
levels = levels.Where(it => it != LogLevel.None).ToArray();
var eventId = 1;
Array.ForEach(levels,level => logger.Log(level, eventId++, "This is a/an {0} log message.", level));
Console.Read();

我们已命名行的方式三次启动演示程序,并利用参数(singleLine=true, color=Disabled)控制对应的格式化行为。从图1所示的结果可以看出日志输出的格式是与我们指定的命名行参数是匹配的。

92118a5ddc21306b087302c84a39f18e.png
图1 基于SimpleConsoleFormatter的格式化

[S902]SystemdConsoleFormatter格式化器

我们使用如下这个实例来演示针对SystemdConsoleFormatter的格式化。如代码片段所示,我们利用命令行参数“includeScopes”来决定是否支持日志范围。在调用ILoggingBuilder接口的AddConsole扩展方法ConsoleLoggerProvider对象进行注册之后,我们接着调用了该接口的AddSystemdConsole扩展方法对SystemdConsoleFormatter及其配置选项进行注册。为了输出所有等级的日志,我们将最低日志等级设置为Trace。为了体现针对异常信息的输出,我们在调用Log方法时传入了一个Exception对象。

using Microsoft.Extensions.Logging;var includeScopes = args.Contains("includeScopes");
var logger = LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.Trace).AddConsole().AddSystemdConsole(options => options.IncludeScopes = includeScopes)).CreateLogger<Program>();
var levels = (LogLevel[])Enum.GetValues(typeof(LogLevel));
levels = levels.Where(it => it != LogLevel.None).ToArray();
var eventId = 1;
Array.ForEach(levels, Log);
Console.Read();void Log(LogLevel logLevel)
{using (logger.BeginScope("Foo")){using (logger.BeginScope("Bar")){using (logger.BeginScope("Baz")){logger.Log(logLevel, eventId++, new Exception("Error..."), "This is a/an {0} log message.", logLevel);}}}
}

我们采用命令行的方式两次启动演示程序,第一次采用默认配置,第二次利用命令行参数“includeScopes”开启针对日志范围的支持。从图2所示的输出结果可以看出六条日志均以单条文本的形式输出到控制台上,对应的日志等级(Trace、Debug、Information、Warning、Error和Critical)均被转换成Syslog日志等级(7、7、6、4、3和2)。

4bc53e42461e4d721ac31dc6f79c9521.png
图2 基于SystemdConsoleFormatter的格式化

[S903]JsonConsoleFormatter格式化器

我们对上面的演示程序略加改动,将针对ILoggingBuilder接口的AddSystemdConsole扩展方法的调用替换成调用AddJsonConsole扩展方法,后者帮助我们完成针对JsonConsoleFormatter及其配置选项的注册。为了减少控制台上输出的内容,我们移除了针对最低日志等级的设置。

using Microsoft.Extensions.Logging;var includeScopes = args.Contains("includeScopes");var logger = LoggerFactory.Create(builder => builder.AddConsole().AddJsonConsole(options => options.IncludeScopes = includeScopes)).CreateLogger<Program>();
var levels = (LogLevel[])Enum.GetValues(typeof(LogLevel));
levels = levels.Where(it => it != LogLevel.None).ToArray();
var eventId = 1;
Array.ForEach(levels, Log);Console.Read();void Log(LogLevel logLevel)
{using (logger.BeginScope("Foo")){using (logger.BeginScope("Bar")){using (logger.BeginScope("Baz")){logger.Log(logLevel, eventId++, new Exception("Error..."), "This is a/an {0} log message.", logLevel);}}}
}

我们依然采用上面的方式两次执行改动后的程序。在默认以及开启日志范围的情况下,控制台分别具有图3所示的输出。可以看出输出的内容不仅包含参数填充生成完整内容,还包含原始的模板。日志范围的路径是以数组的方式输出的。

8cc9e82f3b73e4f92b11dfd3405bc9bb.png
图3 基于JsonConsoleFormatter的格式化

[S904]改变ConsoleLogger的标准输出和错误输出

ConsoleLogger具有“标准输出”和“错误输出”两个输出渠道,分别对应着Console类型的静态属性Out和Error返回的TextWriter对象。对于不高于LogToStandardErrorThreshold设定等级的日志会采用标准输出,高于或者等于该等级的日志则采用错误输出。由于LogToStandardErrorThreshold属性的默认值为None,所以任何等级的日志都被写入标准输出。如下的代码片段演示了如何通过设置这个属性改变不同等级日志的输出渠道。

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;using (var @out = new StreamWriter("out.log") { AutoFlush = true })
using (var error = new StreamWriter("error.log") { AutoFlush = true })
{Console.SetOut(@out);Console.SetError(error);var logger = LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.Trace).AddConsole(options =>options.LogToStandardErrorThreshold = LogLevel.Error).AddSimpleConsole(options =>options.ColorBehavior = LoggerColorBehavior.Disabled)).CreateLogger<Program>();var levels = (LogLevel[])Enum.GetValues(typeof(LogLevel));levels = levels.Where(it => it != LogLevel.None).ToArray();var eventId = 1;Array.ForEach(levels, Log);Console.Read();void Log(LogLevel logLevel) => logger.Log(logLevel, eventId++, "This is a/an {0} log message.", logLevel);
}

如上面的代码片段所示,我们创建了两个针对本地文件(out.log和error.log)的StreamWriter,并通过调用Console类型的静态方法SetOut和SetError将其设置为控制台的标准输出和错误输出。在针对ILogingBuilder接口的AddConsole扩展方法调用中,我们将配置选项ConsoleLoggerOptions的LogToStandardErrorThreshold属性设置为Error,并调用SetMinimumLevel方法将最低日志等级设置为Trace。我们还调用AddSimpleConsole扩展方法禁用作色方案。当程序运行之后,针对具有不同等级的六条日志,四条不高于Error的日志被输出到如图4所示的out.log中,另外两条则作为错误日志被输出到error.log中,控制台上将不会有任何输出内容。

bc1de2894aac032d39e22634149e72f7.png
图4 标准输入和错误输出

[S905]自定义控制台日志的格式化器

为了能够更加灵活地控制日志在控制台上的输出格式,我们自定义了如下这个格式化器类型。如代码片段所示,这个名为TemplatedConsoleFormatter会按照指定的模板来格式化输出的日志内容,它使用的配置选项类型为TemplatedConsoleFormatterOptions,日志格式模板就体现在它的Template属性上。

public class TemplatedConsoleFormatter : ConsoleFormatter
{private readonly bool _includeScopes;private readonly string _tempalte;public TemplatedConsoleFormatter(IOptions<TemplatedConsoleFormatterOptions> options): base("templated"){_includeScopes = options.Value.IncludeScopes;_tempalte = options.Value?.Template?? "[{LogLevel}]{Category}/{EventId}:{Message}\n{Scopes}\n";}public override void Write<TState>(in LogEntry<TState> logEntry, IExternalScopeProvider scopeProvider, TextWriter textWriter){var builder = new StringBuilder(_tempalte);builder.Replace("{Category}", logEntry.Category);builder.Replace("{EventId}", logEntry.EventId.ToString());builder.Replace("{LogLevel}", logEntry.LogLevel.ToString());builder.Replace("{Message}", logEntry.Formatter?.Invoke(logEntry.State, logEntry.Exception));if (_includeScopes && scopeProvider != null){var buidler2 = new StringBuilder();var writer = new StringWriter(buidler2);scopeProvider.ForEachScope(WriteScope, writer);void WriteScope(object? scope, StringWriter state){writer.Write("=>" + scope);}builder.Replace("{Scopes}", buidler2.ToString());}textWriter.Write(builder);}
}public class TemplatedConsoleFormatterOptions: ConsoleFormatterOptions
{public string? Template { get; set; }
}

我们将TemplatedConsoleFormatter的别名指定为“templated”,格式模板利用占位符“{Category}”、“{EventId}”、“{LogLevel}”、“{Message}”和“{Scopes}”表示日志类别、事件ID、等级、消息和范围信息。“[{LogLevel}]{Category}/{EventId}:{Message}\n{Scopes}\n”是我们提供的默认模板。现在我们采用如下这个名为appsettings.json的JSON文件来提供所有的配置。

{"Logging": {"Console": {"FormatterName": "templated","LogToStandardErrorThreshold": "Error","FormatterOptions": {"IncludeScopes": true,"UseUtcTimestamp": true,"Template": "[{LogLevel}]{Category}:{Message}\n"}}}
}

如上面的代码片段所示,我们将控制台日志输出的相关设置定义在“Logging:Console”配置节中,并定义了格式化器名称(“templated”)、错误日志最低等级(“Error”)。“FormatterOptions”配置节的内容将最终绑定到TemplatedConsoleFormatterOptions配置选项上。在如下所示的演示程序中,我们加载这个配置文件并提取代表“Logging”配置节的IConfigguration对象,我们将这个对象作为参数调用ILoggingBuilder接口的AddConfiguration扩展方法进行了注册。

using App;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;var logger = LoggerFactory.Create(Configure).CreateLogger<Program>();var levels = (LogLevel[])Enum.GetValues(typeof(LogLevel));
levels = levels.Where(it => it != LogLevel.None).ToArray();
var eventId = 1;
Array.ForEach(levels, Log);
Console.Read();void Configure(ILoggingBuilder builder)
{var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build().GetSection("Logging");builder.AddConfiguration(configuration).AddConsole().AddConsoleFormatter<TemplatedConsoleFormatter,TemplatedConsoleFormatterOptions>();
}void Log(LogLevel logLevel) => logger.Log(logLevel, eventId++, "This is a/an {0} log message.", logLevel);

在调用ILoggingBuilder接口的AddConsole扩展方法对ConsoleLoggerProvider进行注册之后,我们调用了它的AddConsoleFormatter<TemplatedConsoleFormatter,TemplatedConsoleFormatterOptions>方法,该方法将利用配置来绑定注册格式化器对应的TemplatedConsoleFormatterOptions配置选项。演示程序启动之后,每一条日志将按照配置中提供的模板进行格式化,并以图5所示的形式输出到控制台上。

740e351473e60ad61f9e838b1a1fe6bb.png
图5 基于TemplatedConsoleFormatter的格式化

《ASP.NET Core 6框架揭秘》实例演示[01]:编程初体验
《ASP.NET Core 6框架揭秘》实例演示[02]:各种形式的API开发
《ASP.NET Core 6框架揭秘》实例演示[03]:Dapr初体验
《ASP.NET Core 6框架揭秘》实例演示[04]:自定义依赖注入框架
《ASP.NET Core 6框架揭秘》实例演示[05]:依赖注入基本编程模式
《ASP.NET Core 6框架揭秘》实例演示[06]:依赖注入框架设计细节
《ASP.NET Core 6框架揭秘》实例演示[07]:文件系统
《ASP.NET Core 6框架揭秘》实例演示[08]:配置的基本编程模式
《ASP.NET Core 6框架揭秘》实例演示[09]:将配置绑定为对象
《ASP.NET Core 6框架揭秘》实例演示[10]:Options基本编程模式
《ASP.NET Core 6框架揭秘》实例演示[11]:诊断跟踪的几种基本编程方式 
《ASP.NET Core 6框架揭秘》实例演示[13]:日志的基本编程模式
《ASP.NET Core 6框架揭秘》实例演示[14]:日志的进阶用法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/283225.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《HeadFirst Python》第一章学习笔记

对于Python初学者来说&#xff0c;舍得强烈推荐从《HeadFirst Python》开始读起&#xff0c;这本书当真做到了深入浅出&#xff0c;HeadFirst系列&#xff0c;本身亦是品质的保证。这本书舍得已在《Python起步&#xff1a;写给零编程基础的童鞋》一文中提供了下载。为了方便大家…

Oracle-13:Oracle中的表分区

------------吾亦无他,唯手熟尔&#xff0c;谦卑若愚&#xff0c;好学若饥------------- 本篇博客记录了表分区 表分区的含义&#xff1a; 典型的拿空间换时间的案例&#xff01; 表分区对一张表进行分区&#xff0c;分区之后表中的数据存在相对应的分区内&#xff08;可以是不…

js控制图像等比例缩放

<!DOCTYPE html> <html> <head><title>图片内部放大效果</title> <meta charset"utf-8"> <style type"text/css">#imgborder{ width: 200px;height: 160px;border: 3px solid #000; overflow: hidden;position:…

mysql一张表最多多少索引_MySQL一个索引最多有多少个列?真实的测试例子

MySQL一个索引最多有多少个列&#xff1f;真实的测试例子更新时间&#xff1a;2009年07月01日 22:22:21 作者&#xff1a;MySQL一个索引最多有多少个列&#xff1f;下面是具体的实现代码。最多16列。create table test (f1 int,f2 int,f3 int,f4 int,f5 int,f6 int,f7 int,f8…

.NET Core 使用 LibreOffice 实现 Office 预览(Docker 部署)

前些年做云盘产品的时候&#xff0c;一个很核心的功能就是 Office 文件预览&#xff0c;当时还没有使用 .NET Core ,程序部署在 Windows Server 服务器上&#xff0c;文件预览的方案采用了微软的 OWA 。目前在做的零代码产品中的表单附件控件&#xff0c;同样面临着 Office 文件…

[开源精品] C#.NET im 聊天通讯架构设计 -- FreeIM 支持集群、职责分明、高性能

&#x1f4bb; FreeIM 是什么&#xff1f;FreeIM 使用 websocket 协议实现简易、高性能&#xff08;单机支持5万连接&#xff09;、集群即时通讯组件&#xff0c;支持点对点通讯、群聊通讯、上线下线事件消息等众多实用性功能。 ImCore 已正式改名为 FreeIM。使用场景&#xff…

用websploit获取管理员后台地址

1, use web/dir_scanner 2, set TARGET http://www.****.com 3, run SOURCE: https://sourceforge.net/projects/websploit/ WebSploit Advanced MITM Framework[]Autopwn – Used From Metasploit For Scan and Exploit Target Service[]wmap – Scan,Crawler Target Used Fro…

《ASP.NET Core 6框架揭秘》实例演示[16]:内存缓存与分布式缓存的使用

.NET提供了两个独立的缓存框架&#xff0c;一个是针对本地内存的缓存&#xff0c;另一个是针对分布式存储的缓存。前者可以在不经过序列化的情况下直接将对象存储在应用程序进程的内存中&#xff0c;后者则需要将对象序列化成字节数组并存储到一个独立的“中心数据库”。对于分…

人工智能教程007:创建一个卷积神经网络(2)

2019独角兽企业重金招聘Python工程师标准>>> 我们如何对图像应用卷积 当我们在图像上应用卷积时&#xff0c;我们在两个维度上执行卷积——水平和竖直方向。我们混合两桶信息&#xff1a;第一桶是输入的图像&#xff0c;由三个矩阵构成——RGB三通道&#xff0c;其中…

【系统知识点】linux入门基础命令

大概总结了一下一些基础命令&#xff0c;仅仅是帮助基础使用linux文件系统&#xff0c;如果还有相关基础命令&#xff0c;希望大家留言一起补充汇总一下&#xff01;命令的基本格式&#xff1a;格式&#xff1a;command [-options] parameter1 parameter2 …ps&#xff1a;第一…

Blazor University (48)依赖注入 —— Scoped 依赖

原文链接&#xff1a;https://blazor-university.com/dependency-injection/dependency-lifetimes-and-scopes/scoped-dependencies/Scoped 依赖Scoped 依赖项类似于 Singleton 依赖项&#xff0c;因为 Blazor 会将相同的实例注入到依赖它的每个对象中&#xff0c;但不同之处在…

c 连接mysql怎么增删改_C++ API方式连接mysql数据库实现增删改查

这里复制的http://www.bitscn.com/pdb/mysql/201407/226252.html一、环境配置1&#xff0c;装好mysql&#xff0c;新建一个C控制台工程(从最简单的弄起&#xff0c;这个会了&#xff0c;可以往任何c工程移植)&#xff0c;在vs2010中设置&#xff0c;工程--属性--VC目录--包含目…

阿里云如何实现海量短视频的极速分发?答案在这里!

摘要&#xff1a;短视频行业目前比较火热&#xff0c;但是如何快速的实现海量短视频的极速分发&#xff0c;对于短视频业务提供方来讲是一个比较棘手的问题。阿里云技术专家将带领大家从视频的上传、采集、存储和CDN分发等方面为我们介绍阿里云的整体方案&#xff0c;并且重点讲…

GitHub项目管理维护实用教程

GitHub项目维护教程 1&#xff09;注册GitHub账户并登陆&#xff1b; 2&#xff09;在Windows cmd&#xff08;或Ubuntu中的terminal&#xff09;中cd到自己的工作目录&#xff0c;将仓库clone下来&#xff1a; 命令&#xff1a; 1 git clone https://github.com/... #项目地址…

图文详解cacti的安装和使用

简介&#xff1a; 1.cacti介绍2.安装服务端3.安装客户端4.添加监控的设备cacti的介绍Cacti是一套基于PHP,MySQL,SNMP及RRDTool开发的网络流量监测图形分析工具Cacti是通过 snmpget来获取数据&#xff0c;使用 RRDtool绘画图形&#xff0c;而且你完全可以不需要了解RRDtool复杂…

记一次 .NET 某金融企业 WPF 程序卡死分析

一&#xff1a;背景 1. 讲故事前段时间遇到了一个难度比较高的 dump&#xff0c;经过几个小时的探索&#xff0c;终于给找出来了&#xff0c;在这里做一下整理&#xff0c;希望对大家有所帮助&#xff0c;对自己也是一个总结&#xff0c;好了&#xff0c;老规矩&#xff0c;上 …

如何将图片放到mysql_怎么将图片添加到mysql中

将图片添加到mysql中的方法&#xff1a;首先将数据库存储图片的字段类型设置为blob二进制大对象类型&#xff1b;然后将图片流转化为二进制&#xff1b;最后将图片插入数据库即可。正常的图片储存要么放进本地磁盘&#xff0c;要么就存进数据库。存入本地很简单&#xff0c;现在…

Java线程与Linux内核线程的映射关系

http://blog.sina.com.cn/s/blog_605f5b4f010198b5.html Linux从内核2.6開始使用NPTL &#xff08;Native POSIX Thread Library&#xff09;支持&#xff0c;但这时线程本质上还轻量级进程。Java里的线程是由JVM来管理的。它怎样相应到操作系统的线程是由JVM的实现来确定的。L…

YoursLC 有源 低代码 项目介绍

YoursLC 是我们独立研发的一款低代码产品&#xff0c;YoursLC-yours你们的、LC是低代码low-code的缩写&#xff0c;中文名称&#xff1a;有源低代码&#xff0c; 是一套双输出的低代码产品&#xff1a;既能完整输出功能又能100%输出源码。满足用户高效率、低成本和个性化的需求…

stm32电机控制定时器1_STM32通过PWM控制电机速度

做STM32智能小车的实验中会用到定时器PWM输出&#xff0c;来改变直流电机的转速。分享本文了解如何通过PWM实现对电机速度的控制。PWM控制电机速度的基本原理PWM(Pulse Width Modulation)&#xff0c;也就是脉冲宽度调制。PWM中有一个比较重要的概念&#xff0c;占空比&#xf…