Asp.Net Core中利用Seq组件展示结构化日志功能

在一次.Net Core小项目的开发中,掌握的不够深入,对日志记录并没有好好利用,以至于一出现异常问题,都得跑动服务器上查看,那时一度怀疑自己肯定没学好,不然这一块日志不可能需要自己扒服务器日志来查看,果然,很多东西没掌握,至此,花点时间看了下日志的相关操作。利用日志服务来查看日志数据。

本文地址:https://www.cnblogs.com/CKExp/p/9246788.html

本文Demo的地址:https://gitee.com/530521314/LogPanel.git

一、日志记录的原则

  日志是为了方便我们观察应用程序是否正常运行,也是当运行不正常是,能够快速找到出现问题,定位问题的方式。

  有几条日志记录原则是我们大多都得遵循的:

  1、日志记录清晰,内容得让我们能够知道应用程序运行正常或运行不正常下能够有关键信息指明哪里出问题了。

  2、不要过度记录,一些场景下我们需要预判是否需要记录日志信息,我们能够控制日志记录的数量,同样,日志内容,要精简记录,无关紧要的文字,废话等无需加入。

  3、控制日志记录级别,或许在一个日志级别下记录了很多信息,可是其中的部分信息才是最为重要的,当调高一个记录级别,这部分最为重要的信息就展示出来了,那就直接调高级别吧。

  4、隐私保护,日志虽然是让开发运维人员看到,可是我们也不能所有信息都记录下来,用户的隐私信息我们得保护好。

二、内置日志组件

  Asp.Net Core中内置了日志组件,功能也很强大,首先来个简单示例:

  直接使用内置日志功能,无需在startup中加入另外的代码。

 1    private readonly ILogger<HomeController> _logger;
 2
 3     public HomeController(ILogger<HomeController> logger)
 4     {
 5         _logger = logger;
 6     }
 7
 8     public IActionResult Index()
 9     {
10         Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
11         _logger.LogDebug($"开始监控整个网站的日志信息_{DateTime.Now}");
12         //_logger.LogError($"开始监控整个网站的日志信息Error_{DateTime.Now}");
13         return View();
14     }

  在调试框下看到输出的日志信息。

  

  开始控制日志记录级别:

  在StartUp下,对内置日志组件做一些处理,在配置文件中将日志记录的级别提高到Information级别:

 1     public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 2     {
   3         //默认日志功能
 4         loggerFactory.AddConsole(Configuration.GetSection("Logging"));
 5         loggerFactory.AddDebug();
 6         //loggerFactory.AddSerilog();
 7
 8         if (env.IsDevelopment())
 9         {
10             app.UseBrowserLink();
11             app.UseDeveloperExceptionPage();//更多错误信息的开发者异常详情页
12         }
13         else
14         {
15             app.UseExceptionHandler("/Home/Error");
16         }
17
18         app.UseStaticFiles();
19
20         app.UseMvc(routes =>
21         {
22             routes.MapRoute(
23                 name: "default",
24                 template: "{controller=Home}/{action=Index}/{id?}");
25         });
26     }

  appsetting.json文件中,将LogLevel的默认级别设为Information,这样一来在之前的示例中_logger.LogDebug将失去作用。

 1 {
 2   "Logging": {
 3     "IncludeScopes": false,
 4     "LogLevel": {
 5       "Default": "Information",
 6       "System": "Error",
 7       "Microsoft": "Error"
 8     }
 9   }
10 }

  对于异常来讲,出现异常,日志肯定得记录下来,不然出现异常,直接抛出,那还要日志有什么用呢。

 1     public IActionResult About()
 2     {
 3         try
 4         {
 5             _logger.LogInformation($"业务逻辑执行前,运行正常");
 6             //执行其它业务逻辑
 7             int textInt = 5;
 8             int result = textInt / 0;
 9             //执行其它业务逻辑
10             _logger.LogInformation($"业务逻辑执行后,运行正常");
11         }
12         catch (Exception ex)
13         {
14             _logger.LogError($"出现异常,异常信息{ex.Message}");
15             throw;
16         }
17
18         return View();
19     }

  异常信息加载出来。

  

  出现异常,拦截异常,记录日志信息,不单单在这里,在Filter或是几个中间件中,都能够记录下来,此处不在多讨论。

