You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 7 API中基于来源区分Graylog日志配置的正确实现方式

.NET 7 API中针对WebApp上报日志配置独立Graylog日志源的正确实现

问题背景

基于.NET 7 API开发的React应用,使用Graylog做日志记录。需求是提供/logs API端点接收Web应用上报的错误日志,且Web应用上报的日志需使用独立的LogSource(标记为WebApp),API自身日志使用另一LogSource(标记为API)。

当前问题:每次命中/logs端点时会生成两条内容相同但LogSource分别为API和WebApp的日志记录,原因是每次请求都会向LoggerFactory添加新的GELF日志提供器,导致全局存在多个日志记录器,所有日志被重复输出。

当前代码的核心问题

  • LoggerFactory是全局共享组件,禁止在请求处理过程中动态添加日志提供器,每次调用AddGelf都会新增日志记录器实例,后续所有日志会被所有已添加的记录器处理。
  • 现有中间件逻辑会在每次/logs请求时重复添加WebApp的GELF配置,导致日志提供器数量不断累积,最终所有日志被多份记录。

正确实现方案

方案一:使用命名日志记录器(推荐)

在应用启动时预先配置两个独立的GELF日志提供器,分别对应API和WebApp的日志源,再在不同场景下使用对应的命名日志记录器。

  1. 修改appsettings.json配置
    明确区分两个日志源的配置:
"Logging": {
  "LogLevel": {
    "Default": "Information",
    "Microsoft.AspNetCore": "Warning"
  },
  "GELF:API": {
    "Host": "xxx.graylog.com",
    "LogSource": "API"
  },
  "GELF:WebApp": {
    "Host": "xxx.graylog.com",
    "LogSource": "WebApp"
  }
}
  1. 在Program.cs中预先配置所有GELF日志提供器
    在应用启动阶段完成日志配置,避免请求时动态修改:
var builder = WebApplication.CreateBuilder(args);

// 配置API的GELF日志提供器
builder.Logging.AddGelf(options =>
{
    builder.Configuration.GetSection("Logging:GELF:API").Bind(options);
    options.AdditionalFields["machine_name"] = Environment.MachineName;
});

// 配置WebApp的GELF日志提供器
builder.Logging.AddGelf(options =>
{
    builder.Configuration.GetSection("Logging:GELF:WebApp").Bind(options);
    options.AdditionalFields["machine_name"] = Environment.MachineName;
});

// 其他服务配置...

var app = builder.Build();

// 移除原有动态添加日志配置的LoggingMiddleware,无需再使用
// app.UseMiddleware<LoggingMiddleware>();

// 异常处理器配置
using (var serviceScope = app.Services.CreateScope())
{
    var services = serviceScope.ServiceProvider;
    var logger = services.GetRequiredService<MyProject1.Logging.IMyLogger<MyProject1.Api.Extensions.Project1Exception>>();
    app.ConfigureExceptionHandler(logger);
}

app.Run();
  1. 在LogsController中使用WebApp专属日志记录器
    在处理WebApp上报日志的控制器中,创建并使用WebApp命名的日志记录器:
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace MyProject1.Api.Controllers
{
    [ApiController]
    [Route("logs")]
    public class LogsController : ControllerBase
    {
        private readonly ILogger _webAppLogger;

        public LogsController(ILoggerFactory loggerFactory)
        {
            // 创建对应WebApp日志源的命名日志记录器
            _webAppLogger = loggerFactory.CreateLogger("WebApp");
        }

        [HttpPost]
        public IActionResult SubmitWebAppLog([FromBody] WebAppLogModel logData)
        {
            // 使用WebApp专属日志记录器输出日志,只会触发WebApp的GELF配置
            _webAppLogger.LogError(logData.ErrorMessage, logData.StackTrace);
            return Ok();
        }
    }

    public class WebAppLogModel
    {
        public string ErrorMessage { get; set; }
        public string StackTrace { get; set; }
    }
}
  1. API自身日志保持原有使用方式
    API其他控制器或类中,继续使用依赖注入的ILogger<T>即可,默认会使用API的GELF日志源:
public class SomeApiController : ControllerBase
{
    private readonly ILogger<SomeApiController> _logger;

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

    [HttpGet]
    public IActionResult Get()
    {
        // 此日志会使用API的LogSource
        _logger.LogInformation("API处理了一个请求");
        return Ok();
    }
}

方案二:使用日志过滤器路由(复杂场景可选)

如果需要更灵活的动态日志路由逻辑,可以通过自定义日志过滤器,根据日志的自定义属性选择对应的日志提供器。此方案复杂度较高,适合需动态判断的场景,大多数情况下方案一足够满足需求。

效果验证

  • WebApp通过/logs端点上报的日志,只会在Graylog中出现一条LogSource=WebApp的记录。
  • API自身产生的日志,只会在Graylog中出现一条LogSource=API的记录。
  • 不会再出现重复日志的问题,日志提供器数量固定,不会随请求累积。

内容的提问来源于stack exchange,提问作者Junaid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 01:59:53