.net core 序列日志Serilog

Serilog 是一个用于 .NET 应用程序的诊断日志库。它易于设置,具有干净的 API,并且可以在所有最新的 .NET 平台上运行。尽管即使在最简单的应用程序中它也很有用,但 Serilog 对结构化日志记录的支持在检测复杂、分布式和异步应用程序和系统时大放异彩。

Serilog

与 .NET 的许多其他库一样,Serilog 为文件控制台许多其他输出提供诊断日志记录。

var log = new LoggerConfiguration()
    .WriteTo.Console()
    .WriteTo.File("log.txt")
    .CreateLogger();

log.Information("Hello, Serilog!");

与其他日志库不同,Serilog 是从头开始构建的,用于记录结构化事件数据

var position = new { Latitude = 25, Longitude = 134 };
var elapsedMs = 34;

log.Information("Processed {@Position} in {Elapsed} ms", position, elapsedMs);

Serilog 使用消息模板,这是一种简单的 DSL,它使用命名参数和位置参数扩展 .NET 格式字符串。Serilog 不会立即将事件格式化为文本,而是捕获与每个命名参数关联的值。

上面的示例在日志事件中记录了两个属性Position和。前面Elapsed的操作符告诉 Serilog序列化传入的对象,而不是使用Serilog 对结构化事件数据的深入而丰富的支持开辟了使用传统记录器时不可用的大量诊断可能性。@PositionToString()

例如,呈现为JSON 格式的这些属性会出现在时间戳、级别和消息旁边,例如:

{"Position": {"Latitude": 25, "Longitude": 134}, "Elapsed": 34}

能够记录结构化事件数据的后端使日志搜索和分析成为可能,而无需日志解析或正则表达式。

支持结构化数据并不意味着放弃文本:当 Serilog 将事件写入文件或控制台时,模板和属性会呈现为友好的人类可读文本,就像传统的日志库会产生一样:

09:14:22 [INF] Processed {"Latitude": 25, "Longitude": 134} in 34 ms.

从 Serilog 1.x 升级?查看2.0 升级指南发行说明

特征

  • 社区支持并积极开发
  • 基于格式的日志 API,具有熟悉的级别,如DebugInformationWarningError
  • 可发现的 C# 配置语法和可选的XMLJSON配置支持
  • 启用时高效,关闭日志记录级别时开销极低
  • 一流的 .NET Core 支持,包括与 ASP.NET Core 的丰富集成
  • 支持全面的接收器,包括文件、控制台、本地和基于云的日志服务器、数据库和消息队列
  • 使用上下文信息对日志事件进行复杂的丰富,包括范围 ( LogContext) 属性、线程和进程标识符以及特定于域的相关 ID,例如HttpRequestId
  • 零共享状态Logger对象,具有可选的全局静态Log
  • LogEvent格式不可知的日志管道,可以以纯文本、JSON、内存对象(包括Rx 管道)和其他格式发出事件

入门

Serilog 是从 NuGet 安装的。要查看日志事件,还需要安装一个或多个接收器,这里我们将使用漂亮打印控制台接收器和滚动文件集:

dotnet add package Serilog
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.File

 

 

设置 Serilog 的最简单方法是使用静态Log类。ALoggerConfiguration用于创建和分配默认记录器。

using Serilog;

public class Program
{
    public static void Main()
    {
        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Information()
            .WriteTo.Console()
            .WriteTo.File("log.txt",
                rollingInterval: RollingInterval.Day,
                rollOnFileSizeLimit: true)
            .CreateLogger();
            
        Log.Information("Hello, Serilog!");
        
        Log.CloseAndFlush();
    }
}

如被动接受设备数据:

var deviceValue = $"dmv:{dmon.Uid},Value:{dmon.Value},Status:{dmon.Status},BoxNo:{dmon.BoxNo},Name:{dmon.Name},BoxId:{dmon.BoxId},GroupName:{dmon.GroupName},Timestamp:{dmon.Timestamp}";
Log.Information(deviceValue);

 

 

 

实践,从 NuGet 安装 Serilog

核心的包是 Serilog 和 Serilog.AspNetCore
建议安装 Serilog.AspNetCore,几乎包含了Serilog常用的所有包
异步写入 Serilog.Sinks.Async
写入MSSQL  Serilog.Sinks.MSSqlServer  

