前言:在本文中,我将聊聊在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新特性启动信息中的结构化日志的更多相关文章

  1. 探索 ASP.Net Core 3.0系列五:引入IHostLifetime并弄清Generic Host启动交互

    前言:在本文中,我将介绍如何在通用主机之上重新构建ASP.NET Core 3.0,以及由此带来的一些好处. 同时也展示了3.0中引入新的抽象类IHostLifetime,并描述了它在管理应用程序(尤 ...

  2. .NET Core开发日志——结构化日志

    在.NET生态圈中,最早被广泛使用的日志库可能是派生自Java世界里的Apache log4net.而其后来者,莫过于NLog.Nlog与log4net相比,有一项较显著的优势,它支持结构化日志. 结 ...

  3. 学习ASP.NET Core Blazor编程系列六——新增图书(上)

    学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...

  4. 学习ASP.NET Core Razor 编程系列六——数据库初始化

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  5. C#中的函数式编程:递归与纯函数(二) 学习ASP.NET Core Razor 编程系列四——Asp.Net Core Razor列表模板页面

    C#中的函数式编程:递归与纯函数(二)   在序言中,我们提到函数式编程的两大特征:无副作用.函数是第一公民.现在,我们先来深入第一个特征:无副作用. 无副作用是通过引用透明(Referential ...

  6. 学习ASP.NET Core Razor 编程系列五——Asp.Net Core Razor新建模板页面

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  7. [渣译文] SignalR 2.0 系列: 开始使用SignalR 2.0

    原文:[渣译文] SignalR 2.0 系列: 开始使用SignalR 2.0 英文渣水平,大伙凑合着看吧…… 这是微软官方SignalR 2.0教程Getting Started with ASP ...

  8. Atitit 发帖机系列(8)  词法分析器v5 版本新特性说明)

    Atitit 发帖机系列(8)  词法分析器v5 版本新特性说明) v5  增加对sql单引号的内部支持.可以作为string 结构调整,使用递归法重构循环发..放弃循环发. V4 java dsl词 ...

  9. 学习ASP.NET Core Blazor编程系列六——初始化数据

    学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...

随机推荐

  1. 拎壶带你冲----教育类mysql用户表设计参考

    说起用户表,大概是每个应用/网站立项动工(码农们)考虑的第一件事情.用户表结构的设计,算是整个后台架构的基石.如果基石不稳,待到后面需求跟进了发现不能应付,回过头来反复修改用户表,要大大小小作改动的地 ...

  2. SpringBoot(16)—@ConditionalOnBean与@ConditionalOnClass

    @ConditionalOnBean与@ConditionalOnClass 上一篇讲的@Conditional可以通过条件控制是否注入Bean,这篇讲下有关Bean其它几个常用的注解使用方式 @Co ...

  3. 滑动门出现的背景---实例微信导航栏(a盒子里面包span盒子,文字写在span里)

    需求: 制作网页时,为了美观,常常需要为网页元素设置特殊形状的背景,比如微信导航栏,有凸起和凹下去的感觉,其中最大的问题是字数不同,如何做? 解决: 用一个a包含span来制作,字数放在span里面. ...

  4. Vuex基本使用的总结--转载

    在 Vue 的单页面应用中使用,需要使用Vue.use(Vuex)调用插件.使用非常简单,只需要将其注入到Vue根实例中. import Vuex from 'vuex' Vue.use(Vuex) ...

  5. 「SAP 技术」SAP BP显示供应商账户组时候的怪现象

    SAP BP显示供应商账户组时候的怪现象 BP事务代码显示某个vendor的时候,笔者发现对于账户组字段选项列表里,不显示当前vendor的account group. 如下图,该供应商的accoun ...

  6. GBT22239-2008-等保1.0三级要求

    第三级基本要求 7.1 技术要求 7.1.1 物理安全 7.1.1.1 物理位置的选择(G3) 本项要求包括: a)   机房和办公场地应选择在具有防震.防风和防雨等能力的建筑内: b)   机房场地 ...

  7. 滴滴出行开源项目doraemonkit食用指南

    版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/94 doraemonkit 功能介绍 一两周前在地铁上刷任 ...

  8. 【Android】Handler消息机制

    Handler消息机制主要涉及Looper.Handler.MessageQueue.Message.其中,Looper主要负责获取消息,Handler负责发送消息及处理消息,MessageQueue ...

  9. gitlab设置项目组成员权限

    你敢相信这是个码农? setting菜单的“Members”功能页: 该页面展示了当前Project的成员列表,以及每个成员对应的权限角色,Owner/Master/Developer 注意到该页面顶 ...

  10. linux软件管理-RPM

    目录 linux软件管理-RPM RPM的基础概述 RPM包安装管理 linux软件管理-RPM RPM的基础概述 rpm:RPM全称RPM Package Manager缩写,由红帽开发用于软件包的 ...