概述

调试asp.net core程序时,在输出窗口中,在输出来源选择“调试”或“xxx-ASP.NET Core Web服务器”时,可以看到类似“info:Microsoft.AspNetCore.Hosting.Internal.WebHost[2] Request finished in 285.6ms 200 text/css”这样的内容,这就是asp.net core的日志。如果出现了未捕获的异常,在输出窗口中可以看到出错信息,如:fail: Microsoft.AspNetCore.Server.Kestrel[13]……An unhandled exception was thrown by the application. System.NullReferenceException: 未将对象引用设置到对象的实例。在……行号 xx 在……行号 xx。在网站运行过程中,如果可以把这些出错信息保存下来,就可以排查代码错误了。方法很简单:把web.config文件中aspNetCore标签的stdoutLogEnabled属性设置为true,这样,在网站运行后,默认会在/logs文件夹下产生一个stdout_xxx_xxx.log的文件,日志会保存到这里面。

logging provider

从名称“stdoutLogEnabled”来看,stdout,表示“标准输出”,即控制台输出。试着写一句Console.WriteLine(xxx),在.log文件中果然就可以看到输出的内容。如果是在调试环境,可以在输出窗口/ASP.NET Core Web服务器看到Console输出的内容。asp.net core mvc项目代码模板默认添加了三个logging provider:Console、Debug、EventSource。VS的输出窗口/ASP.NET Core Web服务器,显示的就是Console这个logging provider输出的内容,而输出窗口/调试,显示的是Debug的。所以,stdout_xxx_xxx.log文件,保存的就是Console logging provider输出的日志。

观察VS的输出窗口,可以发现,同一条日志内容,Console和Debug这两个logging provider的输出格式是不同的。

日志级别

ASP.NET Core定义了几个日志级别,表示日志的严重程度,从低到高分别是Trace 、Debug 、Information 、Warning 、Error 、Critical 。

下面是一条Debug级别的日志:

dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[27]
Done attempting to validate the bound parameter 'page' of type 'System.Int32'.

一条Information级别的日志:

info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action method XXX.Controllers.YYYController.GetList (XXX) with arguments (8d35e231-c928-479e-95d4-b305a6a235eb, 1, 15, 1) - Validation state: Valid

在生产环境下,日志一般仅用于错误排查,所以用不到Information 等级别的大量日志,为此,可以设置一个最低日志级别,比如设置成Warning,将屏蔽Trace 、Debug 、Information级别的日志。最低日志级别可以给每个logging provider分别设置,如果没有具体设置,将采用默认设置。如,设置默认日志级别为Information:

"Logging": {
"LogLevel": {
"Default": "Information"
}
}

分别设置Debug、Console的日志级别:

  "Logging": {
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"LogLevel": {
"Default": "Debug"
}
},
"LogLevel": {
"Default": "Debug"
}
},

为什么针对具体的logging provider也标上"Default"?因为可以再针对日志的Log category分别设置:

  "Logging": {
"Console": {
"LogLevel": {
"Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
"Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
"Microsoft.AspNetCore.Mvc.Razor": "Error",
"Default": "Information"
}
},
"LogLevel": {
"Default": "Debug"
}
}

关于Log category的概念请自行查阅官方文档,不再赘述。

值得注意的时,在网站运行状态下,修改appsettings.json中的上述配置,不会造成网站重启(而修改web.config会造成网站重启),但对日志级别的控制会立即生效。所以,在网站运行不正常时,可以临时调低日志级别,以查看更多调试信息,又不会影响用户的使用。平时可以设置一个较高的日志级别,比如Error或Critical。而web.config中的stdoutLogEnabled属性要提前设置好。

输出自己的日志

可以输出自己的日志。用依赖注入的方式,注入ILogger<T>对象,然后用LogInformation()、LogWarning()等方法可以方便的输出对应级别的日志。

示例代码:

    public class HomeController : Controller
{
ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
} public IActionResult Index()
{
_logger.LogInformation("访问主页");
try
{
int i = 0;
int j = 1 / i;
}
catch (Exception ex)
{
_logger.LogWarning($"发生异常了:{ex.Message},调用堆栈:{ex.StackTrace}");
}
throw new Exception("这是一个测试错误"); return View();
}
}

产生的部分日志(级别设置为Information):

info: CommonCoreMvcTest.Controllers.HomeController[0]
访问主页
warn: CommonCoreMvcTest.Controllers.HomeController[0]
发生异常了:尝试除以零。,调用堆栈: 在 CommonCoreMvcTest.Controllers.HomeController.Index() 位置 E:\xxx\Test\CommonCoreMvcTest\Controllers\HomeController.cs:行号 28
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.Exception: 这是一个测试错误
在 CommonCoreMvcTest.Controllers.HomeController.Index() 位置 E:\xxx\Test\CommonCoreMvcTest\Controllers\HomeController.cs:行号 36
在 lambda_method(Closure , Object , Object[] )
在 Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
--- 引发异常的上一位置中堆栈跟踪的末尾 ---
……

添加web.config到源代码项目中

新建的asp.net core 2.2项目,默认没有web.config文件。得在网站发布后才能修改产生的web.config文件内容吗?没必要,可以通过“添加”、“新建项”、“Web配置文件”的方式,手动添加web.config文件到源码项目中。

使日志包含时间

asp.net core的日志不包含时间,这是个大问题,在3.0版本后,Console log provider可以配置时间格式了。经过搜索,我发现一个好用的第三方log provider:LoggingAdvanced.Console。可以用它来取代Console log provider。具体步骤如下:

1、安装nuget包LoggingAdvanced.Console

2、修改Program.cs的CreateWebHostBuilder方法,在其中的方法调用链的最后,调用ConfigureLogging方法,修改后的代码如下:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging((hostingContext, loggingBuilder) =>
{
loggingBuilder.ClearProviders();//清除所有logging provider loggingBuilder.AddDebug();//恢复添加Debug logging provider loggingBuilder.AddEventSourceLogger();//恢复添加EventSource logging provider var loggingSection = hostingContext.Configuration.GetSection("Logging"); loggingBuilder.AddConsoleAdvanced(loggingSection);//添加LoggingAdvanced.Console logging provider
});

3、修改appsettings.json的中的Logging部分,修改后如下:

"Logging": {
"IncludeTimestamp": true,
"IncludeLogNamespace": true,
"TimestampPolicy": {
"TimeZone": "Ulaanbaatar Standard Time",
"Format": "yyyy/MM/dd HH:mm:ss.fff"
},
"LogLevel": {
"Default": "Warning"
}
}

输出的部分日志:

[2020.03.07 22:39:36] info: HomeController: 访问主页
[2020.03.07 22:39:36] warn: HomeController: 发生异常了:尝试除以零。,调用堆栈: 在 CommonCoreMvcTest.Controllers.HomeController.Index() 位置 E:\xxx\Test\CommonCoreMvcTest\Controllers\HomeController.cs:行号 28
[2020.03.07 22:39:36] fail: ExceptionHandlerMiddleware[1]: An unhandled exception has occurred while executing the request.
System.Exception: 这是一个测试错误
在 CommonCoreMvcTest.Controllers.HomeController.Index() 位置 E:\xxx\Test\CommonCoreMvcTest\Controllers\HomeController.cs:行号 36
在 lambda_method(Closure , Object , Object[] )
在 Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
……

技巧

用浏览器查看.log文件,日志有更新,刷新一下就好了。

参考资料

1、Logging in .NET Core and ASP.NET Core

2、LoggingAdvanced.Console

