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

如何在Serilog.AspNetCore中高效缩短ActionName与SourceContext日志格式?

在ASP.NET Core中用Serilog.AspNetCore高效记录缩短的ActionName和SourceContext

一、简化SourceContext(仅保留类名)

现有方案的性能说明

你当前使用的Serilog.Expressions模板:

{Substring(SourceContext, LastIndexOf(SourceContext, '.') + 1)}

性能其实已经足够——Serilog.Expressions会将表达式编译为表达式树,而非每次日志调用都重复解析字符串,开销非常低。

更高效的替代方案:自定义Enricher

如果追求极致性能,推荐在日志事件生成阶段就提前处理SourceContext,将短类名存入新的日志属性,避免模板渲染时重复计算:

  1. 实现自定义Enricher:
public class ShortSourceContextEnricher : ILogEventEnricher
{
    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
    {
        if (logEvent.Properties.TryGetValue("SourceContext", out var sourceContextValue) &&
            sourceContextValue is ScalarValue scalar && scalar.Value is string sourceContext)
        {
            var shortClassName = sourceContext.Substring(sourceContext.LastIndexOf('.') + 1);
            logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("ShortSourceContext", shortClassName));
        }
    }
}
  1. 在Serilog配置中注册Enricher:
Log.Logger = new LoggerConfiguration()
    .Enrich.With<ShortSourceContextEnricher>()
    // 其他配置
    .CreateLogger();
  1. 模板中直接使用新属性:
{ShortSourceContext}

这种方式仅在日志事件创建时处理一次SourceContext,高并发场景下比模板表达式更高效。

二、简化ActionName(保留Controller.Method格式)

方案1:自定义Enricher(性能最优)

和SourceContext的优化思路一致,提前处理ActionName并存为新属性:

  1. 实现Enricher:
public class ShortActionNameEnricher : ILogEventEnricher
{
    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
    {
        if (logEvent.Properties.TryGetValue("ActionName", out var actionNameValue) &&
            actionNameValue is ScalarValue scalar && scalar.Value is string actionName)
        {
            // 移除括号中的程序集信息
            var withoutAssembly = actionName.Split('(')[0].Trim();
            var parts = withoutAssembly.Split('.');
            
            var shortActionName = parts.Length >= 2 
                ? $"{parts[^2]}.{parts[^1]}" 
                : actionName; // 兼容异常格式
            
            logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("ShortActionName", shortActionName));
        }
    }
}
  1. 注册后模板中使用{ShortActionName}即可。

方案2:Serilog.Expressions自定义函数(模板内直接调用)

如果希望直接在模板中通过表达式实现,可注册自定义函数:

  1. 注册自定义函数:
using Serilog.Expressions;

// 在Serilog配置前注册
ExpressionTemplate.RegisterFunction("ShortenActionName", (string actionName) =>
{
    if (string.IsNullOrEmpty(actionName)) return actionName;
    var withoutAssembly = actionName.Split('(')[0].Trim();
    var parts = withoutAssembly.Split('.');
    return parts.Length >= 2 ? $"{parts[^2]}.{parts[^1]}" : actionName;
});
  1. 模板中调用函数:
{ShortenActionName(ActionName)}

这种方式无需新增日志属性,逻辑直接嵌入模板,但性能略低于Enricher方案(每次渲染模板时执行计算)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 03:57:04