Asp.net core ASP.net核心:如何将头值注入自定义记录器?

Asp.net core ASP.net核心:如何将头值注入自定义记录器?,asp.net-core,logging,Asp.net Core,Logging,如果请求HTTP头具有类似CorrelationId的值,那么我的自定义记录器如何获取该值,以便所有日志条目都具有CorrelationId 公共ILogger CreateLogger(字符串类别名称) 无法更改以插入任何参数,并且必须实现iLogger Provider您可以在ConfigureService中注册IHttpContextAccessor,并将其实例传递给自定义记录器 然后您可以使用 var header = _accessor.HttpContext.Request.Hea

如果请求HTTP头具有类似CorrelationId的值,那么我的自定义记录器如何获取该值,以便所有日志条目都具有CorrelationId

公共ILogger CreateLogger(字符串类别名称)
无法更改以插入任何参数,并且必须实现iLogger Provider

您可以在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>());

}
public void配置服务(IServiceCollection服务)
{
services.AddSingleton();
}
public void配置(IApplicationBuilder应用程序、ILoggerFactory loggerFactory、IServiceProvider服务提供商)
{
loggerFactory.AddCustomLogger(serviceProvider.GetService());
}
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;
    }
}
公共类CustomLogProvider:ILoggerProvider
{
专用只读函数过滤器;
私有只读IHttpContextAccessor _accessor;//DI
公共CustomLogProvider(Func筛选器、IHttpContextAccessor访问器)
{
_过滤器=过滤器;
_存取器=存取器;
}
公共ILogger CreateLogger(字符串类别名称)
{
返回新的CustomLogger(categoryName、\u filter、\u accessor);
}
公共空间处置()
{
}
}
公共类CustomLogger:ILogger
{
私有字符串_categoryName;
私有函数过滤器;
专用只读IHttpContextAccessor\u访问器;
公共CustomLogger(字符串类别名称、Func筛选器、IHttpContextAccessor访问器)
{
_categoryName=categoryName;
_过滤器=过滤器;
_存取器=存取器;
}
公共IDisposable BeginScope(州)
{
返回null;
}
公共布尔值已启用(日志级别日志级别)
{
返回(_filter==null | | u filter(_categoryName,logLevel));
}
公共无效日志(日志级别、日志级别、事件ID、事件ID、TState状态、异常、函数格式化程序)
{
如果(!IsEnabled(日志级别))
{
返回;
}
if(格式化程序==null)
{
抛出新ArgumentNullException(nameof(formatter));
}
var消息=格式化程序(状态、异常);
if(string.IsNullOrEmpty(message))
{
返回;
}
message=$“{logLevel}:{message}”;
if(异常!=null)
{
message+=Environment.NewLine+Environment.NewLine+exception.ToString();
}
如果(_accessor.HttpContext!=null)//您应该检查HttpContext
{
var headers=_accessor.HttpContext.Request.headers[“CorrelationId”].ToString();
如果(标题!=“”)
{
message+=Environment.NewLine+headers+Environment.NewLine+\u accessor.HttpContext.Request.Path;
Console.ForegroundColor=ConsoleColor.DarkGreen;
控制台写入线(消息);
}
}
//您的实现
}
}
公共静态类CustomLoggerExtensions
{
公共静态iLogger工厂AddCustomLogger(此iLogger工厂、IHttpContextAccessor访问器、,
Func filter=null)
{
AddProvider(新的CustomLogProvider(过滤器、访问器));
返回工厂;
}
}

我最后使用的解决方案是实现一个具有相关id的基类。 创建了一个customer Controller工厂类,以从标头获取相关Id并将其设置在基类上。 然后,记录器可以使用基类中的值

示例代码位于此处。