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

如何用类Serilog简洁语法实现.NET Core MEL日志事件enrichment?

简化MEL日志上下文属性的几种方案

针对你觉得MEL添加日志上下文属性写法繁琐的问题,这里有几个实用的简化方案:

1. 用匿名类型替代Dictionary

MEL的BeginScope原生支持匿名类型,无需手动创建Dictionary<string, object?>,写法大幅简化:

using (_logger.BeginScope(new { Foo = "abc", Bar = 123, Baz = true }))
{
    _logger.LogInformation("Process returned {Result}", 42);
}

这个方案无需额外代码,利用MEL本身特性,是最轻量化的实现方式。

2. 封装扩展方法模拟Serilog链式风格

如果更偏好Serilog那种链式ForContext的写法,可以给ILogger编写扩展方法,实现近似的语法:

public static class LoggerExtensions
{
    // 链式添加上下文,自动处理Scope释放
    public static ILogger WithContext(this ILogger logger, string key, object? value)
    {
        var scope = logger.BeginScope(new Dictionary<string, object?> { { key, value } });
        return new ScopedLogger(logger, scope);
    }

    // 内部包装类,确保日志完成后释放Scope
    private class ScopedLogger : ILogger
    {
        private readonly ILogger _innerLogger;
        private readonly IDisposable? _scope;

        public ScopedLogger(ILogger innerLogger, IDisposable? scope)
        {
            _innerLogger = innerLogger;
            _scope = scope;
        }

        public IDisposable? BeginScope<TState>(TState state) where TState : notnull 
            => _innerLogger.BeginScope(state);

        public bool IsEnabled(LogLevel logLevel) 
            => _innerLogger.IsEnabled(logLevel);

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
        {
            try
            {
                _innerLogger.Log(logLevel, eventId, state, exception, formatter);
            }
            finally
            {
                _scope?.Dispose();
            }
        }
    }
}

调用时就和Serilog的写法几乎一致:

_logger
    .WithContext("Foo", "abc")
    .WithContext("Bar", 123)
    .WithContext("Baz", true)
    .LogInformation("Process returned {Result}", 42);

3. 利用Serilog的LogContext(需启用)

既然你底层用Serilog作为MEL的提供者,可以直接用Serilog的LogContext添加属性,前提是在Serilog配置中启用FromLogContext:

// Serilog配置时添加
Log.Logger = new LoggerConfiguration()
    .Enrich.FromLogContext() // 启用LogContext
    .WriteTo.Console()
    .CreateLogger();

之后就能链式推送属性,写法简洁且贴近你熟悉的Serilog风格:

using (LogContext.PushProperty("Foo", "abc")
    .PushProperty("Bar", 123)
    .PushProperty("Baz", true))
{
    _logger.LogInformation("Process returned {Result}", 42);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 14:04:52