.Net Core日志记录之第三方框架Serilog

一、前言

对内置日志系统的整体实现进行了介绍之后,可以通过使用内置记录器来实现日志的输出路径。而在实际项目开发中,使用第三方日志框架(如: Log4NetNLogLoggrSerilogSentry 等)来记录也是非常多的。首先一般基础的内置日志记录器在第三方日志框架中都有实现,然后第三方日志框架在功能上更加强大和丰富,能满足我们更多的项目分析和诊断的需求。

所以在这一篇中,我们将介绍第三方日志记录提供程序——Serilog

二、回顾

系统内置日志系列:

1. 基于.NetCore3.1系列 —— 日志记录之日志配置揭秘

2. 基于.NetCore3.1系列 —— 日志记录之日志核心要素揭秘

3. 基于.NetCore3.1系列 —— 日志记录之自定义日志组件

从之前学习的内置日志系统中,我们根据日志配置的方式了解到了通过配置的方式,可以有效的输出日志记录,方便我们查找发现问题。

而在进一步对内部运行的主要核心机制进行深入探究后发现了内置日志记录的几个核心要素,在日志工厂记录器(ILoggerFactory)中实现将日志记录提供器(ILoggerProvider)对象都可以集成到Logger对象组合中,这样的话,我们就可以通过基于ILoggerProvider自定义日志记录程序集成到Logger中,再创建写日志定义Ilogger,自定义日志记录器实现日志的输出方式,这样实现自定义日志记录工具。

在最后我们通过自定义的方式简单的实现了自定义日志组件,在这个基础上,我们可以根据具体的需求进行完善修改。当然了,我们也可以借用第三方日志框架组件程序进行使用。

三、说明

我们都知道日志记录在项目开发中或者生产环境中,都起到举足轻重的作用。因此,我们都会采用在项目加入第三方框架日志或自行封装日志记录来记录日志。

所以在这一篇中,我们会采用在项目中使用Serilog,目的不仅仅在于希望在用户使用之前发现代码中的BUG和错误,更多的是方便我们可以快速的查询生产环境的日志问题,深入的了解系统运行的表现。

Serilog的官方介绍中,我们可以发现 其框架是.net中的诊断日志库,可以在所有的.net平台上运行。支持结构化日志记录,对复杂、分布式、异步应用程序的支持非常出色。