三、第三方日志组件

  尽管微软已经内置了日志记录组件,但是一些第三方组件或许是我们中意的,在性能上、记录方式上、操作上等等,如Log4Net、Logger、NLog和Serilog 等。结构化的日志使得我们阅读日志也更加轻松点。

  在此,我利用Serilog组件来替换内置的日志组件,添加相应的依赖包(Serilog.Extensions.Logging和Serilog.Sinks.Literate)。

  然后来更新Startup类,令Serilog组件开始发挥它的作用。

  尽管可以在Program中加入Serilog组件,在这里,我将只在StartUp类中更改代码,为了代码统一存放,对于组件加入有三种方式:

  方式一在StartUp初始化完毕加入进来,利用Log.Logger的全局性,在整个应用程序中发挥作用,而不需要在各处声明注入。

  其中的 .WriteTo.Seq("http://localhost:5341")是为了后面加入Seq组件而提前写入的,可以忽略。

 1     public Startup(IConfiguration configuration)
 2     {
 3         Configuration = configuration;
 4         //方式一:配置Seq服务器的地址(5341端口为默认地址)
 5         Log.Logger = new LoggerConfiguration()
 6             .MinimumLevel.Debug()
 7             .MinimumLevel.Override("LoggingService", Serilog.Events.LogEventLevel.Debug)
 8             .Enrich.FromLogContext()
 9             .WriteTo.Seq("http://localhost:5341")
10             .WriteTo.LiterateConsole()
11             .CreateLogger();
12     }

  在应用程序中的使用方式是直接使用Log.Logger写入即可,如在HomeController的Contact方法中,利用且只能利用这种方式写入,当想用最开始那种方式注入时,在LoggerFactory中并没有SerilogProvider,因为我们并没有把Serilog加入到LoggerFactory中,这也使得Serilog和内置日志出现共存的局面,并可以通过两种方式使用日志功能。

1     public IActionResult Contact()
2     {
3         Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
4         Log.Debug("Log.Debug:Serilog Start Send Message");
5         Log.Information("Log.Information:Serilog Start send Message");
6         Log.Logger.Debug("Log.Logger:Serilog Start Send Message");
7         Log.Logger.Information("Log.Logger.Information:Serilog Start Send Message");
8         return View();
9     }

  利用这种方式下的日志输出。  

  

   方式二:在ConfigureServices中将Serilog加入到LoggerFactory中,通过统一的扩展方式加入进来,利用Action委托指定Serilog组件,其中允许我们对Serilog进行相关设置。

 1     public void ConfigureServices(IServiceCollection services)
 2     {
 3         //方式二
 4         var serilog = new LoggerConfiguration()
 5                 .MinimumLevel.Information()
 6                 .MinimumLevel.Override("LoggingService", Serilog.Events.LogEventLevel.Debug)
 7                 .Enrich.FromLogContext()
 8                 .WriteTo.Seq("http://localhost:5341")
 9                 .WriteTo.LiterateConsole();
10
11         services.AddLogging(loggerBuilder =>
12         {
13             loggerBuilder.AddSerilog(serilog.CreateLogger());
14         });
15         services.AddMvc();
16     }

  这种方式下,我们需要将Logger通过依赖注入的形式加入进来,先来看下是否加入到了LoggerFactory中

  

  加入进来了,并完成了日志的输出。

  

  方式三:和方式二一样都是加入到LoggerFactory中,但是直接利用的是Serilog提供的扩展方法AddSerilog加入进来。

 1     public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 2     {
 3         //默认日志功能
 4         //loggerFactory.AddConsole(Configuration.GetSection("Logging"));
 5         //loggerFactory.AddDebug();
 6
 7         #region Serilog
 8         //方式三
 9         //默认配置
10         //loggerFactory.AddSerilog();
11
12         //配置Seq服务器的地址(5341端口为默认地址)
13         //var serilog = new LoggerConfiguration()
14         //    .MinimumLevel.Information()
15         //    .MinimumLevel.Override("LoggingService", Serilog.Events.LogEventLevel.Debug)
16         //    .Enrich.FromLogContext()
17         //    .WriteTo.Seq("http://localhost:5341")
18         //    .WriteTo.LiterateConsole();
19         //loggerFactory.AddSerilog(serilog.CreateLogger());
20         #endregion
21
22         if (env.IsDevelopment())
23         {
24             app.UseBrowserLink();
25             app.UseDeveloperExceptionPage();//更多错误信息的开发者异常详情页
26         }
27         else
28         {
29             app.UseExceptionHandler("/Home/Error");
30         }
31
32         app.UseStaticFiles();
33
34         app.UseMvc(routes =>
35         {
36             routes.MapRoute(
37                 name: "default",
38                 template: "{controller=Home}/{action=Index}/{id?}");
39         });
40     }

  Serilog组件同源加入进来了,输出结果就不展示了和方式二一样的。

  

  具体Serilog的非常优秀的功能就不介绍了,请看Serilog的官方介绍 https://github.com/serilog