Install-Package Serilog.AspNetCore
Install-Package Serilog
Install-Package Serilog.Sinks.Async
Install-Package Serilog.Sinks.MSSqlServer

 

日志输出

输出到控制台

复制代码
 1 using Serilog;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.ComponentModel;
 5 using System.IO;
 6 using System.Linq;
 7 
 8 namespace NetCoreConsoleApp
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             Log.Logger = new LoggerConfiguration()
15             .WriteTo.Console()  //输出到控制台
16             .CreateLogger();
17 
18             Log.Information("log");
19 
20         }
21  
22 
23     }
24 }
复制代码

 

 

输出到本地日志文件

WriteTo.File详解(日志默认路径为当前程序路径)

     path:默认路径是程序的bin目录+path参数,当然也可以写绝对路径,只需要写入参数就可以了
     rollingInterval:创建文件的类别,可以是分钟,小时,天,月。 此参数可以让创建的log文件名默认 + 时间。例如:log20191219.log
     outputTemplate:日志模板,可以自定义
     retainedFileCountLimit:设置日志文件个数最大值,默认31,意思就是只保留最近的31个日志文件,等于null时永远保留文件

 

复制代码
 1 using Serilog;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.ComponentModel;
 5 using System.IO;
 6 using System.Linq;
 7 
 8 namespace NetCoreConsoleApp
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             /*
15             WriteTo.File详解 
16                 path:默认路径是程序的bin目录+path参数,当然也可以写绝对路径,只需要写入参数就可以了
17                 rollingInterval:创建文件的类别,可以是分钟,小时,天,月。 此参数可以让创建的log文件名 + 时间。例如log20191219.log
18                 outputTemplate:日志模板,可以自定义
19                 retainedFileCountLimit:设置日志文件个数最大值,默认31,意思就是只保留最近的31个日志文件,等于null时永远保留文件
20              */
21 
22 
23             string SerilogOutputTemplate = "{NewLine}{NewLine}Date:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel:{Level}{NewLine}Message:{Message}{NewLine}{Exception}" + new string('-', 100);
24 
25             Log.Logger = new LoggerConfiguration()
26               .MinimumLevel.Debug() // 所有Sink的最小记录级别
27               .WriteTo.Console()    //输出到控制台
28               .WriteTo.File("00_Logs\\log.log", //$"{AppContext.BaseDirectory}00_Logs\log.log"
29                             rollingInterval: RollingInterval.Day,
30                             outputTemplate: SerilogOutputTemplate
31                             //,retainedFileCountLimit: 31
32                             )
33               .CreateLogger();
34             Log.Information("log");
35         }
36     }
37 }
复制代码

 

输出到本地日志文件(异步)

需要Serilog.Sinks.Async包,github详解路径:https://github.com/serilog/serilog-sinks-async

 

复制代码
 1 using Serilog;
 2 
 3 namespace NetCoreConsoleApp
 4 {
 5     class Program
 6     {
 7         static void Main(string[] args)
 8         {
 9             //github详解路径:https://github.com/serilog/serilog-sinks-async
10 
11             Log.Logger = new LoggerConfiguration()
12           .WriteTo.Async(a => a.File("00_Logs\\log.log", rollingInterval: RollingInterval.Day))
13           .CreateLogger();
14             Log.Information("log");
15             Log.CloseAndFlush();
16         }
17     }
18 }
复制代码

 

不同的日志级别输出到不同的文件夹下

 

复制代码
using Serilog;
using Serilog.Events;
using System;

namespace NetCoreConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            string LogFilePath(string LogEvent) => $@"{AppContext.BaseDirectory}00_Logs\{LogEvent}\log.log";
            string SerilogOutputTemplate = "{NewLine}{NewLine}Date:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel:{Level}{NewLine}Message:{Message}{NewLine}{Exception}" + new string('-', 50);

            Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.WriteTo.Console()
.MinimumLevel.Debug() // 所有Sink的最小记录级别
.WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Debug).WriteTo.File(LogFilePath("Debug"), rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Information).WriteTo.File(LogFilePath("Information"), rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Warning).WriteTo.File(LogFilePath("Warning"), rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Error).WriteTo.File(LogFilePath("Error"), rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Fatal).WriteTo.File(LogFilePath("Fatal"), rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.CreateLogger();

            Log.Information("log");
            Log.Error("log");
        }
    }
}
复制代码

 

输出到MSSQL 

