如果请求HTTP标头具有类似CorrelationId的值,我的自定义Logger如何获得该值,以便所有日志条目都具有CorrelationId?
公共ILogger CreateLogger(字符串类别名称) 不能更改以注入任何参数,而必须实现 ILoggerProvider
答案 0 :(得分:1)
您可以在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;
}
}
答案 1 :(得分:0)
我最后使用的解决方案是实现一个具有相关ID的基类。 创建了一个客户Controller工厂类,以从标头中获取相关性ID并将其设置在基类上。 然后,记录器可以使用基类中的值。