四、Seq组件

  到了本文的主题——Seq组件,通过网页UI的形式将日志展现出来,内容更加多样化,并赋予了更多功能日志搜索。

  首先,安装Seq组件,Seq下载地址:https://getseq.net/Download

  本地开发情形下是免费使用的,如果需要在生产环境中使用,需要商业许可(你懂的,money).在目前的版本中,4.2是只能够在windows下跑,也就是说我们如果是在windows下开发,在测试时可以借助这个方便的查看日志信息,按照给定的安装步骤完成安装。

  在应用程序中,我们通过Nuget管理Serilog.Sinks.Seq包,该组件隶属于Serilog旗下。Seq默认的端口是利用5341端口,如果我们想要使用其它端口,我们可以更改在应用程序中的地址

  以上一节的方式三为例,在其中加入一行.WriteTo.Seq(“http://localhost:5341”)便可指定Seq服务器地址。

1     var serilog = new LoggerConfiguration()
2         .MinimumLevel.Information()
3         .MinimumLevel.Override("LoggingService", Serilog.Events.LogEventLevel.Debug)
4         .Enrich.FromLogContext()
5         .WriteTo.Seq("http://localhost:5341")
6         .WriteTo.LiterateConsole();
7     loggerFactory.AddSerilog(serilog.CreateLogger());

  在本地windows运行起来看下,启动Seq服务器,当然,你这里或许需要配置一些账号密码之类的,都是小问题。

  

  启动应用程序,并进入那些写了日志的方法中,日志信息已经进来了,我们可以查看这些日志信息,并通过日志搜索功能搜索。

  

  

  在这里要说明一下,同时也在Seq组件的网站中也写明了。使用这些方式都可以直接使用Seq组件,第三方组件也不是必须的,直接利用Asp.Net Core的内置日志组件一样可以使用Seq组件。

     

  可是,Linux下可以吗? 假如我的开发环境在Linux下岂不是不行。现在有一个预览版5.0的,在Docker Hub中有Seq的镜像,虽然是预览版,可是我还是想试试。

  Docker Hub中Seq镜像地址:https://docs.getseq.net/v5.0/docs/docker

  现在,开始Linux中弄起来。

  首先完成镜像的爬取,之后会自动启动该镜像内部的服务。我们直接输入地址访问即可。默认地址ip:5341端口

docker run -e ACCEPT_EULA=Y -p 5341:80 datalust/seq:latest

  页面有了,Linux下看来也是可以的了,把应用程序通过Jenkins上都发布成功了,可是访问出现问题,Docker外部端口无法映射到内部端口,糟心,可是应该不是大问题,就此也就不弄日志信息的展示了。

  

  至此,日志相关的一系列知识简单带过,关键是Seq那个可视化日志界面,很nice。

  本文地址:https://www.cnblogs.com/CKExp/p/9246788.html

  本文Demo的地址:https://gitee.com/530521314/LogPanel.git

2018-6-30,望技术有成后能回来看见自己的脚步

原文地址:https://www.cnblogs.com/CKExp/p/9246788.html

时间: 2024-10-11 22:08:27

Asp.Net Core中利用Seq组件展示结构化日志功能的相关文章

ASP.NET Core中的ActionFilter与DI

一.简介 前几篇文章都是讲ASP.NET Core MVC中的依赖注入(DI)与扩展点的,也许大家都发现在ASP.NET CORE中所有的组件都是通过依赖注入来扩展的,而且面向一组功能就会有一组接口或抽象工厂来扩展功能,就如IControllerActivator这样的功能点在上篇文章(查看.NET Core源代码通过Autofac实现依赖注入到Controller属性)中也提到了,今天我们主要介绍一个大类似的扩展点,ASP.NET Core MVC中为我们提供了新的机制为Action Filt

ASP.NET Core 中的中间件

ASP.NET Core 中的中间件(Middleware) 在这个节中,我们将了解,ASP.NET Core 中的中间件是 什么?中间件很重要,尤其是在你想当架构师这一条路上. ASP.NET Core 中的中间件是 什么? 在 ASP.NET Core 中,中间件(Middleware)是一个可以处理 HTTP 请求或响应的软件管道. ASP.NET Core 中给中间件组件的定位是具有非常特定的用途.例如,我们可能有需要一个中间件组件验证用户,另一个中间件来处理错误,另一个中间件来提供静态

玩转ASP.NET Core中的日志组件

玩转ASP.NET Core中的日志组件简介日志组件,作为程序员使用频率最高的组件,给程序员开发调试程序提供了必要的信息.ASP.NET Core中内置了一个通用日志接口ILogger,并实现了多种内置的日志提供器,例如 ConsoleDebugEventSourceEventLogTraceSourceAzure App Service除了内置的日志提供器,ASP.NET Core还支持了多种第三方日志工具,例如 elmah.ioGelfJSNLogKissLog.netLoggrNLogSe

ASP.Net Core 中使用Zookeeper搭建分布式环境中的配置中心系列一:使用Zookeeper.Net组件演示基本的操作

前言:马上要过年了,祝大家新年快乐!在过年回家前分享一篇关于Zookeeper的文章,我们都知道现在微服务盛行,大数据.分布式系统中经常会使用到Zookeeper,它是微服务.分布式系统中必不可少的分布式协调框架.它的作用体现在分布式系统中解决了配置中心的问题,以及解决了在分布式环境中不同进程之间争夺资源的问题,也就是分布式锁的功能以及分布式消息队列功能等等.所以在微服务的环境中Zookeeper是现在很多公司首选的分布式协调框架,包括我之前的公司也在使用Zookeeper.说了这么多,没别的就

ASP.NET Core Web 应用程序系列(五)- 在ASP.NET Core中使用AutoMapper进行实体映射

原文:ASP.NET Core Web 应用程序系列(五)- 在ASP.NET Core中使用AutoMapper进行实体映射 本章主要简单介绍下在ASP.NET Core中如何使用AutoMapper进行实体映射.在正式进入主题之前我们来看下几个概念: 1.数据库持久化对象PO(Persistent Object):顾名思义,这个对象是用来将我们的数据持久化到数据库,一般来说,持久化对象中的字段会与数据库中对应的 table 保持一致. 2.视图对象VO(View Object):视图对象 V

在ASP.NET Core中使用Apworks开发数据服务:对HAL的支持

HAL,全称为Hypertext Application Language,它是一种简单的数据格式,它能以一种简单.统一的形式,在API中引入超链接特性,使得API的可发现性(discoverable)更强,并具有自描述的特点.使用了HAL的API会更容易地被第三方开源库所调用,并且使用起来也很方便,开发者可以像处理普通JSON数据那样去处理API数据.有关HAL的更多信息,可以参考官方网站:http://stateless.co/hal_specification.html.目前,很多REST

ASP.NET Core 中的依赖注入 [共7篇]

一.控制反转(IoC) ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了“标准化”,我们将这些标准化的组件称为服务,ASP.NET在内部专门维护了一个DI容器来提供所需的服务.要了解这个DI容器以及现实其中的服务提供机制,我们先得知道什么是DI(Dependence Injection),而一旦我们提到DI,又不得不说IoC(Inverse of Control)… [

【翻译】介绍 ASP.NET Core 中的 Razor Pages

介绍 ASP.NET Core 中的 Razor Pages 原文地址:Introduction to Razor Pages in ASP.NET Core         译文地址:介绍 asp.net core 中的 Razor Pages          翻译:ganqiyin Razor Pages 是 ASP.NET Core MVC 的一个新功能,可以让基于页面的编程方案更容易,更高效. 如果您正在寻找使用 Model-View-Controller 的教程,请参阅ASP.NET

[译]ASP.NET Core中使用MediatR实现命令和中介者模式

作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9866068.html 在本文中,我将解释命令模式,以及如何利用基于命令模式的第三方库来实现它们,以及如何在ASP.NET Core中使用它来解决我们的问题并使代码简洁.因此,我们将通过下面的主题来进行相关的讲解. 什么是命令模式? 命令模式的简单实例以及中介者模式的简单描述 MVC中的瘦控制器是什么?我们是如如何实现使控制器变瘦的? 我们如何在我们的.NET Core应用程序中使用MediatR 使用