总结:利用asp.net core日志进行生产环境下的错误排查(asp.net core version 2.2,用IIS做服务器)的更多相关文章

  1. Python开发程序:生产环境下实时统计网站访问日志信息

    日志实时分析系统 生产环境下有需求:要每搁五分钟统计下这段时间内的网站访问量.UV.独立IP等信息,用直观的数据表格表现出来 环境描述: 网站为Nginx服务,系统每日凌晨会对日志进行分割,拷贝到其他 ...

  2. Python开发【项目】:生产环境下实时统计网站访问日志信息

    日志实时分析系统 生产环境下有需求:要每搁五分钟统计下这段时间内的网站访问量.UV.独立IP等信息,用直观的数据表格表现出来 环境描述: 网站为Nginx服务,系统每日凌晨会对日志进行分割,拷贝到其他 ...

  3. 四步法分析定位生产环境下MySQL上千条SQL中的问题所在

    第一步:通过以下两种方式之一来打开慢查询功能 (1)方式一:通过修改mysql的my.cnf文件 如果是5.0或5.1等版本需要增加以下选项: log-slow-queries="mysql ...

  4. 生产环境下JAVA进程高CPU占用故障排查

    问题描述:生产环境下的某台tomcat7服务器,在刚发布时的时候一切都很正常,在运行一段时间后就出现CPU占用很高的问题,基本上是负载一天比一天高. 问题分析:1,程序属于CPU密集型,和开发沟通过, ...

  5. 生产环境下JAVA进程高CPU占用故障排查---temp

    问题描述:生产环境下的某台tomcat7服务器,在刚发布时的时候一切都很正常,在运行一段时间后就出现CPU占用很高的问题,基本上是负载一天比一天高. 问题分析:1,程序属于CPU密集型,和开发沟通过, ...

  6. 生产环境下,MySQL大事务操作导致的回滚解决方案

    如果mysql中有正在执行的大事务DML语句,此时不能直接将该进程kill,否则会引发回滚,非常消耗数据库资源和性能,生产环境下会导致重大生产事故. 如果事务操作的语句非常之多,并且没有办法等待那么久 ...

  7. 生产环境下,oracle不同用户间的数据迁移。第三部分

    任务名称:生产环境下schema ELON数据迁移至schema TIAN########################################前期准备:1:确认ELON用户下的对象状态se ...

  8. Java生产环境下性能监控与调优详解视频教程 百度云 网盘

    集数合计:9章Java视频教程详情描述:A0193<Java生产环境下性能监控与调优详解视频教程>软件开发只是第一步,上线后的性能监控与调优才是更为重要的一步本课程将为你讲解如何在生产环境 ...

  9. 生产环境下一定要开启mysqlbinlog

    在没有备份数据库的情况下,可以用binlog进行恢复 在生产环境下安全第一,损失一点点效率换来的安全还是值得的. http://www.cnblogs.com/zc22/archive/2013/06 ...

随机推荐

  1. HashMap相关知识

    HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么为何这道面试题如此 ...

  2. WIN10 蓝牙连接音箱之后,音量调节无效,音量从1-100,声音一样大,都是最大声,可以静音(解决方案)

    1.win+r,输入regedit,打开注册表2.进入路径:计算机\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Bluetooth\Audio\AV ...

  3. cs231n spring 2017 lecture5 Convolutional Neural Networks

    1. 之前课程里,一个32*32*3的图像被展成3072*1的向量,左乘大小为10*3072的权重矩阵W,可以得到一个10*1的得分,分别对应10类标签. 在Convolution Layer里,图像 ...

  4. rocket mq 入门文档

    原文地址: http://jm.taobao.org/2017/01/12/rocketmq-quick-start-in-10-minutes/ 感谢原作者 十分钟入门RocketMQ 本文首先引出 ...

  5. Listary快速查找文件

    快速查找文件 https://www.listary.com/

  6. unittest(22)- p2p项目实战(3)-project_path

    # 3. project_path.py # 用来读取文件的路径 import os # os.path.split(path)使用: # 1.path如果是具体到文件名,则返回最后层级的文件,和文件 ...

  7. 缓存系统——redis数据库

    缓存系统有:mongodb.redis(速度更快).memcache 学习memcached 参考:http://www.cnblogs.com/wupeiqi/articles/5132791.ht ...

  8. JSP Connect Database

    JDBC简介 在Java技术中,访问数据库的技术叫做JDBC,它提供了一系列的API,让Java语言编写的代码连接数据库,对数据库进行添加.删除.修改和查询. JDBC相关的API存在java.sql ...

  9. 在JavaScript里的“对象字面量”是什么意思?

    字面量表示如何表达这个值,一般除去表达式,给变量赋值时,等号右边都可以认为是字面量.字面量分为字符串字面量(string literal ).数组字面量(array literal)和对象字面量(ob ...

  10. 1078 Hashing (25 分)

    1078 Hashing (25 分) The task of this problem is simple: insert a sequence of distinct positive integ ...