探索ASP.Net Core 3.0系列六:ASP.NET Core 3.0新特性启动信息中的结构化日志
前言:在本文中,我将聊聊在ASP.NET Core 3.0中细小的变化——启动时记录消息的方式进行小的更改。 现在,ASP.NET Core不再将消息直接记录到控制台,而是正确使用了logging 基础结构,来生成结构化日志。
翻译: Andrew Lock https://andrewlock.net/new-in-aspnetcore-3-structured-logging-for-startup-messages/
探索ASP.NET Core 3.0系列一:新的项目文件、Program.cs和generic host
探索ASP.Net Core 3.0系列二:聊聊ASP.Net Core 3.0 中的Startup.cs
探索 ASP.Net Core 3.0系列三:ASP.Net Core 3.0中的Service provider validation
探索ASP.Net Core 3.0系列四:在ASP.NET Core 3.0的应用中启动时运行异步任务
探索 ASP.Net Core 3.0系列五:引入IHostLifetime并弄清Generic Host启动交互
一、ASP.NET Core 2.x中恼人的非结构化日志
当您在ASP.NET Core 2.x中启动应用程序时,默认情况下,ASP.NET Core会将一些有关您的应用程序的信息输出到控制台,例如当前环境,内容根路径以及Kestrel正在监听的URL。:

这些消息由WebHostBuilder写入的,目的是为您提供了应用程序的便捷概述,但它直接写入控制台中。
这有两个主要缺点:
- 这些有用的信息仅写入控制台,因此不会写入任何其他日志记录基础结构。
- 写入控制台的消息是非结构化的,它们的格式将与写入控制台的任何其他日志不同。 他们甚至没有日志级别或源。
最后一点特别烦人,因为在Docker中运行时通常将结构化日志写入标准输出(控制台),然后让另一个进程读取这些日志并将其发送到中央位置(例如使用fluentd),这很常见。

幸运的是,在ASP.NET Core 2.1中,有一种方法可以使用环境变量禁用这些消息,如我在上一篇文章中所展示的。 唯一的缺点是消息被完全禁用,因此根本不会记录任何方便的信息,详细请参考这边文章:
https://andrewlock.net/suppressing-the-startup-and-shutdown-messages-in-asp-net-core/
幸运的是,ASP.NET Core 3.0中的微小变化为我们提供了两全其美的方法!
二、在ASP.NET Core 3.0中正确记录日志
如果使用dotnet run启动ASP.NET Core 3.0应用程序,您会注意到写入控制台的日志消息中的细微差别:

现在,使用结构化日志记录启动消息! 但是并不像使用Logger替代Console那样简单。 在ASP.NET Core 2.x中,由WebHost负责记录这些消息。 在ASP.NET Core 3.0中,这些消息由ConsoleLifetime记录,ConsoleLifetime是通用主机注册的默认IHostLifetime。
我在上一篇文章中描述了IhostLifetime(尤其是ConsoleLifetime)的作用,但总而言之,该类负责侦听控制台中的Ctrl + C按键,并启动关闭过程。
ConsoleLifetime还在其WaitForStartAsync()方法期间注册回调,这些回调在触发ApplicationLifetime.ApplicationStarted事件以及触发ApplicationLifetime.ApplicationStopping事件时调用:
public Task WaitForStartAsync(CancellationToken cancellationToken)
{
if (!Options.SuppressStatusMessages)
{
// Register the callbacks for ApplicationStarted
_applicationStartedRegistration = ApplicationLifetime.ApplicationStarted.Register(state =>
{
((ConsoleLifetime)state).OnApplicationStarted();
},
this); // Register the callbacks for ApplicationStopping
_applicationStoppingRegistration = ApplicationLifetime.ApplicationStopping.Register(state =>
{
((ConsoleLifetime)state).OnApplicationStopping();
},
this);
} // ... return Task.CompletedTask;
}
这些回调运行简单地写入日志记录基础结构的OnApplicationStarted()和OnApplicationStopping()方法(如下所示):
private void OnApplicationStarted()
{
Logger.LogInformation("Application started. Press Ctrl+C to shut down.");
Logger.LogInformation("Hosting environment: {envName}", Environment.EnvironmentName);
Logger.LogInformation("Content root path: {contentRoot}", Environment.ContentRootPath);
} private void OnApplicationStopping()
{
Logger.LogInformation("Application is shutting down...");
}
尽管确切的消息略有不同,但是System Lifetime和Windows ServiceLifetime实现使用相同的方法通过标准日志记录基础结构来写入日志文件。
三、使用ConsoleLifetime抑制启动消息
ConsoleLifetime创建的启动消息引起的一个令人惊讶的变化是,您将无法再按照我在上一篇文章中描述的方式隐藏消息。 设置ASPNETCORE_SUPPRESSSTATUSMESSAGES显然没有任何效果-无论是否设置了环境变量,消息都将继续记录!
正如我已经指出的那样,由于使用Microsoft.Extensions.Logging基础结构正确记录了消息,因此这现在并不是什么大问题。 但是,如果这些消息由于某种原因冒犯了您,并且您真的想摆脱它们,则可以在Startup.cs中配置ConsoleLifetimeOptions:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// ... other configuration
services.Configure<ConsoleLifetimeOptions>(opts => opts.SuppressStatusMessages = true);
}
}

