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

.NET Core 7(C#)如何为所有日志添加方法名称至Azure Application Insights

在.NET Core 7 WebApi中为Azure Application Insights日志附加调用方法名

方案1:使用Application Insights遥测初始化器(推荐)

通过实现ITelemetryInitializer接口,可以全局为所有日志自动附加调用方法名,无需修改现有日志代码,就能将方法名注入到App Insights的遥测属性中。

步骤:

  1. 创建自定义遥测初始化器类:
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.Extensibility;
using System.Diagnostics;

public class MethodNameTelemetryInitializer : ITelemetryInitializer
{
    public void Initialize(ITelemetry telemetry)
    {
        // 仅处理日志类型的遥测(TraceTelemetry)
        if (telemetry is TraceTelemetry traceTelemetry)
        {
            var stackTrace = new StackTrace();
            // 跳过系统框架的调用栈帧,定位到业务方法
            for (int i = 0; i < stackTrace.FrameCount; i++)
            {
                var frame = stackTrace.GetFrame(i);
                var method = frame.GetMethod();
                if (!method.DeclaringType.FullName.StartsWith("Microsoft.") 
                    && !method.DeclaringType.FullName.StartsWith("System."))
                {
                    traceTelemetry.Properties["CallingMethod"] = $"{method.DeclaringType.Name}.{method.Name}";
                    break;
                }
            }
        }
    }
}
  1. 在Program.cs中注册初始化器:
builder.Services.AddApplicationInsightsTelemetry();
// 注册自定义遥测初始化器
builder.Services.AddSingleton<ITelemetryInitializer, MethodNameTelemetryInitializer>();

配置完成后,所有日志会自动携带CallingMethod属性,在Azure Application Insights的日志详情中即可查看对应方法名。

注意:获取调用栈存在一定性能开销,建议在生产环境中按需启用,比如通过配置开关控制,或仅在Debug模式下开启。

方案2:使用CallerMemberName手动传入方法名

如果不需要全局配置,可利用[CallerMemberName]特性自动获取当前方法名,手动传入日志中,这种方式性能开销更低,但需要修改现有日志调用代码:

using System.Runtime.CompilerServices;

public class MyCustomService
{
    private readonly ILogger<MyCustomService> _logger;

    public MyCustomService(ILogger<MyCustomService> logger)
    {
        _logger = logger;
    }

    public void ExecuteBusinessLogic()
    {
        LogAction("开始执行业务逻辑");
    }

    private void LogAction(string message, [CallerMemberName] string methodName = "")
    {
        // 将方法名作为日志属性传入,方便App Insights筛选
        _logger.LogInformation("{Message} | 调用方法: {CallingMethod}", message, methodName);
    }
}

方案3:自定义Logger实现

若需要完全控制日志流程,可自定义ILogger和ILoggerProvider,在日志写入时自动附加调用方法信息:

  1. 创建自定义Logger:
using Microsoft.Extensions.Logging;
using System.Diagnostics;

public class MethodLogger<T> : ILogger<T>
{
    private readonly ILogger<T> _innerLogger;

    public MethodLogger(ILogger<T> innerLogger)
    {
        _innerLogger = innerLogger;
    }

    public IDisposable BeginScope<TState>(TState state) => _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)
    {
        var methodName = GetCallingMethodName();
        // 将方法名添加到日志属性集合中
        var newState = new Dictionary<string, object>(state as IEnumerable<KeyValuePair<string, object>> ?? Enumerable.Empty<KeyValuePair<string, object>>())
        {
            ["CallingMethod"] = methodName
        };

        _innerLogger.Log(logLevel, eventId, newState, exception, formatter);
    }

    private string GetCallingMethodName()
    {
        var stackTrace = new StackTrace();
        for (int i = 0; i < stackTrace.FrameCount; i++)
        {
            var frame = stackTrace.GetFrame(i);
            var method = frame.GetMethod();
            if (!method.DeclaringType.FullName.StartsWith("Microsoft.") 
                && !method.DeclaringType.FullName.StartsWith("System."))
            {
                return $"{method.DeclaringType.Name}.{method.Name}";
            }
        }
        return "UnknownMethod";
    }
}
  1. 创建自定义LoggerProvider:
using Microsoft.Extensions.Logging;

public class MethodLoggerProvider : ILoggerProvider
{
    private readonly ILoggerProvider _innerProvider;

    public MethodLoggerProvider(ILoggerProvider innerProvider)
    {
        _innerProvider = innerProvider;
    }

    public ILogger CreateLogger(string categoryName)
    {
        var innerLogger = _innerProvider.CreateLogger(categoryName);
        var loggerType = typeof(MethodLogger<>).MakeGenericType(Type.GetType(categoryName) ?? typeof(object));
        return (ILogger)Activator.CreateInstance(loggerType, innerLogger);
    }

    public void Dispose() => _innerProvider.Dispose();
}
  1. 在Program.cs中注册:
// 包装现有LoggerProvider,实现方法名注入
var innerProvider = builder.Logging.Services.First(s => s.ServiceType == typeof(ILoggerProvider)).ImplementationInstance as ILoggerProvider;
builder.Logging.AddProvider(new MethodLoggerProvider(innerProvider));

这种方式灵活性最高,但实现复杂度也相对较高,适合有特殊日志需求的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 15:40:58