Serilog是基于日志事件(log events),而不是日志消息(log message)。可以将日志事件格式化为控制台的可读文本或者将事件化为JSON格式。应用程序中的日志语句会创建LogEvent对象,而连接到管道的接收器(sinks)会知道如何记录它们。(接收器 包括各种终端、控制台、文本、SqlServer、ElasticSearch等等可用的列表

结构化与非结构化之间的问题

对于日志的处理,在大部分情况下,会权衡是否对开发者的友好型以及对程序解析的方便性。在很多情况下,开发者可能只是想记录一段日志而已,所以可以会考虑简单的加上一行代码来以达到记录日志的目的,如(log.debug("Disk quota {0} exceeded by user {1}", quota, user);)当然了,日志的执行结构可能被存于文本文件或者数据库中。这样的日志从开发者的角度来说,清晰易懂,十分友好。

但是如果后续要使用程序取查找海量的的上述例子在某段时间内的特定用户,则很难高效率地完成这一要求,因为需要对每个日志进行字符串解析。因此,我们就需要寻求更快更方便的方式来查找记录。

非结构的日志:

对自由格式文本的解析往往依赖于正则表达式,并且依赖于不变的文本。这会使解析自由格式的文本变得非常脆弱(即解析与代码中的确切文本紧密耦合)。

还考虑搜索/查找的情况,例如:

SELECT text FROM logs WHERE text LIKE "Disk quota";

LIKE条件需要与每个text行值进行比较;再次,这在计算上是相对浪费的,尤其是在使用通配符时:

SELECT text FROM logs WHERE text LIKE "Disk %";

结构化的日志:

使用结构化日志记录,与磁盘错误相关的日志消息在JSON中可能如下所示:

{ "level": "DEBUG", "user": "username", "error_type": "disk", "text": "Disk quota ... exceeded by user ..." }

这种结构的字段可以很容易地映射到例如 SQL表列名,这意味着查找可以更具体/更细粒度:

SELECT user, text FROM logs WHERE error_type = "disk";

您可以在希望经常搜索/查找其值的列上放置索引,只要您不对LIKE这些列值使用子句即可。您可以将日志消息细分为特定类别的内容越多,查找的对象就越有针对性。例如,除了error_type上面示例中的字段/列之外,您甚至可以设置为be "error_category": "disk", "error_type": "quota"或诸如此类。

结构越多,你的日志消息,通过解析/检索系统(如fluentdelasticsearchkibana),可以利用该结构,并以更快的速度和更低的CPU /内存执行任务。

总之这不仅与速度和效率有关,更重要的是使用结构化日志记录和“结构化查询”时,能以特定格式捕获以及呈现结构化日志,同时提供对开发者与程序友好的解析支持。可以更方便地以其为条件进行筛选,搜索结果的相关性将更高。如果没有这种搜索,那么在不同上下文中出现的任何单词都会给您带来大量无关的点击。

四、开始

为了更好的理解认识Serilog,我们这简单的创建一个新的项目来认识一下Serilog的使用。这里我们就简单的使用ConsoleDebug的方式来实现,后续有机会我们可以实现更多方式的接收器写入日志。

4.1 Serilog使用

4.1.1 安装依赖包

Serilog.AspNetCore : 基于AspNetCore框架整合的Serilog日志记录程序包,包含了Serilog基本库和控制台日志的实现。

当然了,你也可以直接安装Serilog 基本库,然后根据需要安装对应的拓展包。

说明:

  • Serilog.Extensions.Logging 包含了注入了Serilog的拓展方法。
  • Serilog.Sinks.Async 实现了日志异步收集。
  • Serilog.Sinks.Console 实现了控制台输出日志。
  • Serilog.Sinks.Debug 实现了调试台输出日志。
  • Serilog.Sinks.File 实现了文件输出日志。

4.1.2 配置Serilog

在应用程序中Program.cs文件中,配置Serilog记录,确保正确记录任何配置日志问题。

    public static void Main(string[] args)
    {
        Log.Logger = new LoggerConfiguration()
       .MinimumLevel.Debug()
       .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
       .Enrich.FromLogContext()
       .WriteTo.Console()
       .CreateLogger();

        try
        {
            Log.Information("Starting web host");
            CreateHostBuilder(args).Build().Run();
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Host terminated unexpectedly");
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }

然后,添加UseSerilog()CreateHostBuilder()中的通用主机中。

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args) //从appsettings.json中读取配置。
         .UseSerilog() // <-- Add this line
        .ConfigureLogging((hostingContext, logging) =>
        {
            logging.ClearProviders(); //去掉默认添加的日志提供程序
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });
}

最后,通过删除默认记录器的其余配置进行清理,从appsettings.json文件中删除Logging对应的配置部分。可以再使用根据Serilog的配置规则进行相应配置替换它。

"Serilog": {
    "MinimumLevel": {
        "Default": "Information",
        "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
        }
    }
}

4.1.3 提示

当在IIS下运行时候,要在Visual Studio输出窗口中查看Serilog输出日志的时候,需要将输出方式选择为 Web 服务器方式,输出窗口查看日志,或者使用WriteTo.Debug()替换记录器配置中的WriteTo.Console()

4.2 输出格式

4.2.1 文本格式

作为文本,它的格式如下:

[21:45:15 INF]  HTTP GET / responded 200 in 227.3253 ms

测试在控制台中输出如下:

上述事件格式中,可以看出由以下几个格式组成:

  • 事件发生时的时间戳[timestamp]
  • 描述何时应该捕获事件的级别[level]
  • 记录事件的消息[message]内容]
  • 描述事件的命名属性[properties]
  • 还可能有一个Exception对象

4.2.2 JSON格式

作为JSON格式,它的格式如下:

{
  "@t": "2020-08-27T13:59:44.6410761Z",
  "@mt": "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms",
  "@r": ["224.5185"],
  "RequestMethod": "GET",
  "RequestPath": "/",
  "StatusCode": 200,
  "Elapsed": 224.5185,
  "RequestId": "0HLNPVG1HI42T:00000001",
  "CorrelationId": null,
  "ConnectionId": "0HLNPVG1HI42T"
}

在写入日志文件中,根据Serilog的多种接收器的中(Console()、Debug()、File())等支持使用JSON写入日志记录,通过引用紧凑的JSON格式化类库[Serilog.Formatting.Compact]接收所有JSON格式的输出。

要编写以换行符分隔的JSON,请将CompactJsonFormatterRenderedCompactJsonFormatter传递到接收器配置方法,如下:

 .WriteTo.Console(new RenderedCompactJsonFormatter())
 或
  .WriteTo.Console(new CompactJsonFormatter())

运行这个程序将产生使用Serilog的紧凑格式JSON,并在对应的输出路径中生成换行符分隔的JSON流。

4.3 示例

4.3.1 安装依赖包

安装 Serilog.AspNetCore NuGet 包 ;

4.3.2 配置文件

appsettings.json配置文件添加 Serilog 配置,WriteTo 指定输出目标位置,它是一个数组类型,所以可以指定多个目标位置,这里暂时只指定输出到控制台:

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Debug"
    }
  }
}

4.3.3 设置配置信息

读取配置文件信息,设置配置信息

public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
           .SetBasePath(Directory.GetCurrentDirectory())
           .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
           .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
           .AddEnvironmentVariables()
           .Build();

在main方法中,

 public static void Main(string[] args)
 {
     Log.Logger = new LoggerConfiguration()
         .ReadFrom.Configuration(Configuration)
         .Enrich.FromLogContext()
         .WriteTo.Debug()   //输出路径
         .WriteTo.Console(
         outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}")    //模板
         .CreateLogger();
     try
     {
         Log.Information("Starting web host");
         CreateHostBuilder(args).Build().Run();
     }
     catch (Exception ex)
     {
         Log.Fatal(ex, "Host terminated unexpectedly");
     }
     finally
     {
         Log.CloseAndFlush();
     }
 }

Program.cs 添加 UseSerilog()

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
  .ConfigureWebHostDefaults(webBuilder =>
  {
      webBuilder.UseStartup<Startup>();
  })
  .UseSerilog();  //添加

4.3.4 设置请求管道

在 Startup.cs 的 中的Configure 请求管道中添加 UseSerilogRequestLogging

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
  if (env.IsDevelopment())
  {
    app.UseDeveloperExceptionPage();
  }
  app.UseStaticFiles();
  app.UseSerilogRequestLogging();

  app.UseRouting();

  app.UseAuthorization();

  app.UseEndpoints(endpoints =>
  {
    endpoints.MapControllers();
  });
}

重要的是UseSerilogRequestLogging()调用应出现在诸如MVC之类的处理程序之前。 中间件不会对管道中出现在它之前的组件进行时间或日志记录。通过将UseSerilogRequestLogging() 放在它们之后,可以将其用于从日志中排除杂乱的处理程序,例如UseStaticFiles()。)

为了减少每个HTTP请求需要构造,传输和存储的日志事件的数量。 在同一事件上具有许多属性还可以使请求详细信息和其他数据的关联更加容易。

默认情况下,以下请求信息将作为属性添加:

  • 请求方法
  • 请求路径
  • 状态码
  • 响应时间

您可以使用UseSerilogRequestLogging()上的选项回调来修改用于请求完成事件的消息模板,添加其他属性或更改事件级别:

app.UseSerilogRequestLogging(options =>
{
    // 自定义消息模板
    options.MessageTemplate = "Handled {RequestPath}";
    // 发出调试级别的事件,而不是默认事件
    options.GetLevel = (httpContext, elapsed, ex) => LogEventLevel.Debug;
    //将其他属性附加到请求完成事件
    options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
    {
        diagnosticContext.Set("RequestHost", httpContext.Request.Host.Value);
        diagnosticContext.Set("RequestScheme", httpContext.Request.Scheme);
    };
});

4.3.5 输出效果

由于日志总是输出一堆,我们不能快速的查找定位问题,其实 Serilog 输出的日志是非常简洁的,只有 HTTP GET ... 这一条,其他都是 AspNetCore 系统本身输出的,所以我们可以对输出的日志进行简化操作。

4.3.6 输出简化

为了使日志输出更简洁,我们可以设置不输出 AspNetCore Info 日志,只需在 Serilog配置节点中设置 AspNetCore 日志输出级别为 Warning

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Debug",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    }
  }
}

五、总结

  • 本篇主要是对Serilog的说明,认识到是一个基于日志事件的而非日志消息的结构化日志类库。
  • 简单的涉及对基础知识的认识以及使用,通过构建一个新的项目来实现Serilog的日志记录以及怎么使用这个框架。
  • 在后续中如何结合这个日志类库引入项目中使用,以及对日志怎么存储和查询进行说明(会考虑 ELK存储采集分析 )。
  • 如果有不对的或不理解的地方,希望大家可以多多指正,提出问题,一起讨论,不断学习,共同进步。
  • 本文中参考资料: 官方简介 、Serilog文档serilog-aspnetcore
  • 本文源码下载地址

到此这篇关于.Net Core日志记录之第三方框架Serilog的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • .NET日志框架Nlog使用介绍

    目录 快速安装 快速配置 快速使用 详解配置 添加支持Console输出 输出至CSV文件 配置日志大小 配置日志分级 配置生成规则 日志过滤器 条件语言 条件函数 NLog是一个基于.NET平台编写的类库,我们可以使用NLog在应用程序中添加极为完善的跟踪调试代码. NLog是一个简单灵活的.NET日志记录类库.通过使用NLog,我们可以在任何一种.NET语言中输出带有上下文的(contextual information)调试诊断信息,根据喜好配置其表现样式之后发送到一个或多个输出目标(ta

  • .Net使用日志框架NLog

    在Nuget中安装NLog NLog可以直接使用Nuget安装:PM > Install-Package Nlog 使用NLog NLog的使用方式基本上和其它的Log库差不多,分为Trace.Debug.Info.Error.Fatal五个等级 private static Logger logger = LogManager.GetCurrentClassLogger(); static void Main(string[] args) { logger.Trace("Trace Me

  • 解读ASP.NET 5 & MVC6系列教程(9):日志框架

    框架介绍 在之前的.NET中,微软还没有提供过像样的日志框架,目前能用的一些框架比如Log4Net.NLog.CommonLogging使用起来多多少少都有些费劲,和java的SLF4J根本无法相比.但在新版的ASP.NET5中,可谓是牛气冲天,微软提供的Microsoft.Framework.Logging框架集可谓就是.NET版的SLF4J,提供相应的接口,其它第三方组件可以根据接口实现自己的实现. ILoggerFactory接口 ILoggerFactory接口是日志的入库点,在系统中通

  • .net项目使用日志框架log4net

    目录 一.log4net简介 二.log4net结构 1.Logger: 2.APPender: 3.Filter: 4.Layout: 5.ObjectRender 三.Log4net参数: 四.Log4net日志分类 五.在配置中启用和关闭日志 六.log4net使用 1.引用log4net.dll文件 (1).在Nuget中下载log4net (2).在官网下载 2.在config文件中的配置 3.示例程序 一.log4net简介 Log4net是Apache下一个开放源码的项目,我们可以

  • .net新兴日志框架Serilog简介

    Serilog是.net下的新兴的日志框架,本文这里简单的介绍一下它的用法. 首先安装Nuget包: Install-Package Serilog Install-Package Serilog.Sinks.Console 其中包Serilog是Log核心库,Serilog.Sinks.Console是Log的控制台输出库,这个也是日志框架的一贯策略,一个核心库加多个输出库组合使用,这样可以保持良好的扩展性. 简单的示例: using (var log = new LoggerConfigur

  • .Net Core日志记录之第三方框架Serilog

    一.前言 对内置日志系统的整体实现进行了介绍之后,可以通过使用内置记录器来实现日志的输出路径.而在实际项目开发中,使用第三方日志框架(如: Log4Net.NLog.Loggr.Serilog.Sentry 等)来记录也是非常多的.首先一般基础的内置日志记录器在第三方日志框架中都有实现,然后第三方日志框架在功能上更加强大和丰富,能满足我们更多的项目分析和诊断的需求. 所以在这一篇中,我们将介绍第三方日志记录提供程序——Serilog 二.回顾 系统内置日志系列: 1. 基于.NetCore3.1

  • .Net Core日志记录之日志记录器

    目录 一.前言 二.说明 三.开始 3.1 日志记录器工厂 3.1.1 ILoggerFactory 接口 3.1.2 LoggerFactory 实现 CreateLogger 3.2日志记录提供器 3.2.1 ILoggerProvider 接口 3.3 日志记录器 3.3.1 ILogger 接口 3.3.2 Logger 实现 四.总结 一.前言 回顾:日志记录之日志配置揭秘 在上一篇中,我们已经了解了内置系统的默认配置和自定义配置的方式,在学习了配置的基础上,我们进一步的对日志在程序中

  • .Net Core日志记录之日志配置

    目录 一.前言 二.说明 三.开始 3.1 默认配置 3.2 自定义配置 3.2.1 代码添加提供程序 3.2.2 代码添加过滤器 3.2.3 配置文件自定义 四.问题 五.总结 一.前言 在项目的开发维护阶段,有时候我们关注的问题不仅仅在于功能的实现,甚至需要关注系统发布上线后遇到的问题能否及时的查找并解决.所以我们需要有一个好的解决方案来及时的定位错误的根源并做出正确及时的修复,这样才能不影响系统正常的运行状态. 这个时候我们发现,其实在asp.net core中已经内置了日志系统,并提供了

  • .Net Core日志记录之自定义日志组件

    一.前言 回顾:日志记录之日志核心要素揭秘 在上一篇中,我们通过学习了解在.net core 中内置的日志记录中的几大核心要素,在日志工厂记录器(ILoggerFactory)中实现将日志记录提供器(ILoggerProvider)对象都可以集成到Logger对象组合中,这样的话,我们就可以通过基于ILoggerProvider自定义日志记录程序集成到Logger中,再创建写日志定义Ilogger,自定义日志记录器实现日志的输出方式,这样实现自定义日志记录工具. 在这个过程中,日志记录器ILog

  • tp5框架使用composer实现日志记录功能示例

    本文实例讲述了tp5框架使用composer实现日志记录功能.分享给大家供大家参考,具体如下: tp5实现日志记录 1.安装 psr/log composer require psr/log 它的作用就是提供一套接口,实现正常的日志功能! 我们可以来细细的分析一下,LoggerInterface.php <?php namespace Psr\Log; /** * Describes a logger instance. * * The message MUST be a string or o

  • Laravel框架实现利用中间件进行操作日志记录功能

    本文实例讲述了Laravel框架实现利用中间件进行操作日志记录功能.分享给大家供大家参考,具体如下: 利用中间件进行操作日志记录过程: 1.创建中间件 php artisan make:middleware AdminOperationLog 2.生成了文件./app/Http/Middleware/AdminOperationLog.php 代码如下: <?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\R

  • Yii框架日志记录Logging操作示例

    本文实例讲述了Yii框架日志记录Logging操作.分享给大家供大家参考,具体如下: 1.Yii::getLogger()->log($message, $level, $category = 'application') 2.Yii::trace($message, $category = 'application'); 3.Yii::error($message, $category = 'application'); 4.Yii::warning($message, $category =

  • Spring框架实现AOP添加日志记录功能过程详解

    这篇文章主要介绍了Spring框架实现AOP添加日志记录功能过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 需求,在调用业务方法的时候,在被调用的业务方法的前面和后面添加上日志记录功能 整体架构: 日志处理类: package aop; import java.util.Arrays; import org.apache.log4j.Logger; import org.aspectj.lang.JoinPoint; //日志处理类 增

  • Log4j日志记录框架配置及用法解析

    任何一个系统都需要日志记录功能,以便开发调试,线上环境追溯问题. 常用的日志记录框架Log4j.其是apache的一个开源日志组件. #生产环境使用info #log4j.rootLogger = info,stdout,logfile #开发环境使用debug log4j.rootLogger = info,stdout,logfile log4j.logger.com.seecen.system.aop.advice = trace,aop log4j.appender.stdout = o

随机推荐