概述

调试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级别的日志:

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

一条Information级别的日志:

  1. info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
  2. 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:

  1. "Logging": {
  2. "LogLevel": {
  3. "Default": "Information"
  4. }
  5. }

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

  1. "Logging": {
  2. "Debug": {
  3. "LogLevel": {
  4. "Default": "Information"
  5. }
  6. },
  7. "Console": {
  8. "LogLevel": {
  9. "Default": "Debug"
  10. }
  11. },
  12. "LogLevel": {
  13. "Default": "Debug"
  14. }
  15. },

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

  1. "Logging": {
  2. "Console": {
  3. "LogLevel": {
  4. "Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
  5. "Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
  6. "Microsoft.AspNetCore.Mvc.Razor": "Error",
  7. "Default": "Information"
  8. }
  9. },
  10. "LogLevel": {
  11. "Default": "Debug"
  12. }
  13. }

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

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

输出自己的日志

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

示例代码:

  1. public class HomeController : Controller
  2. {
  3. ILogger<HomeController> _logger;
  4.  
  5. public HomeController(ILogger<HomeController> logger)
  6. {
  7. _logger = logger;
  8. }
  9.  
  10. public IActionResult Index()
  11. {
  12. _logger.LogInformation("访问主页");
  13. try
  14. {
  15. int i = 0;
  16. int j = 1 / i;
  17. }
  18. catch (Exception ex)
  19. {
  20. _logger.LogWarning($"发生异常了:{ex.Message},调用堆栈:{ex.StackTrace}");
  21. }
  22. throw new Exception("这是一个测试错误");
  23.  
  24. return View();
  25. }
  26. }

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

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

添加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方法,修改后的代码如下:

  1. public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
  2. WebHost.CreateDefaultBuilder(args)
  3. .UseStartup<Startup>()
  4. .ConfigureLogging((hostingContext, loggingBuilder) =>
  5. {
  6. loggingBuilder.ClearProviders();//清除所有logging provider
  7.  
  8. loggingBuilder.AddDebug();//恢复添加Debug logging provider
  9.  
  10. loggingBuilder.AddEventSourceLogger();//恢复添加EventSource logging provider
  11.  
  12. var loggingSection = hostingContext.Configuration.GetSection("Logging");
  13.  
  14. loggingBuilder.AddConsoleAdvanced(loggingSection);//添加LoggingAdvanced.Console logging provider
  15. });

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

  1. "Logging": {
  2. "IncludeTimestamp": true,
  3. "IncludeLogNamespace": true,
  4. "TimestampPolicy": {
  5. "TimeZone": "Ulaanbaatar Standard Time",
  6. "Format": "yyyy/MM/dd HH:mm:ss.fff"
  7. },
  8. "LogLevel": {
  9. "Default": "Warning"
  10. }
  11. }

输出的部分日志:

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

技巧

用浏览器查看.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. 40)PHP,mysql_fetch_row,mysql_fetch_array,mysql_fetch_assoc的区别

    分析: mysql_fetch_row,这个函数是从结果集中取一行作为枚举数据,从和指定的结果标识关联的结果集中取得一行数据并作为数组返回.每个结果的列储存在一个数组的单元中,偏移量从 开始. 注意, ...

  2. day31-hmac模块检测客户端是否合法

    #如果客户端知道服务端的ip地址和端口,就可以连接服务端,信息不安全. #使用os.urandam随机生成32位bytes,然后hmac加密之后再发送给客户端. #server: import soc ...

  3. 在Python 中怎么表示一个元素在一个list中的数量?

    commonest = [1,2,2,2,1,3,4,5,1,1] print(commonest.count(1))

  4. Excel-DNA项目只用1个文件实现Ribbon CustomUI和CustomTaskpane定制【C#版】

    Excel-DNA项目中的自定义功能区和自定义任务窗格需要用到各种命名空间.添加所需文件,才能实现.后来我发现可以把所有代码都写在Class1.cs这个默认文件中. 大家可以在Visual Studi ...

  5. 基于TCP的大文件发送、UDP、socketserver

    基于TCP的大文件发送 #server服务端 import struct import json import os import socket server = socket.socket() # ...

  6. iOS仿抖音节拍界面、Swift,MVVM架构完整项目、日历demo、滚动切换分类等源码

    iOS精选源码 在Object-C中学习数据结构与算法之排序算法 日历-基本功能都有的日历 选择日期 上下月 动画 仿抖音卡节拍界面 垂直.水平方向皆可滚动.header悬浮的列表视图 Auto La ...

  7. django框架中的cookie与session

    cookie因为http是一个无状态协议,无法记录用户上一步的操作,所以需要状态保持.cookie和session的区别:1.cookie是保存在浏览器本地的,所以相对不安全.cookie是4k的大小 ...

  8. Chrome开发者调试工具

    参考资料 Chrome Console不完全指南 Chrome使用技巧 Chrome开发工具详解 结束语 工欲善其事,必先利其器.

  9. 从CVPR 2014看计算机视觉领域的最新热点

    2014看计算机视觉领域的最新热点" title="从CVPR 2014看计算机视觉领域的最新热点"> 编者按:2014年度计算机视觉方向的顶级会议CVPR上月落下 ...

  10. 关于前端使用JavaScript无法实现canvas打印问题的解决

    当使用浏览器的打印功能window.print()无法打印网页上的canvas图像,但是可以通过转换canvas成一个图片的形式来实现canvas的打印. 解决方法 getElementById获取c ...