.NET Core开发实战(第19课:日志作用域:解决不同请求之间的日志干扰)--学习笔记...

19 | 日志作用域:解决不同请求之间的日志干扰

开始之前先看一下上一节的代码

// 配置的框架
var configBuilder = new ConfigurationBuilder();
configBuilder.AddCommandLine(args);
configBuilder.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);var config = configBuilder.Build();
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<IConfiguration>(p => config);// 日志的框架
serviceCollection.AddLogging(builder =>
{builder.AddConfiguration(config.GetSection("Logging"));// 注册 Logging 配置的 Sectionbuilder.AddConsole();// 先使用一个 Console 的日志输出提供程序builder.AddDebug();
});

我们可以观察到配置的框架和日志的框架,它们的设计模式是很相似的

区别就是:

配置的框架是从不同的数据源读取数据并且供给我们结构化的数据可以读取

日志框架是用统一的记录方式,让我们可以把日志记录到不同的地方去,输出到不同的地方去

接下来演示一下关于日志的作用域的部分

日志作用域几个常用场景:

1、一个事务包含多条操作时:比如说在一个事务里面去操作的时候,会需要记录多条日志,需要把多条日志串联在一起,而不是记录成一行

2、复杂流程的日志关联时:比如说工作流流程里面去进入这个日志

3、调用链追踪与请求处理过程对应时:如果在调用链追踪过程中记录了多条日志,希望把日志串联在一起的时候,作用域就发挥了作用

源码链接:
https://github.com/witskeeper/geektime/tree/master/samples/LoggingScopeDemo

主程序

