asp.net core 自定义基于 HttpContext 的 Serilog Enricher

asp.net core 自定义基于 HttpContext 的 Serilog Enricher

Intro#

通过 HttpContext 我们可以拿到很多有用的信息,比如 Path/QueryString/RequestHeader 等请求信息, StatusCode/ResponseHeader 等响应信息,借助 HttpContext 我们可以在日志中记录很多有用的信息,于是需要自定义一个基于 HttpContext 的 Enricher

实现代码#

public class HttpContextEnricher : ILogEventEnricher
{
    private readonly IServiceProvider _serviceProvider;
    private readonly Action<LogEvent, ILogEventPropertyFactory, HttpContext> _enrichAction;

    public HttpContextEnricher(IServiceProvider serviceProvider) : this(serviceProvider, null)
    {
    }

    public HttpContextEnricher(IServiceProvider serviceProvider, Action<LogEvent, ILogEventPropertyFactory, HttpContext> enrichAction)
    {
        _serviceProvider = serviceProvider;
        if (enrichAction == null)
        {
            _enrichAction = (logEvent, propertyFactory, httpContext) =>
            {
                logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("RequestIP", httpContext.GetUserIP()));
                logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("RequestPath", httpContext.Request.Path));
                logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("RequestMethod", httpContext.Request.Method));

                logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("Referer", httpContext.Request.Headers["Referer"].ToString()));
            };
        }
        else
        {
            _enrichAction = enrichAction;
        }
    }

    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
    {
        var httpContext = _serviceProvider.GetService<IHttpContextAccessor>()?.HttpContext;
        if (null != httpContext)
        {
            _enrichAction.Invoke(logEvent, propertyFactory, httpContext);
        }
    }
}

public static class EnricherExtensions
{
    public static LoggerConfiguration WithHttpContextInfo(this LoggerEnrichmentConfiguration enrich, IServiceProvider serviceProvider)
    {
        if (enrich == null)
            throw new ArgumentNullException(nameof(enrich));

        return enrich.With(new HttpContextEnricher(serviceProvider));
    }

    public static LoggerConfiguration WithHttpContextInfo(this LoggerEnrichmentConfiguration enrich, IServiceProvider serviceProvider, Action<LogEvent, ILogEventPropertyFactory, HttpContext> enrichAction)
    {
        if (enrich == null)
            throw new ArgumentNullException(nameof(enrich));

        return enrich.With(new HttpContextEnricher(serviceProvider, enrichAction));
    }
}

使用方式#

上面的 Enricher 允许我们定义了一个委托来自定义加从 HttpContext 中添加一些我们想要记录的信息了

logFactory.AddSerilog(loggingConfig =>
{
    loggingConfig
        .Enrich.FromLogContext()
        .Enrich.WithHttpContextInfo(app.ApplicationServices, (logEvent, propertyFactory, httpContext) =>
        {
            logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("RequestIP", httpContext.GetUserIP()));
            logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("RequestPath", httpContext.Request.Path));
            logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("RequestMethod", httpContext.Request.Method));

            logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("Referer", httpContext.Request.Headers["Referer"].ToString()));
            if (httpContext.Response.HasStarted)
            {
                logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("ResponseStatus", httpContext.Response.StatusCode));
            }
        })
        ;

    var esConnString = Configuration.GetConnectionString("ElasticSearch");
    if (esConnString.IsNotNullOrWhiteSpace())
    {
        loggingConfig.WriteTo.Elasticsearch(esConnString,
            $"logstash-{ApplicationHelper.ApplicationName.ToLower()}");
    }
})

使用效果#

More#

上面的扩展可以自行修改,自己用的顺手就好~~

Reference#

作者:weihanli

出处:https://www.cnblogs.com/weihanli/p/12105239.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   WeihanLi  阅读(1351)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
点击右上角即可分享
微信分享提示
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu