【发布时间】:2025-12-04 19:00:02
【问题描述】:
如果请求 HTTP 标头具有 CorrelationId 之类的值,我的自定义 Logger 如何获取此值,以便所有日志条目都具有 CorrelationId?
公共 ILogger CreateLogger(string categoryName) 不能更改注入任何参数,必须实现 ILoggerProvider
【问题讨论】:
标签: asp.net-core logging
如果请求 HTTP 标头具有 CorrelationId 之类的值,我的自定义 Logger 如何获取此值,以便所有日志条目都具有 CorrelationId?
公共 ILogger CreateLogger(string categoryName) 不能更改注入任何参数,必须实现 ILoggerProvider
【问题讨论】:
标签: asp.net-core logging
您可以在 ConfigureService 中注册 IHttpContextAccessor 并将其实例传递给自定义记录器。
然后你可以使用
var header = _accessor.HttpContext.Request.Headers["CorrelationId"].ToString()
1.startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IServiceProvider serviceProvider)
{
loggerFactory.AddCustomLogger(serviceProvider.GetService<IHttpContextAccessor>());
}
2.CustomLogger.cs:
public class CustomLogProvider : ILoggerProvider
{
private readonly Func<string, LogLevel, bool> _filter;
private readonly IHttpContextAccessor _accessor;//DI
public CustomLogProvider(Func<string, LogLevel, bool> filter, IHttpContextAccessor accessor)
{
_filter = filter;
_accessor = accessor;
}
public ILogger CreateLogger(string categoryName)
{
return new CustomLogger(categoryName, _filter, _accessor);
}
public void Dispose()
{
}
}
public class CustomLogger : ILogger
{
private string _categoryName;
private Func<string, LogLevel, bool> _filter;
private readonly IHttpContextAccessor _accessor;
public CustomLogger(string categoryName, Func<string, LogLevel, bool> filter, IHttpContextAccessor accessor)
{
_categoryName = categoryName;
_filter = filter;
_accessor = accessor;
}
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
return (_filter == null || _filter(_categoryName, logLevel));
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
if (!IsEnabled(logLevel))
{
return;
}
if (formatter == null)
{
throw new ArgumentNullException(nameof(formatter));
}
var message = formatter(state, exception);
if (string.IsNullOrEmpty(message))
{
return;
}
message = $"{ logLevel }: {message}";
if (exception != null)
{
message += Environment.NewLine + Environment.NewLine + exception.ToString();
}
if (_accessor.HttpContext != null) // you should check HttpContext
{
var headers = _accessor.HttpContext.Request.Headers["CorrelationId"].ToString();
if(headers != "")
{
message += Environment.NewLine + headers + Environment.NewLine + _accessor.HttpContext.Request.Path;
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine(message);
}
}
// your implementation
}
}
public static class CustomLoggerExtensions
{
public static ILoggerFactory AddCustomLogger(this ILoggerFactory factory, IHttpContextAccessor accessor,
Func<string, LogLevel, bool> filter = null)
{
factory.AddProvider(new CustomLogProvider(filter, accessor));
return factory;
}
}
【讨论】:
我使用的最终解决方案是实现一个具有相关 ID 的基类。 创建了一个客户控制器工厂类以从标头中获取相关 ID 并将其设置在基类上。 然后记录器可以使用基类中的值。
【讨论】: