.NET 中的日志采样

.NET 提供日志采样功能,使你能够控制应用程序发出的日志量,而不会丢失重要信息。 可以使用以下采样策略:

  • 基于跟踪的采样:基于当前跟踪的采样决策采样日志。
  • 随机概率采样:基于配置的概率规则对日志进行采样。
  • 自定义采样:实现自己的自定义采样策略。 有关详细信息,请参阅 “实现自定义采样”。

注释

一次只能使用一个采样器。 如果注册多个采样器,则使用最后一个采样器。

日志采样通过更精细地控制应用程序发出的日志来扩展 筛选功能 。 与其简单地启用或禁用日志,您可以通过配置采样比例来仅发出部分日志。

例如,虽然筛选通常使用概率( 0 不发出日志)或 1 (发出所有日志),但采样允许你选择介于两者之间的任何值,例如 0.1 发出 10 个日志%,或 0.25 发出 25 个%。

开始吧

若要开始,请安装 📦 Microsoft.Extensions.Telemetry NuGet 包:

dotnet add package Microsoft.Extensions.Telemetry

有关详细信息,请参阅 dotnet add package管理 .NET 应用程序中的包依赖项

配置基于跟踪的采样

基于跟踪的采样可确保日志被与底层Activity一致地采样。 如果要在跟踪和日志之间保持相关性,这非常有用。 可以启用跟踪采样(如 指南中所述),然后相应地配置基于跟踪的日志采样:

builder.Logging.AddTraceBasedSampler();

当启用基于跟踪的采样时,仅当基础 Activity 被采样时才会记录日志。 采样决策来自当前 Recorded 值。

配置随机概率采样

随机概率采样允许你根据配置的概率规则对日志进行采样。 可以定义以下特定规则:

  • 日志类别
  • 日志级别
  • 事件编号

有多种方法可以配置随机概率采样及其规则:

基于文件的配置

appsettings.json中创建配置部分,例如:

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

  "RandomProbabilisticSampler": {
    "Rules": [
      {
        "CategoryName": "Microsoft.AspNetCore.*",
        "Probability": 0.25,
        "LogLevel": "Information"
      },
      {
        "CategoryName": "System.*",
        "Probability": 0.1
      },
      {
        "EventId": 1001,
        "Probability": 0.05
      }
    ]
  }
}

上述配置:

  • 从所有级别开始 System. 的类别中的日志示例 10%。
  • 从以 Microsoft.AspNetCore. 开头的类别中抽取 25% 的日志样本 LogLevel.Information
  • 包含事件 ID 为 1001 的所有类别和级别日志的示例 5%。
  • 从所有其他日志中采样 100%。

重要

该值 Probability 表示值为 0 到 1 的概率。 例如,0.25 表示将采集25单位的% 日志。 0 表示不会采样任何日志,1 表示将采样所有日志。 这些包含 0 和 1 的案例可以有效地禁用或启用特定规则的所有日志。 概率不能小于 0 或大于 1,如果这种情况发生在应用程序中,则会引发异常。

要将采样器与配置进行注册,请按以下代码操作:

builder.Logging.AddRandomProbabilisticSampler(builder.Configuration);

更改正在运行的应用中的采样规则

随机概率采样支持通过 IOptionsMonitor<TOptions> 接口进行运行时配置更新。 如果使用支持重载的配置提供程序(如 文件配置提供程序),则可以在运行时更新采样规则,而无需重启应用程序。

例如,可以使用以下 appsettings.json 启动应用程序,它实际上充当 no-op:

{
  "Logging": {
    "RandomProbabilisticSampler": {
      "Rules": [
        {
          "Probability": 1
        }
      ]
    }
  }
}

在应用运行时,可以使用以下配置更新 appsettings.json

{
  "Logging": {
    "RandomProbabilisticSampler": {
      "Rules": [
        {
          "Probability": 0.01,
          "LogLevel": "Information"
        }
      ]
    }
  }
}

例如,根据上述配置,新规则将被自动应用,例如,带有 LogLevel.Information 标记的% 类日志中,有 1 个会被采样。

如何应用采样规则

该算法与 日志筛选非常相似,但存在一些差异。

对每个日志记录执行日志采样规则评估,但存在性能优化,例如缓存。 以下算法用于给定类别的每个日志记录:

  • 选择等于或高于记录器日志级别的规则 LogLevel
  • 选择 EventId 未定义或已定义且等于日志事件 ID 的规则。
  • 选择具有最长匹配类别前缀的规则。 如果找不到任何匹配项,则选择未指定类别的所有规则。
  • 如果选择了多条规则,则采用最后一条 。
  • 如果未选择任何规则,则不会应用采样,例如,日志记录会照常发出。

内联代码配置

builder.Logging.AddRandomProbabilisticSampler(options =>
{
    options.Rules.Add(
        new RandomProbabilisticSamplerFilterRule(
            probability: 0.05d,
            eventId : 1001));
});

上述配置:

  • 包含事件 ID 为 1001 的所有类别和级别日志的示例 5%。
  • 从所有其他日志中采样 100%。

简单概率配置

对于基本方案,可以配置适用于指定级别或以下的所有日志的单个概率值:

builder.Logging.AddRandomProbabilisticSampler(0.01, LogLevel.Information);
builder.Logging.AddRandomProbabilisticSampler(0.1, LogLevel.Warning);

上面的代码注册了采样器,该采样器将采集 10 次% 类型的 Warning 日志,以及 1 次% 类型的 Information(及以下)日志。 如果配置中没有为 Information 设置规则,则会采集 Warning 日志以及以下所有级别的日志(包括 Information),总计 10%。

实现自定义采样

可以通过从 LoggingSampler 抽象类派生并重写其抽象成员来创建自定义采样策略。 这样,就可以根据特定要求定制采样行为。 例如,自定义采样器可以:

  • 根据日志状态中特定键/值对的状态和值进行采样决策。
  • 仅当预定义时间间隔内的日志数保持在低于特定阈值时,才应用速率限制逻辑,例如发出日志。

若要实现自定义采样器,请执行以下步骤:

  1. 创建继承自 LoggingSampler. 的类。
  2. LoggingSampler.ShouldSample重写方法以定义自定义采样逻辑。
  3. 使用 AddSampler 扩展方法在日志记录管道中注册自定义采样器。

对于未筛选出的每个日志记录,该方法 LoggingSampler.ShouldSample 将完全调用一次。 其返回值确定是否应发出日志记录。

性能注意事项

日志采样旨在降低存储成本,但需要平衡的是 CPU 使用率略有增加。 如果您的应用程序生成大量且存储成本高昂的日志,抽样有助于减少这些日志的数量。 正确配置时,采样可以降低存储成本,而不会丢失诊断事件至关重要的信息。

有关内置采样,请参阅 基准

有关何时使用采样的日志级别指南

日志级别 建议
Trace 请勿应用采样处理,因为在生产环境中通常会禁用这些日志
Debug 请勿应用采样处理,因为在生产环境中通常会禁用这些日志
Information 务必进行采样
Warning 可以考虑采取采样技术
Error 不要应用采样
Critical 不要应用采样

最佳做法

  • 从更高的采样率开始,并根据需要向下调整。
  • 使用基于类别的规则以特定组件为目标。
  • 如果使用分布式跟踪,请考虑实现基于跟踪的采样。
  • 共同监视采样规则的有效性。
  • 为应用程序找到适当的平衡 - 采样率过低可以降低可观测性,而过高的速率可能会增加成本。

另请参阅