Util应用框架基础(六) – 日志记录(一) – 正文

本文介绍Util应用框架如何记录日志.

日志记录共分4篇,本文是正文,后续还有3篇分别介绍写入不同日志接收器的安装和配置方法.

概述

日志记录对于了解执行情况非常重要.

Asp.Net Core 抽象了日志基础架构,支持使用日志提供进行扩展,提供控制台日志等简单实现.

Serilog 是 .Net 流行的第三方日志框架,支持结构化日志,并能与 Asp.Net Core 日志集成.

Serilog 支持多种日志接收器,可以将日志发送到不同的地方.

我们可以将日志写入文本,但查看文本文件比较困难,文件如果很大,查找问题非常费力.

对于,我们需要包含管理界面的.

Seq 是一个日志系统,可以很好的展示结构化日志数据,并提供模糊功能.

Exceptionless 是基于 Asp.Net Core 开发的日志系统.

与 Seq 相比,Exceptionless 搜索能力较弱.

Seq 和 Exceptionless 都提供了 Serilog 日志接收器,可以使用 Serilog 接入它们.

Util应用框架使用 Serilog 日志框架,同时集成了 SeqExceptionless 日志系统.

Util简化了日志配置,并对常用功能进行扩展.

日志配置

选择日志接收器

Util应用框架默认支持三种 Serilog 日志接收器:

  • 日志文件
  • Seq
  • Exceptionless

你可以从中选择一种或多种,如果都不能满足要求,你也可以引用 Serilog 支持的其它日志接收器,或自行实现.

配置日志接收器

请转到特定日志接收器章节查看配置方法.

配置日志级别

Asp.Net Core 使用日志级别表示日志的严重程度,定义如下:

  • Trace = 0
  • Debug = 1
  • Information = 2
  • Warning = 3
  • Error = 4
  • Critical = 5
  • None = 6

None不开启日志,Trace的严重程度最低,Critical的严重程度最高,需要高度关注.

可以在 appsettings.json 设置日志级别.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information"
    }
  }
}

Logging 配置节用于配置日志.

LogLevel 为所有日志提供程序配置日志级别.

Default 为所有日志类别设置默认的日志级别.

上面的配置将默认日志级别设置为 Information.

意味着只输出日志级别等于或大于 Information 的日志.

现在 Trace 和 Debug 两个级别的日志被禁用了.

可以为特定日志类别设置日志级别.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Debug",
    }
  }
}

配置增加了 Microsoft 日志类别,并设置为 Debug 日志级别.

日志类别用来给日志分类,一般使用带命名空间的类名作为日志类别.

日志类别支持模糊匹配, Microsoft 日志类别不仅匹配 Microsoft ,而且还能匹配以 Microsoft 开头的所有日志类别,比如 Microsoft.AspNetCore .

Serilog 的日志级别

Serilog 定义了自己的日志级别,不支持上面介绍的标准配置方式.

Exceptionless 也是如此.

使用第三方框架的日志级别会导致复杂性.

Util应用框架扩展了 Serilog 和 Exceptionless 的日志级别配置,允许以统一的标准方式进行配置.

记录日志

.Net 提供了标准的日志记录接口 Microsoft.Extensions.Logging.ILogger.

你可以使用 ILogger 记录日志.

Util应用框架还提供了一个 Util.Logging.ILog 接口.

当你需要写入很长的日志时,可能需要使用 StringBuilder 拼接日志内容.

ILog 提供了一种更简单的方式写入长内容日志.

使用 ILogger 记录日志

ILogger 支持泛型参数, 用来指定日志类别,使用带命名空间的类名作为日志类别.

ILogger 扩展了一些以 Log 开头的方法,比如 LogDebug,表示写入日志级别为 Debug 的消息.

logger.LogDebug( “Util” ) 以 Debug 日志级别写入消息'Util'.

使用 ILog 记录日志

Util应用框架定义了 ILog 接口.

ILog 是对 ILogger 接口的简单包装, 对日志内容的设置进行了扩展.

ILog 也使用泛型参数来指定日志类别.

使用 ILog 完成上面相同的示例.

Message 是 ILog 定义的方法, 用来设置日志消息,可以多次调用它拼接内容.

当你需要写比较长的日志内容, ILog 可以帮你拼接内容,这样省去了定义 StringBuilder 的麻烦.

可以在 ILog 添加自定义扩展方法来设置内容, Util应用框架内置了一些设置日志消息的扩展方法, 比如 AppendLine.

你可以定义自己的扩展方法,以更加语义化的方式记录日志.

范例:

ILog 与 ILogger 比较:

ILog 更擅长记录内容很长的日志.

ILog 是有状态服务,不能在多个线程共享使用.

可以使用 ILog 记录业务日志,其它场景应使用 ILogger.

结构化日志支持

Serilog 日志框架对结构化日志提供了支持.

结构化日志使用特定语法的消息模板日志格式,可以从日志文本中提取搜索元素.

结构化日志的优势主要体现在日志系统对日志消息的展示和搜索方式上.

