.Net Core3.0 WebApi 项目框架搭建 十六:使用Serilog替换掉Log4j

为什么使用Serilog

Serilog 是一个用于.NET应用程序的日志记录开源库,配置简单,接口干净,并可运行在最新的.NET平台上,与其他日志库不同, Serilog 是以功能强大的结构化事件数据为基础构建的, 支持将日志输出到控制台、文件、数据库和其它更多的方式,支持参数化日志模板,非常灵活。

之前我们项目使用的是Log4j来记录用户日志的,在开发的过程中,慢慢的发现Log4j好像并不能满足我们的需求,比如结构化,日志分析等,于是决定使用serilog来替换掉Log4j,在使用的过程中发现Serilog还是很强大的。

删除原有的Log4j

1.卸载log4j包

2.删除log4j文件夹

3.删除startup的代码

 

 4.将log4j相关的代码删除

安装Serilog包

nuget安装以下几个包

配置Serilog

编辑Appsetting.json

  "Serilog": {
    "MinimumLevel": {
      "Default": "Debug", //最小日志记录级别
      "Override": { //系统日志最小记录级别
        "Default": "Warning",
        "System": "Warning",
        "Microsoft": "Warning"
      }
    },
    "WriteTo": [
      { "Name": "Console" }//输出到控制台
    ]
  },

program.cs将系统的logger替换为serilog

 public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
              .UseServiceProviderFactory(new AutofacServiceProviderFactory()) //<--NOTE THIS
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>()
                      .UseSerilog((context, logger) =>//注册Serilog
                      {
                          logger.ReadFrom.Configuration(context.Configuration);
                          logger.Enrich.FromLogContext();
                      });
        });

Test控制器注入logger,并修改LogTest方法。

        private readonly ILogger<TestController> _logger;

        public TestController(ILogger<TestController> logger)
        {
           _logger = logger;
        }
      /// <summary>
        /// 测试日志
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult LogTest()
        {
            //_logger.Error(typeof(TestController), "这是错误日志", new Exception("123"));
            //_logger.Debug(typeof(TestController), "这是bug日志");
            //throw new System.IO.IOException();
            _logger.LogInformation("info 日志");
            _logger.LogDebug("debug 日志");
            _logger.LogError(new System.IO.IOException(), "io 错误");
            return Ok();
        }

可以看到日志输出到了控制台

 配置Serilog输出到文件

appsetting.json增加配置

    "WriteTo": [
      { "Name": "Console" }, //输出到控制台
      {
        "Name": "Async", //Serilog.Sinks.Async
        "Args": {
          "configure": [
            {
              "Name": "File", //输出文件
              "Args": {
                "path": "log/log.txt",
                "outputTemplate": "{NewLine}Date:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel:{Level}{NewLine}Message:{Message}{NewLine}{Exception}",
                "rollingInterval": "3" //按天记录
              }
            }
          ]
        }
      }
      ]

启动项目测试

  生成了日志文件

输出到了数据库

 配置Serilog输出到数据库

