前言:在本文中,我将聊聊在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. 我的前端架构(jquery)汇总

    目录 我的前端架构之一--页面作用域 我的前端架构之二--统一扩展Js方法 我的前端架构之三 -- 页面规范 我的前端架构之四 -- UI控件 我的前端架构之五 -- 一些方案实现 判断对象是否是 e ...

  2. spider-通过scrapyd网页管理工具执行scrapy框架

    1.首先写一个scrapy框架爬虫的项目 scrapy startproject 项目名称 # 创建项目 cd 项目名称 scrapy genspider 爬虫名称 爬虫网址(www.xxxx) #生 ...

  3. python接口自动化12-pytest前后置与fixture

    前言 我们都知道在自动化测试中都会用到前后置,pytest 相比 unittest 无论是前后置还是插件等都灵活了许多,还能自己用 fixture 来定义.(甩 unttest 半条街?) 首先了解一 ...

  4. SpringBoot2.0.4部署在tomcat容器中

    1.  修改启动类继承自SpringBootServletInitializer. 2. 重写config方法: @Overrideprotected SpringApplicationBuilder ...

  5. Android Studio 提高开发效率的插件

    好久没有更新博客了,最近搞个listview搞得半死不活的,心累~~ 今天带来的是Android Studio插件的整理,全是我已经安装使用的,写这篇博文的目的也是因为我怕我自己给忘记怎么用(尴尬) ...

  6. Docker是什么、为什么是一种趋势

    Docker的思想来自于集装箱,集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来.并且各种各样的货物被集装箱标准化了,集装箱和集装箱之间不会互相影响.那么我就不需要专门运送水果的船和专门运 ...

  7. find命令通过排序只保留最新的文件目录

    find /usr/local/canal/logs/example -type d -name "*-*" | sort -nr | awk '{if (NR>=2){pr ...

  8. Linux中fdisk分区

    一.硬盘接口    从整体的角度上,硬盘接口分为IDE.SATA.SCSI和SAS四种,IDE接口硬盘多用于家用产品中,也部分应用于服务器,SCSI接口的硬盘则主要应用于服务器市场,而SAS只在高端服 ...

  9. element-ui修改表单自带验证的样式

    1.比如重写在表单自带验证的样式 .el-form-item__error是对应是的文字的类名,图标我是通过伪元素插进去的 下面是伪元素代码 基本上要重写样式的,到控制台看样式名,因为是封装的,所以有 ...

  10. easyui权限

    实现权限目的: 是为了让不同的用户可以操作系统中不同资源 直接点说就是不同的用户可以看到不同的菜单 我们先来看下3张接下来用到的数据表 1.菜单表(t_easyui_menu) 2.用户菜单中间表(t ...