不同的日志系统对结构化日志的展示方式和搜索能力不同.

请参考 Seq 和 Exceptionless 的 结构化日志支持 小节.

日志操作上下文

记录日志时,我们除了需要记录业务内容,还需要知道一些额外的信息,比如操作用户是谁.

我们希望记录日志时仅设置业务内容,这些额外的信息最好能自动记录.

Util应用框架通过日志上下文自动设置这些额外信息.

  • UserId 设置当前操作用户标识

  • Application 设置当前应用程序名称.

  • Environment 设置当前环境名称.

  • TraceId 设置跟踪号.

  • Stopwatch 设置计时器,用于记录请求执行花了多长时间.

在 Asp.Net Core 环境, 日志上下文由日志上下文中间件 Util.Applications.Logging.LogContextMiddleware 创建.

无需手工添加日志上下文中间件,只要引用 Util.Application.WebApi 类库, 就会自动添加到中间件管道.

对于 Web 请求, 跟踪号是一个重要的信息,可以通过查询跟踪号,将相关的请求日志全部查出来.

另外, Exceptionless 会自动收集很多.

源码解析

ILog 日志操作

ILog 日志操作接口提供链式调用方式设置日志内容.

  • Message 方法设置日志消息.

  • Property 方法设置扩展属性.

  • State 设置日志参数对象.

Log 开头的日志记录方法,将日志操作委托给 ILogger 相关方法.

ILogExtensions 日志操作扩展

Util应用框架内置了几个日志操作扩展方法,你可以定义自己的扩展方法,以方便内容设置.

/// 
/// 日志操作扩展
/// 
public static class ILogExtensions {
    /// 
    /// 添加消息
    /// 
    /// 
    /// 
    /// 
    public static ILog Append( this ILog log,string message, params object[] args ) {
        log.CheckNull( nameof( log ) );
        log.Message( message, args );
        return log;
    }

    /// 
    /// 当条件为true添加消息
    /// 
    /// 
    /// 
    /// 
    /// 
    public static ILog AppendIf( this ILog log, string message,bool condition, params object[] args ) {
        log.CheckNull( nameof( log ) );
        if ( condition )
            log.Message( message, args );
        return log;
    }

    /// 
    /// 添加消息并换行
    /// 
    /// 
    /// 
    /// 
    public static ILog AppendLine( this ILog log, string message, params object[] args ) {
        log.CheckNull( nameof( log ) );
        log.Message( message, args );
        log.Message( Environment.NewLine );
        return log;
    }

    /// 
    /// 当条件为true添加消息并换行
    /// 
    /// 
    /// 
    /// 
    /// 
    public static ILog AppendLineIf( this ILog log, string message, bool condition, params object[] args ) {
        log.CheckNull( nameof( log ) );
        if ( condition ) {
            log.Message( message, args );
            log.Message( Environment.NewLine );
        }
        return log;
    }

    /// 
    /// 消息换行
    /// 
    /// 
    public static ILog Line( this ILog log ) {
        log.CheckNull( nameof(log) );
        log.Message( Environment.NewLine );
        return log;
    }
}

LogContext 日志上下文

通过日志上下文自动记录重要的额外信息.

LogContextMiddleware 日志上下文中间件

日志上下文中间件创建日志上下文,并添加到 HttpContext 对象的 Items .

ILogContextAccessor 日志上下文访问器

日志上下文访问器从 HttpContext.Items 获取日志上下文.

LogContextEnricher 日志上下文扩展

Serilog 提供 ILogEventEnricher 接口用于设置扩展属性.

LogContextEnricher 使用 Ioc.Create 方法获取依赖服务 ILogContextAccessor.

这是因为不能使用依赖注入,它要求实现类必须是无参构造函数.

Ioc.Create 在 Asp.Net Core 环境获取依赖服务是的,但在其它环境则可能获取失败.

如果获取日志上下文失败,也不会对功能造成影响,只是丢失了一些上下文信息.

LoggerEnrichmentConfigurationExtensions

将 LogContextEnricher 扩展到 LoggerEnrichmentConfiguration 上.

AddSerilog 配置方法

AddSerilog 配置方法封装了 Serilog 的配置.

  • 配置 ILog 接口服务依赖.

  • 将 Asp.Net Core 日志级别转换为 Serilog 日志级别.

  • 设置日志上下文扩展.

AddExceptionless 配置方法

AddExceptionless 配置方法封装了 Serilog 和 Exceptionless 的配置.

  • 配置 ILog 接口服务依赖.

  • 将 Asp.Net Core 日志级别转换为 Exceptionless 日志级别.

  • 设置日志上下文扩展.

Util应用框架交流群: 24791014

欢迎转载
何镇汐的技术博客
扫描二维码支持Util

Util应用框架基础(六) - 日志记录(一) - 正文

给TA打赏
共{{data.count}}人
人已打赏
软件设计

分布式亿级流量整体架构设计原则

2023-11-18 14:24:32

软件设计

c#组合模式详解

2023-11-18 14:24:34

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索