《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,一经查实,立即删除!

相关文章

基于mysql数据库的应用_MySQL数据库应用

参考资料&#xff1a;准备软件&#xff1a;mysql-5.5.13-win32.msi、MySQL安装图解.doc、Navicat_for_MySQL_10.0.5.0_XiaZaiBa.exe、mysqldriver.jar、eclipseMySQL基本操作登陆&#xff1a;mysql -u 用户名 -p 密码显示数据库&#xff1a;show databases;使用数据库&#xff…

《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 文件…

es6(五):函数的扩展

函数参数的默认值 function log(x, y World) {console.log(x, y); }log(Hello) // Hello World log(Hello, China) // Hello China log(Hello, ) // Hellofunction Point(x 0, y 0) {this.x x;this.y y; }var p new Point(); p // { x: 0, y: 0 }函数length 的属性 指定了…

tomcat启动报错:Bean name 'XXX' is already used in this beans element

如题&#xff0c;tomcat容器启动时加载spring的bean&#xff0c;结果报错如下&#xff1a; 六月 28, 2017 9:02:25 上午 org.apache.tomcat.util.digester.SetPropertiesRule begin 警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property source to…

[开源精品] 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…

mysql事务操作_mysql的事务操作

倒着思考。杜绝纯粹的知识填鸭教育少废话&#xff0c;是上代码&#xff1a;update table1 set money-100 where id1; //A账户减少100元update table2 set money100 where id2; //B 账户增加100元问题&#xff1a;这是一个简单的银行转账案例sql&#xff0c;由于服务器等未知原因…

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

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

高可用架构-- MySQL主从复制的配置

环境 操作系统&#xff1a;CentOS-6.6-x86_64-bin-DVD1.iso MySQL版本&#xff1a;mysql-5.6.26.tar.gz 主节点IP&#xff1a;192.168.1.205 主机名&#xff1a;edu-mysql-01 从节点IP&#xff1a;192.168.1.206 主机名&#xff1a;edu-mysql-02 主机配置&#xff1a;4核CPU、4…

java 数组冒泡排序、转置(降序)

1.java 数组冒泡排序 排序的基本原理&#xff08;升序&#xff09;&#xff1a; 原始数据&#xff1a; 2 、1 、9 、0 、5 、3 、7 、6 、8&#xff1b; 第一次排序&#xff1a; 1 、2 、0 、5 、3 、7 、6 、8 、9 &#xff1b; 第二次排序&#xff1a; 1 、0 、2 、…

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

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

释放mysql ibdata1文件_释放MySQL ibdata1文件的空间

在MySQL数据库中&#xff0c;如果不指定innodb_file_per_table参数&#xff0c;单独存在每个表的数据&#xff0c;MySQL的数据都会存放在ibdata1文件。mysql ibdata1存放数据&#xff0c;索引等&#xff0c;是MYSQL的最主要的数据。步骤&#xff1a;1&#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;并且重点讲…