需要Serilog.Sinks.MSSqlServer包github详解路径:https://github.com/serilog/serilog-sinks-mssqlserver

参考链接:https://www.cnblogs.com/lonelyxmas/p/11980881.html

复制代码
using Serilog;
using Serilog.Events;
using Serilog.Sinks.MSSqlServer;
using System;
using System.Collections.ObjectModel;
using System.Data;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {


            string connectionString = @"Server=....";string tableNameA = "LogsA";
            string tableNameB = "LogsB";
            string tableNameC = "LogsC";
            static void Write()
            {
                Log.Information("测试信息");
                Log.Error("Error");
                Log.Write(LogEventLevel.Error, new Exception("错误"), "致命错误");
            };


            //A:默认配置
            //autoCreateSqlTable为true 时 会自动创建日志表
            Log.Logger = new LoggerConfiguration().WriteTo.MSSqlServer(connectionString, tableNameA, autoCreateSqlTable: true).CreateLogger();
            Write();


            //B:移除列
            var options = new ColumnOptions();
            options.Store.Remove(StandardColumn.Properties);
            options.Store.Remove(StandardColumn.MessageTemplate);
            Log.Logger = new LoggerConfiguration()
                         .WriteTo.MSSqlServer(connectionString, tableNameB, columnOptions: options, autoCreateSqlTable: true)
                         .CreateLogger();
            Write();


            //C:添加自定义列
            options = new ColumnOptions();
            options.AdditionalColumns = new Collection<SqlColumn>
                {
                    new SqlColumn { DataType = SqlDbType.NVarChar, DataLength =-1, ColumnName = "IP" },
                    new SqlColumn { DataType = SqlDbType.NVarChar, DataLength =-1, ColumnName = "IP2" }
                };
            Log.Logger = new LoggerConfiguration()
                             .Enrich.WithProperty("IP", "8.8.8.8")
                             .Enrich.WithProperty("IP2", "9.9.9.9")
                             .WriteTo.MSSqlServer(connectionString, tableNameC, columnOptions: options, autoCreateSqlTable: true)
                             .CreateLogger();
            Write();



            Console.WriteLine("Hello World!");
            Console.ReadKey();

        }
    }
}
复制代码

 

 

 ASP.NET Core 中使用 Serilog

参考链接:https://www.cnblogs.com/MaleDeer/p/10797509.html

在Program.cs程序启动时注入Serilog 加载配置

复制代码
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Serilog;

namespace WebApplication1
{
    public class Program
    {
        public static void Main(string[] args)
        {

            Log.Logger = new LoggerConfiguration()
             .MinimumLevel.Debug()
             .WriteTo.Console()
             .WriteTo.File($"{AppContext.BaseDirectory}00_Logs\\log.log", rollingInterval: RollingInterval.Day)
             .CreateLogger();

            try
            {
                Log.Information("Starting up");
                CreateHostBuilder(args).Build().Run();
            }
            catch (Exception ex)
            {
                Log.Fatal(ex, "Application start-up failed");
            }
            finally
            {
                Log.CloseAndFlush();
            }
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                })
            .UseSerilog();
    }
}
复制代码

或者

复制代码
using System;using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Serilog;

namespace WebApplication1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();

        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                    webBuilder.UseSerilog((hostingContext, loggerConfiguration) =>
                    {
                        loggerConfiguration
                       .ReadFrom.Configuration(hostingContext.Configuration)
                       .Enrich.FromLogContext()
                       .WriteTo.File($"{AppContext.BaseDirectory}00_Logs\\log.log", rollingInterval: RollingInterval.Day)
                       .WriteTo.Console();
                    });
                });
    }
}
复制代码

 

 

使用 Serilog 时,直接使用 ILogger 即可,因为此服务项目应该是默认注入了,此处需要依赖关系注入知识。如你不了解依赖关系注入,请看 微软官方文档

复制代码
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace WebApplication1.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        private readonly ILogger<ValuesController> _logger;

        public ValuesController(ILogger<ValuesController> logger)
        {
            _logger = logger;
        }

        // GET api/values
        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            _logger.LogInformation("test info");
            return new string[] { "value1", "value2" };
        }
    }
}
复制代码

 

 

相关链接 

 
鸣谢:
https://www.cnblogs.com/RainFate/p/12073662.html
  
posted @ 2022-08-31 14:17  春光牛牛  阅读(795)  评论(0编辑  收藏  举报