WindPayer.Logging 1.1.2

安装

dotnet add package WindPayer.Logging

快速开始

// Program.cs
using WindPayer.Logging;
builder.UseWindpayerLogging();

// 正常的logger调用
// 文本信息推荐使用占位符形式,框架会自动解析出额外的结构化,以下写法会额外输出字段【id】
logger.LogInformation("这是一条日志 {id}", id);
// 不推荐写法
logger.LogInformation($"这是一条日志 {id}");

// 自定义额外信息,单次
_logger.LogCtxInformation(new { bid = 20251212 }, "这是一条日志 {id}", id);

// 范围生效
using(_logger.WithCtx(new { userId = 10001 })
{
    // 业务代码
    _logger.LogCtxInformation(new { bid = 20251212 }, "这是一条日志 {id}", id);
    // 业务代码
    _logger.LogCtxInformation(new { orderId = "123456" }, "这是一条日志 {id}", id);
    // 业务代码
}

// 不推荐直接使用 _logger.WithCtx(), 因为会在调用后整个请求生命周期内生效

// 使用 Module 做额外信息时,写文件日志时会自动把 Module 的值作为日志文件夹名称,可以使用 Module 来区分不同模块的日志
_logger.LogCtxInformation(new { Module = "文件夹" }, "这是一条日志 {id}", id);

RabbitMQ Trace 传播

当业务代码使用 RabbitMQ 时,可以通过本库提供的扩展方法在消息生产和消费时传播 Trace 上下文,使得整个调用链(HTTP → Queue → Consumer)的 Trace 完整连贯。

安装

业务项目需要添加 WindPayer.Logging 的项目引用:

<ProjectReference Include="..\WindPayer.Logging\WindPayer.Logging.csproj" />

然后确保 appsettings.json 中开启了 Trace(EnableOtlp 或 EnableTrace):

"WindpayerLogging": {
  "EnableOtlp": true,
  "OtlpEndpoint": "http://localhost:4317",
  ...
}

使用方式

1. 消费者端 — QueueWorker.ConsumerReceived

在消息到达时提取 Trace 上下文并创建 Consumer Activity:

private async Task ConsumerReceived(object? sender, BasicDeliverEventArgs e)
{
    string content = string.Empty;

    // ========== 提取 Trace 上下文 ==========
    using var activity = e.StartConsumerActivity($"rabbitmq consume {QueueName}");
    // ======================================

    try
    {
        // ... 原有处理逻辑不变
        var body = e.Body.ToArray();
        content = Encoding.UTF8.GetString(body);
        // ...
    }
    catch (Exception ex)
    {
        _logger?.LogError(ex, "处理消息异常");
    }
}

2. 生产者端 — QueueService.Publish(首次发布)

发布时注入当前 Trace 上下文到消息 Headers:

public void Publish(string exchange, string routingKey, string messageId, string body)
{
    var bodyArray = Encoding.UTF8.GetBytes(body);
    var properties = Channel.CreateBasicProperties();
    properties.Persistent = true;
    properties.MessageId = messageId;

    // ========== 注入 Trace 上下文 ==========
    properties.InjectTrace();
    // =====================================

    Channel.BasicPublish(exchange, routingKey, properties, bodyArray, mandatory: true);
}

3. 持久化 Trace Headers(重试时保持同一 TraceId)

如需在消息重试时保持原始 TraceId,首次发布后将 Trace Headers 提取为 JSON 存入数据库,重试时恢复。

TMessageQueue 实体新增字段:

public string? TraceHeaders { get; set; }   // JSON 格式 {"traceparent":"00-xxx-xxx-00","tracestate":"..."}

首次发布 — 保存 Headers:

// 在 Publish 后调用,将 Headers 保存到数据库
msg.TraceHeaders = TraceHelper.ExtractTraceHeadersJson();

重试发布 — 恢复 Headers:

// 从数据库读取保存的 Headers
var savedHeaders = TraceHelper.DeserializeTraceHeaders(msg.TraceHeaders);

_queueService.Publish(exchange, routingKey, msgId, body, savedHeaders);

QueueService.Publish 支持可选的 traceHeaders 参数:

public void Publish(string exchange, string routingKey, string messageId, string body,
    IReadOnlyDictionary<string, string>? traceHeaders = null)
{
    var bodyArray = Encoding.UTF8.GetBytes(body);
    var properties = Channel.CreateBasicProperties();
    properties.Persistent = true;
    properties.MessageId = messageId;

    if (traceHeaders != null)
        properties.InjectTrace(traceHeaders);   // 重试:恢复原 TraceId
    else
        properties.InjectTrace();               // 首次:生成新 Trace

    Channel.BasicPublish(exchange, routingKey, properties, bodyArray, mandatory: true);
}

4. Serilog 日志自动附带 TraceId

在 WindPayer.Logging 的 SerilogBootstrapper 中已注册了 TraceEnricher,只要 Activity.Current 存在(通过上述扩展方法已经创建),所有 Serilog 日志事件都会自动附加 trace_idspan_id 字段,无需额外配置。


配置

在 appsettings.json 中添加如下配置

  "WindpayerLogging": {
    "LogLevel": "Information",              //日志级别
    "ServiceName": "Notification",          //服务名称  
    "EnableConsole": true,
    "EnableOtlp": false,
    "EnableTracing": false,
    "OtlpEndpoint": "http://localhost:4317",// OTLP 地址,EnableOtlp,EnableTracing为 true 时生效
    "OtlpAuthKey": "dXNlcjE6T20xNWNHRnpjMWQ=",   // OTLP key,base64 编码的 "用户名:密码"
    // 请求日志记录配置
    "RequestLogging": {
      "SlowRequestThresholdMs": 1000,
      "GetRequestSamplingRate": 0.1,
      "LogPostRequestsAll": true,
      "LogUnsampledSlowOrErrorRequests": true,
      "MaxRequestBodyLogLength": 10000,
      "MaxResponseBodyLogLength": 10000,      
      "IgnoredPaths": [
        "/health",
        "/healthz",
        "/ready",
        "/live",
        "/metrics"
      ]
    }
  },

Showing the top 20 packages that depend on WindPayer.Logging.

Packages Downloads
WindPayer.Logging.AspNetCore
提供 WindPayer.Logging 的 ASP.NET Core 快速配置扩展,包含 IStartupFilter 自动注入请求日志中间件及 WebApplicationBuilder / IHostBuilder 快速配置。
11
WindPayer.Logging.AspNetCore
提供 WindPayer.Logging 的 ASP.NET Core 快速配置扩展,包含 IStartupFilter 自动注入请求日志中间件及 WebApplicationBuilder / IHostBuilder 快速配置。
6
WindPayer.Logging.AspNetCore
提供 WindPayer.Logging 的 ASP.NET Core 快速配置扩展,包含 IStartupFilter 自动注入请求日志中间件及 WebApplicationBuilder / IHostBuilder 快速配置。
4

.NET 7.0

.NET 8.0

Version Downloads Last updated
1.1.13 7 07/16/2026
1.1.12 4 07/16/2026
1.1.11 4 07/15/2026
1.1.10 7 06/15/2026
1.1.9 5 06/15/2026
1.1.8 10 06/08/2026
1.1.7 11 06/05/2026
1.1.6 5 06/05/2026
1.1.5 6 06/05/2026
1.1.4 6 06/05/2026
1.1.3 6 06/03/2026
1.1.2 11 05/11/2026
1.1.1 9 04/30/2026
1.1.0 7 04/30/2026
1.0.9 6 04/24/2026
1.0.8 11 04/23/2026
1.0.7 8 04/23/2026
1.0.6 8 04/23/2026
1.0.5 6 03/26/2026
1.0.4 848 11/06/2025
1.0.3 845 10/29/2025
1.0.2 847 10/29/2025
1.0.1 851 10/29/2025
1.0.0 852 10/29/2025