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

如何仅追踪调用Redis的API请求并上报至Application Insights

问题分析与解决方案

现象原因

这不是异常现象,完全是当前中间件代码逻辑导致的结果。你的代码在进入中间件后,无论后续业务逻辑是否真的调用了Redis命令,只要执行到finally块就会无条件上报Redis依赖。哪怕只是获取了IDatabase实例但没执行任何Redis操作,也会触发上报。

解决方案

要实现仅上报实际执行过Redis命令的请求,需要追踪Redis命令的真实执行情况,而非仅依赖中间件的生命周期。以下提供两种可行方案:

方案一:自定义Redis数据库包装类

通过封装IDatabase接口,记录是否有实际命令执行:

  1. 创建追踪用的Redis数据库包装类
public class TrackedRedisDatabase : IDatabase
{
    private readonly IDatabase _innerDb;
    public bool HasExecutedCommands { get; private set; }

    public TrackedRedisDatabase(IDatabase innerDb)
    {
        _innerDb = innerDb;
    }

    // 实现IDatabase所有方法,每个方法执行后标记命令已执行
    public RedisValue StringGet(RedisKey key, CommandFlags flags = CommandFlags.None)
    {
        HasExecutedCommands = true;
        return _innerDb.StringGet(key, flags);
    }

    // 此处需补充实现IDatabase的其他所有方法(如StringSet、HashGet等),每个方法都要设置HasExecutedCommands = true
}
  1. 修改中间件代码
var stopwatch = Stopwatch.StartNew();
var originalDb = connectionMultiplexer.GetDatabase();
var trackedDb = new TrackedRedisDatabase(originalDb);

// 将追踪实例存入HttpContext,供后续业务逻辑使用
httpContext.Items["TrackedRedisDatabase"] = trackedDb;

try
{
    await next(httpContext).ConfigureAwait(false);
}
finally
{
    stopwatch.Stop();
    
    // 仅当有实际Redis命令执行时才上报依赖
    if (trackedDb.HasExecutedCommands)
    {
        var dependency = new DependencyTelemetry
        {
            Name = "Redis",
            Type = "Redis",
            Target = connectionMultiplexer.Configuration,
            Data = httpContext.Request.Path,
            Duration = stopwatch.Elapsed,
            Success = true
        };
        
        telemetryClient.TrackDependency(dependency);
    }
}
  1. 业务逻辑中使用追踪实例
// 从HttpContext获取追踪用的Redis数据库实例
var trackedDb = (TrackedRedisDatabase)HttpContext.Items["TrackedRedisDatabase"];
var value = trackedDb.StringGet("your-key");

方案二:利用StackExchange.Redis的事件回调

通过订阅ConnectionMultiplexer的CommandExecuted事件,监听Redis命令执行:

var stopwatch = Stopwatch.StartNew();
bool hasRedisCall = false;

// 订阅命令执行完成事件
void OnCommandExecuted(object sender, CommandExecutedEventArgs e)
{
    hasRedisCall = true;
}

connectionMultiplexer.CommandExecuted += OnCommandExecuted;

try
{
    await next(httpContext).ConfigureAwait(false);
}
finally
{
    stopwatch.Stop();
    // 必须取消订阅,避免内存泄漏和跨请求干扰
    connectionMultiplexer.CommandExecuted -= OnCommandExecuted;
    
    if (hasRedisCall)
    {
        var dependency = new DependencyTelemetry
        {
            Name = "Redis",
            Type = "Redis",
            Target = connectionMultiplexer.Configuration,
            Data = httpContext.Request.Path,
            Duration = stopwatch.Elapsed,
            Success = true
        };
        
        telemetryClient.TrackDependency(dependency);
    }
}

注意:ConnectionMultiplexer通常是单例实例,因此每个请求必须在finally块中取消事件订阅,防止多个请求的状态互相干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 23:27:09