namespace LoggingScopeDemo
{class Program{static void Main(string[] args){var configBuilder = new ConfigurationBuilder();configBuilder.AddCommandLine(args);configBuilder.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);var config = configBuilder.Build();IServiceCollection serviceCollection = new ServiceCollection();serviceCollection.AddSingleton(p => config); //用工厂模式将配置对象注册到容器管理serviceCollection.AddLogging(builder =>{builder.AddConfiguration(config.GetSection("Logging"));builder.AddConsole();builder.AddDebug();});IServiceProvider service = serviceCollection.BuildServiceProvider();var logger = service.GetService<ILogger<Program>>();// 相当于记录了一条上下文串联的日志using (logger.BeginScope("ScopeId:{scopeId}", Guid.NewGuid())){logger.LogInformation("这是Info");logger.LogError("这是Error");logger.LogTrace("这是Trace");}}}
}

配置文件

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

启动程序,输出如下:

info: LoggingScopeDemo.Program[0]这是Info
fail: LoggingScopeDemo.Program[0]这是Error
trce: LoggingScopeDemo.Program[0]这是Trace

和之前一样的输出,接着修改配置文件

"IncludeScopes": true,

启动程序,输出如下:

info: LoggingScopeDemo.Program[0]=> ScopeId:b8ef7682-6c6d-4f74-83c8-b9fd4613c623这是Info
fail: LoggingScopeDemo.Program[0]=> ScopeId:b8ef7682-6c6d-4f74-83c8-b9fd4613c623这是Error
trce: LoggingScopeDemo.Program[0]=> ScopeId:b8ef7682-6c6d-4f74-83c8-b9fd4613c623这是Trace

可以看到,日志里面有 scope,并且三条日志都包含了相同的 ScopeId,这个是由我们决定 Scope 的内容是什么,一般推荐使用一个唯一标识,比如 HTTP 请求的 id,或者是 session 的 id,或者是事务的 id

接着修改为循环

// 只要输入不是 Esc 就循环执行
while (Console.ReadKey().Key != ConsoleKey.Escape)
{// 相当于记录了一条上下文串联的日志using (logger.BeginScope("ScopeId:{scopeId}", Guid.NewGuid())){logger.LogInformation("这是Info");logger.LogError("这是Error");logger.LogTrace("这是Trace");}Console.WriteLine("============分割线=============");
}
Console.ReadKey();

启动程序,输出如下:

info: LoggingScopeDemo.Program[0]=> ScopeId:cc25dd86-d3fe-41e8-b607-61912c65bde7这是Info
============分割线=============
fail: LoggingScopeDemo.Program[0]=> ScopeId:cc25dd86-d3fe-41e8-b607-61912c65bde7这是Error
trce: LoggingScopeDemo.Program[0]=> ScopeId:cc25dd86-d3fe-41e8-b607-61912c65bde7这是Trace

这里可以看到分割线有点错乱,这是因为 Console 的提供程序实际上内部是用异步的方式在记录,那也就是这里遇到并发的问题

调整一下代码,让主线程休息一下

System.Threading.Thread.Sleep(100);
Console.WriteLine("============分割线=============");

这样子启动之后顺序就正确了

在程序启动的情况下,修改 Debug 目录下的配置文件

"IncludeScopes": false,

修改保存后在控制台输入回车,可以看到配置生效了,意味着可以使用配置热更新能力来动态修改配置的输出,调整配置输出的级别

比如将

"LoggingScopeDemo.Program": "Trace",

修改为

"LoggingScopeDemo.Program": "Error",

修改保存后在控制台输入回车,只会输出 Error 级别

这是在控制台里面的效果,接下来看一下在一个 ASP.NET Core Web 应用下面的日志是什么样子

源码链接:
https://github.com/witskeeper/geektime/tree/master/samples/LoggingDemo

这是一个默认的工程,仅仅在应用程序里面加了两行代码

[HttpGet]
public async Task<IEnumerable<WeatherForecast>> Get()
{_logger.LogInformation("开始Get了");_logger.LogInformation("Get睡醒了");var rng = new Random();return Enumerable.Range(1, 5).Select(index => new WeatherForecast{Date = DateTime.Now.AddDays(index),TemperatureC = rng.Next(-20, 55),Summary = Summaries[rng.Next(Summaries.Length)]}).ToArray();}

日志级别

"Console": {"IncludeScopes": true}

启动程序,输出如下:

info: LoggingDemo.Controllers.WeatherForecastController[0]=> RequestPath:/weatherforecast RequestId:0HLU2MTQ99HO2:00000001, SpanId:|7bb9cb12-4a0fe499cae27707., TraceId:7bb9cb12-4a0fe499cae27707, ParentId: => LoggingDemo.Controllers.WeatherForecastController.Get (LoggingDemo)开始Get了
info: LoggingDemo.Controllers.WeatherForecastController[0]=> RequestPath:/weatherforecast RequestId:0HLU2MTQ99HO2:00000001, SpanId:|7bb9cb12-4a0fe499cae27707., TraceId:7bb9cb12-4a0fe499cae27707, ParentId: => LoggingDemo.Controllers.WeatherForecastController.Get (LoggingDemo)Get睡醒了

可以看到,记录的 开始Get了 以及 Get睡醒了,都包含了 RequestPath,RequestId,SpanId,TraceId 这些信息,这些信息是当前请求的上下文

也就意味着可以在记录日志的时候,用请求上下文把日志串联起来,多个请求的日志可以区分开来,无论记录了多条还是单条

也就意味着可以在事务处理的过程中,复杂的流程的过程中,或者调用链的处理过程中,当然还有其他的场景任意的需要将多条日志串联起来的场景,都可以用作用域来实现这个能力

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

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

相关文章

递归算法(二)-分治法

分治法 分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题&#xff0c;这些子问题相互独立且与原问题性质相同。求出子问题的解&#xff0c;就可得到原问题的解。即一种分目标完成程序算法&#xff0c;简单问题可用二分法完成。 分治法解题的一般步骤&#…

自适应滤波器在matlab仿真的程序_电气信息类专业课程之matlab系统仿真 第五章 BPSK通信系统(3)...

继续讲解&#xff01;上一篇文章提出了那么多问题&#xff0c;不知道大家是否能回答上来啊&#xff1f;如果回答不了&#xff0c;有没有去问问度娘呢&#xff1f;程序写完了&#xff0c;回想了一下辅导2017届学生毕业设计的过程&#xff0c;那是真累。我要求他们在现有程序基础…

阿捷外传之Git代码统计:DotNetCore + PowerBI 实现Git仓库日志分析

前言2020年3月初春&#xff0c;虽然春节已经过去一个多月&#xff0c;大街上还未恢复往年的热闹。由于春节前夕突然降临的冠状病毒&#xff0c;导致很多员工无法回到城市复工。春节之后&#xff0c;阿捷所在的公司考虑到复工带来的风险&#xff0c;通知所有员工以远程的方式在家…

递归算法(三)- 回溯法Backtracking

回溯法 回溯法Backtracking&#xff08;找所有的可能&#xff09;递归&#xff1a; 类似枚举&#xff0c;一层一层向下递归&#xff0c;尝试搜索答案。找到答案&#xff1a; > 返回答案&#xff0c;并尝试别的可能未找到答案&#xff1a; > 返回上一层递归&#xff0c;…

一个全栈式的应用集成平台,打破“信息孤岛”

源宝导读&#xff1a;随着企业数字化进程的逐渐深入&#xff0c;企业存在大量的异构系统&#xff0c;各个系统之间信息传输、资源利用困难。本文将介绍明源云ERP为了打破这种“信息孤岛”&#xff0c;而进行的思考与实践。一、前言随着企业信息化进程的逐步深入&#xff0c;互联…

【朝夕技术专刊】Core3.1WebApi_Filter多种注册方式支持依赖注入

欢迎大家阅读《朝夕Net社区技术专刊》第5期我们致力于.NetCore的推广和落地&#xff0c;为更好的帮助大家学习&#xff0c;方便分享干货&#xff0c;特创此刊&#xff01;很高兴你能成为忠实读者&#xff0c;文末福利不要错过哦&#xff01;01PARTCoreFilter多种注册方式在上一…

SQL(一)- 数据库介绍与基础操作

数据库介绍 一、常用的数据库分为两大类&#xff1a; 关系型数据库非关系型数据库&#xff08;NoSql&#xff09; 关系型数据库 概念&#xff1a;是建立在关系模型基础上的数据库&#xff0c;借助于集合代数等数学概念和方法来处理数据库中的数据。 关系型数据库的优势&am…

opencv +数字识别

现在很多场景需要使用的数字识别&#xff0c;比如银行卡识别&#xff0c;以及车牌识别等&#xff0c;在AI领域有很多图像识别算法&#xff0c;大多是居于opencv 或者谷歌开源的tesseract 识别.由于公司业务需要&#xff0c;需要开发一个客户端程序&#xff0c;同时需要在xp这种…

SQL(二)- 基础查询语句

简单的查询语句&#xff08;DQL&#xff09; 下面我们正式来学习查询语句&#xff0c;下面所有查询用到的表均为前面提到的三张表&#xff1a; 员工表中的数据&#xff1a; 部门表中的数据&#xff1a; 薪资表中的数据&#xff1a; 基本查询语句的语法&#xff1a; sele…

SQL(三)- 连接查询

连接查询概念 一、什么是连接查询&#xff1f; 在实际开发中&#xff0c;大部分的情况下都不是从单张表中查询数据&#xff0c;一般都是多张表联合查询最终取出最终结果。在实际再发中&#xff0c;一般一个业务都会对应多张表&#xff0c;比如学生和班级&#xff0c;最起码两…

远程办公也可以很高效

题图&#xff1a;我的站立办公环境因为疫情&#xff0c;全中国人民都过了一个难忘的春节&#xff0c;而身在武汉的我&#xff0c;更是没有出家门半步&#xff0c;坚决做到不过国家添乱。从开始的2月14到后来的2月20日&#xff0c;再到现在的3月10日&#xff0c;官方发布的复工日…

SQL(四) - 子查询和union以及limit分页

子查询概念 什么是子查询&#xff1f;子查询都可以出现在哪里&#xff1f; select语句当中嵌套select语句&#xff0c;被嵌套的select语句是子查询。 子查询可以出现在哪里&#xff1f; select..(select). from..(select). where..(select).1.where子句中使用子查询 案例&a…

ASP.NET Core中的Http缓存

ASP.NET Core中的Http缓存Http响应缓存可减少客户端或代理对 web服务器发出的请求数。响应缓存还减少了 web服务器生成响应所需的工作量。响应缓存由 Http请求中的 header控制。而 ASP.NETCore对其都有相应的实现&#xff0c;并不需要了解里面的工作细节&#xff0c;即可对其进…

SQL(五) - 表的创建以及操作

创建表 建表语句的语法格式&#xff1a; create table 表名(字段名1 数据类型,字段名2 数据类型,字段名3 数据类型,....);MySql常用数据类型 BLOB 二进制大对象&#xff08;存储图片、视频等流媒体信息&#xff09; Binary Large OBject &#xff08;对应java中的Object&…

Istio 2020 年 Roadmap——一切为了商用

原文地址&#xff1a;https://preliminary.istio.io/zh/blog/2020/tradewinds-2020/&#xff0c;由 ServiceMesher 社区翻译。Istio 解决了人们在运行微服务时遇到的实际问题。甚至早期的预发行版本就已经可以帮助用户诊断其体系架构中的延迟&#xff0c;提高服务的可靠性以及透…

SQL(七) - 事务、索引、视图

事务&#xff08;Transaction&#xff09; 3.1、什么是事务&#xff1f; 一个事务是一个完整的业务逻辑单元&#xff0c;不可再分。 比如&#xff1a;银行账户转账&#xff0c;从A账户向B账户转账10000.需要执行两条update语句&#xff1a; update t_act set balance balan…

如何编写高性能的C#代码(二)

使用Benchmark.NET对C# 代码进行基准测试的简介在我以前的文章中[10]&#xff0c;我介绍了该系列文章[11]&#xff0c;在其中我将分享我的经验&#xff0c;同时了解C&#xff03;和.NET Core&#xff08;corefx&#xff09;框架的新性能。在本文中&#xff0c;我想着重于对现有…

如何编写高性能的C#代码(一)

原文来自互联网&#xff0c;由长沙DotNET技术社区编译。如译文侵犯您的署名权或版权&#xff0c;请联系小编&#xff0c;小编将在24小时内删除。作者介绍&#xff1a;史蒂夫戈登&#xff08;Steve Gordon&#xff09;是Microsoft MVP&#xff0c;Pluralsight的作者&#xff0c;…

从Java转向.NET/C#,Are You OK?

最近由于项目变动&#xff0c;需要用.NET/C#做开发&#xff0c;经过一段时间的学习和培训&#xff0c;对这个技术栈有了一定的理解。大家可能都知道Java和.NET/C#很像&#xff0c;这里粗略的把两者做一个对比&#xff0c;希望对感兴趣的童鞋有所帮助。如果现在有人问我&#xf…

树的节点值之和

题目背景 墨家家主有棵树。 题目描述 给定一个保存树节点信息的数据结构&#xff0c;它包含了树节点唯一的 id &#xff0c;树节点值 和 直系子节点的 id 。 比如&#xff0c;树节点1是树节点2的父节点&#xff0c;树节点2是树节点3的父节点。他们相应的树节点值为 9 , 4 , …