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

如何用PromQL获取API指定时间区间内的最大/最小响应时间?

问题描述

我想可视化API最近x分钟内的最大和最小响应时间,目前已经能用以下PromQL通过StatPanel展示每分钟平均响应时间:

sum(rate(request_duration_seconds_sum[1m]))/sum(rate(request_duration_seconds_count[1m]))

现在需要类似的StatPanel,展示最近1分钟内的最大响应时间(比如1分钟内响应时间为7ms、92ms、6ms、50ms时,显示92ms)和最小响应时间(显示6ms)。

当前客户端埋点配置了Counter、Gauge和Histogram指标,代码如下:

public MetricReporter(ILogger<MetricReporter> logger)
{
    _logger = logger ?? throw new ArgumentNullException(nameof(logger));

    _requestCounter = Metrics.CreateCounter("total_requests", "The total number of requests serviced by this API.");
    _requestGauge = Metrics.CreateGauge("total_requests_gauge", "The total number of requests serviced by this API.");

    _responseTimeHistogram = Metrics.CreateHistogram("request_duration_seconds",
        "The duration in seconds between the response to a request.", new HistogramConfiguration
        {
            Buckets = new[] { 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10  },
            LabelNames = new[] { "status_code", "method" , "path"}
        });
}

尝试过用子查询结合max_over_time,但结果不准确,查Prometheus文档发现min_over_time()、max_over_time()这类函数只适用于Gauge指标。我是否应该改用Gauge?如果需要,该怎么配置?

更新:尝试用直方图分位数语句创建面板,但计算结果不正确(实际1分钟内最大响应时间25ms,最小3ms):

histogram_quantile(1, increase(request_duration_seconds_bucket[1m]))
histogram_quantile(0, increase(request_duration_seconds_bucket[1m]))

解决方案

关于直方图分位数的问题

你用histogram_quantile(1, ...)得不到准确最大值的核心原因是:当前直方图的最小桶是0.01秒(10ms),而实际最小响应时间是3ms,最大25ms刚好卡在0.025秒(25ms)的桶边界上——直方图的分位数计算是基于桶区间的估算值,不是精确的单请求响应时间。

如果想用直方图近似获取最大/最小响应时间,需要调整桶的边界,覆盖实际的响应时间范围:

  • 新增更小的桶,比如0.001(1ms)、0.005(5ms),适配小响应时间的请求
  • 确保最大桶能覆盖API的实际最大响应时间(当前10秒桶如果满足业务需求可以保留)

调整后的Histogram配置示例:

_responseTimeHistogram = Metrics.CreateHistogram("request_duration_seconds",
    "The duration in seconds between the response to a request.", new HistogramConfiguration
    {
        Buckets = new[] { 0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10  },
        LabelNames = new[] { "status_code", "method" , "path"}
    });

调整后,histogram_quantile(1, increase(request_duration_seconds_bucket[1m]))会返回最接近实际最大值的桶边界(比如25ms请求会落在0.025桶,结果就是25ms),histogram_quantile(0, ...)会返回最小的非空桶边界。但要明确:直方图分位数始终是近似值,无法得到精确的单请求极值。

用Gauge获取精确的最大/最小响应时间

如果需要精确的最大、最小响应时间,确实需要改用Gauge指标,分别记录每次请求的响应时间瞬时极值。

配置方式:

  1. 创建两个Gauge指标,按业务维度(状态码、方法、路径)拆分:
private readonly Gauge _maxResponseTimeGauge;
private readonly Gauge _minResponseTimeGauge;

public MetricReporter(ILogger<MetricReporter> logger)
{
    _logger = logger ?? throw new ArgumentNullException(nameof(logger));

    _requestCounter = Metrics.CreateCounter("total_requests", "The total number of requests serviced by this API.");
    _requestGauge = Metrics.CreateGauge("total_requests_gauge", "The total number of requests serviced by this API.");

    _responseTimeHistogram = Metrics.CreateHistogram("request_duration_seconds",
        "The duration in seconds between the response to a request.", new HistogramConfiguration
        {
            Buckets = new[] { 0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10  },
            LabelNames = new[] { "status_code", "method" , "path"}
        });

    // 最大响应时间Gauge
    _maxResponseTimeGauge = Metrics.CreateGauge("request_duration_seconds_max",
        "The maximum duration in seconds of requests serviced by this API.",
        new GaugeConfiguration { LabelNames = new[] { "status_code", "method", "path" } });

    // 最小响应时间Gauge
    _minResponseTimeGauge = Metrics.CreateGauge("request_duration_seconds_min",
        "The minimum duration in seconds of requests serviced by this API.",
        new GaugeConfiguration { LabelNames = new[] { "status_code", "method", "path" } });
}
  1. 在请求处理逻辑中,更新Gauge值:
// 假设responseTime是当前请求的响应时间(单位:秒)
var labels = new[] { statusCode.ToString(), method, path };

// 更新最大响应时间:仅当当前值大于Gauge现有值时更新
_maxResponseTimeGauge.WithLabels(labels).Set(currentValue => Math.Max(currentValue, responseTime));

// 更新最小响应时间:初始值为0时直接设为当前响应时间,否则取较小值
_minResponseTimeGauge.WithLabels(labels).Set(currentValue => 
    currentValue == 0 ? responseTime : Math.Min(currentValue, responseTime));
  1. 用PromQL查询最近1分钟的极值:
  • 单维度最大响应时间:
max_over_time(request_duration_seconds_max[1m])
  • 单维度最小响应时间:
min_over_time(request_duration_seconds_min[1m])
  • 聚合所有维度的全局极值:
max(max_over_time(request_duration_seconds_max[1m]))
min(min_over_time(request_duration_seconds_min[1m]))

两种方案对比

方案精度资源消耗适用场景
直方图分位数近似值(依赖桶配置)低(Counter类型,内存占用稳定)不需要精确极值,关注响应时间整体分布时使用
Gauge记录极值精确值略高(需维护每个维度的极值状态)需要准确的最大/最小响应时间时使用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 14:40:19