现在只显示结构化的日志信息了。
如果需要,您甚至可以根据ASPNETCORE_SUPPRESSSTATUSMESSAGES环境变量的存在来设置SuppressStatusMessages字段:
public class Startup
{
public IConfiguration Configuration { get; } public Startup(IConfiguration configuration) => Configuration = configuration; public void ConfigureServices(IServiceCollection services)
{
// ... other configuration
services.Configure<ConsoleLifetimeOptions>(opts
=> opts.SuppressStatusMessages = Configuration["SuppressStatusMessages"] != null);
}
}
如果您确实选择不显示消息,请注意,Kestrel仍会记录其正在监听的URL;否则,您将保留其记录。 没有办法抑制这些:
info: Microsoft.Hosting.Lifetime[]
Now listening on: http://0.0.0.0:5000
info: Microsoft.Hosting.Lifetime[]
Now listening on: https://0.0.0.0:5001
四、总结
在本文中,我展示了如何在3.0中记录结构化日志,避免在ASP.NET Core 2.x应用程序启动时烦人的非结构化日志。 这样可以确保将日志写入所有已配置的记录器,并且在写入控制台时具有标准格式。 我在日志消息中描述了IhostLifetime的角色,并说明了如何配置ConsoleLifetimeOptions以根据需要禁止显示状态消息。
好了,这个系列 的文章就到此结束,后面我会再补充6篇文章,该系列就完全结束了,剩下的 就是继续搞秒杀项目(ASP.Net Core )的CI/CD,争取 年前能搞定吧。
翻译: Andrew Lock https://andrewlock.net/new-in-aspnetcore-3-structured-logging-for-startup-messages/
作者:郭峥
出处:http://www.cnblogs.com/runningsmallguo/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
探索ASP.Net Core 3.0系列六:ASP.NET Core 3.0新特性启动信息中的结构化日志的更多相关文章
- 探索 ASP.Net Core 3.0系列五:引入IHostLifetime并弄清Generic Host启动交互
前言:在本文中,我将介绍如何在通用主机之上重新构建ASP.NET Core 3.0,以及由此带来的一些好处. 同时也展示了3.0中引入新的抽象类IHostLifetime,并描述了它在管理应用程序(尤 ...
- .NET Core开发日志——结构化日志
在.NET生态圈中,最早被广泛使用的日志库可能是派生自Java世界里的Apache log4net.而其后来者,莫过于NLog.Nlog与log4net相比,有一项较显著的优势,它支持结构化日志. 结 ...
- 学习ASP.NET Core Blazor编程系列六——新增图书(上)
学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...
- 学习ASP.NET Core Razor 编程系列六——数据库初始化
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
- C#中的函数式编程:递归与纯函数(二) 学习ASP.NET Core Razor 编程系列四——Asp.Net Core Razor列表模板页面
C#中的函数式编程:递归与纯函数(二) 在序言中,我们提到函数式编程的两大特征:无副作用.函数是第一公民.现在,我们先来深入第一个特征:无副作用. 无副作用是通过引用透明(Referential ...
- 学习ASP.NET Core Razor 编程系列五——Asp.Net Core Razor新建模板页面
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
- [渣译文] SignalR 2.0 系列: 开始使用SignalR 2.0
原文:[渣译文] SignalR 2.0 系列: 开始使用SignalR 2.0 英文渣水平,大伙凑合着看吧…… 这是微软官方SignalR 2.0教程Getting Started with ASP ...
- Atitit 发帖机系列(8) 词法分析器v5 版本新特性说明)
Atitit 发帖机系列(8) 词法分析器v5 版本新特性说明) v5 增加对sql单引号的内部支持.可以作为string 结构调整,使用递归法重构循环发..放弃循环发. V4 java dsl词 ...
- 学习ASP.NET Core Blazor编程系列六——初始化数据
学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...
随机推荐
- 掌握Spring REST TypeScript生成器
在优锐课的java分享中,讨论了关于Spring REST TypeScript生成器,该生成器创建反映后端模型和REST服务的模型和服务.码了很多干货,分享给大家参考学习. 我注意到网络开发人员创建 ...
- URLDecoder异常Illegal hex characters in escape (%)
URLDecoder对参数进行解码时候,代码如: URLDecoder.decode(param,"utf-8"); 有时候会出现类似如下的错误: URLDecoder异常Ille ...
- 2018-2-13-win10-uwp-手动锁Bitlocker
原文:2018-2-13-win10-uwp-手动锁Bitlocker title author date CreateTime categories win10 uwp 手动锁Bitlocker l ...
- Python 3 行代码 5 秒抠图的 AI 神器,根本无需 PS
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 苏克1900 PS:如有需要Python学习资料的小伙伴可以加点击下 ...
- 一个小事例,了解golang通道阻塞模式
在学习golang中,channel真的是让人捉摸不透的东西,本来我自以为我理解了协程阻塞的用法了,结果就下面这个小例子,我还是在打印输出后才搞明白到底怎么回事? 当然了,这也是我自身对协程这块不太熟 ...
- 机器学习实战:基于Scikit-Learn和TensorFlow 读书笔记 第6章 决策树
数据挖掘作业,要实现决策树,现记录学习过程 win10系统,Python 3.7.0 构建一个决策树,在鸢尾花数据集上训练一个DecisionTreeClassifier: from sklearn. ...
- shell 编程练习题2
需求1:使用root用户清空/var/log/messages日志,并每次执行保留最近100行 1.必须是root用户 2.需要保留最后100行 [root@manager if]# cat ...
- Dynamics 365 登录报错:MSIS7042
微软动态CRM专家罗勇 ,回复329或者20190504可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me! 今天访问我的CRM环境报错,AD FS登录页面输入用户名和密码登 ...
- ABP进阶教程5 - 多语言配置
点这里进入ABP进阶教程目录 更新脚本 打开展示层(即JD.CRS.Web.Mvc)的\wwwroot\view-resources\Views\Course\Index.js //用以存放Cours ...
- PHP代码篇(七)--PHP及MySQL已经使用过的函数
一.PHP常用函数 //数组转字符串 $str = implode(',',$device_string); //字符串转数组 $arr = explode(',',$device_string); ...