appsetting.json配置

 {"Name": "Async", //Serilog.Sinks.Async
        "Args": {
          "configure": [
            {
              "Name": "File", //输出文件
              "Args": {
                "path": "log/log.txt",
                "outputTemplate": "{NewLine}Date:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel:{Level}{NewLine}Message:{Message}{NewLine}{Exception}",
                "rollingInterval": "3" //按天记录
              }
            },
            {
              "Name": "MSSqlServer", //输出到sqlserver
              "Args": {
                "connectionString": "Server=.;User Id=sa;Password=sa123;Database=ApiLog;MultipleActiveResultSets=true",
                "schemaName": "dbo", //数据库所有者,默认dbo
                "tableName": "Logs", // 记录日志的表名 
                "autoCreateSqlTable": true, // 是否自动创建表
                "restrictedToMinimumLevel": "Information", // 记录日志的最小level 
                "batchPostingLimit": 100, //单次批量处理中提交的最大日志数量
                "period": "0.00:00:30", //进行批量提交的间隔
                "columnOptionsSection": {
                  "disableTriggers": true,
                  "clusteredColumnstoreIndex": false,
                  "primaryKeyColumnName": "Id",
                  "addStandardColumns": [ "LogEvent" ],
                  "removeStandardColumns": [ "MessageTemplate" ],
                  "additionalColumns": [ //自定义列
                    {
                      "ColumnName": "Ip",
                      "DataType": "varchar",
                      "DataLength": 20
                    },
                    {
                      "ColumnName": "UserName",
                      "DataType": "varchar",
                      "DataLength": 30
                    },
                    {
                      "ColumnName": "UserId",
                      "DataType": "varchar",
                      "DataLength": 50
                    },
                    {
                      "ColumnName": "LogType",
                      "DataType": "tinyint"
                    },
                    {
                      "ColumnName": "Parameter"
                    },
                    {
                      "ColumnName": "Result"
                    }

                  ],
                  "id": { "nonClusteredIndex": true },
                  "properties": {
                    "columnName": "Properties",
                    "excludeAdditionalProperties": true,
                    "dictionaryElementName": "dict",
                    "itemElementName": "item",
                    "omitDictionaryContainerElement": false,
                    "omitSequenceContainerElement": false,
                    "omitStructureContainerElement": false,
                    "omitElementIfEmpty": true,
                    "propertyElementName": "prop",
                    "rootElementName": "root",
                    "sequenceElementName": "seq",
                    "structureElementName": "struct",
                    "usePropertyKeyAsElementName": false
                  },
                  "timeStamp": {
                    "columnName": "Timestamp",
                    "convertToUtc": true
                  },
                  "logEvent": {
                    "excludeAdditionalProperties": true,
                    "excludeStandardColumns": true
                  },
                  "message": { "columnName": "message" },
                  "exception": { "columnName": "exception" }
                }
              }
            }
          ]
        }
      }

Test控制器修改Aoptest方法,添加以下语句

_logger.LogInformation("ip:{IP},username{UserName},userid:{UserId}","127.0.0.1","admin","1");

启动项目,测试接口,数据库已经插入数据。

配置Serilog输出到Seq

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

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

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

安装完成之后,浏览器输出localhost:5341,会看到以下页面

 

 

appsetting.json配置输出到seq

           {
              "Name": "Seq", //输出到seq
              "Args": {
                "serverUrl": "http://192.168.0.89:5341"
              }
            },

启动项目,测试接口,可以通过页面看到数据。

 

 

 全局使用Serilog记录日志

在CustomExceptionMiddleware.cs直接这样

public class CustomExceptionMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly ILogger<CustomExceptionMiddleware> _logger;
        public CustomExceptionMiddleware(RequestDelegate next, ILogger<CustomExceptionMiddleware> logger)
        {
            _next = next;
        }
        public async Task Invoke(HttpContext httpContext)
        {
            try
            {
                await _next(httpContext);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message, ex); // 日志记录
                await HandleExceptionAsync(httpContext, ex.Message);
            }

GlobalExceptionsFilter中也一样

    public class GlobalExceptionsFilter : IExceptionFilter
    {
        private readonly IHostEnvironment _env;
        private readonly ILogger<GlobalExceptionsFilter> _logger;
        public GlobalExceptionsFilter(IHostEnvironment env, ILogger<GlobalExceptionsFilter> logger)
        {
            _env = env;
            _logger = logger;
        }


        public void OnException(ExceptionContext context)
        {
            var json = new JsonErrorResponse();
            json.Message = context.Exception.Message;//错误信息
            if (_env.IsDevelopment())
            {
                json.DevelopmentMessage = context.Exception.StackTrace;//堆栈信息
            }
            context.Result = new InternalServerErrorObjectResult(json);

            _logger.LogError(context.Exception, context.Exception.Message);
        }

如果想在服务层或仓储层用的话,安装这个包

 然后直接代码里用就行了

 

 

posted @ 2020-08-01 14:39  HuTiger  阅读(3239)  评论(14编辑  收藏  举报