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

如何在Prometheus/Grafana中仅展示实际发送的指标值

问题描述

我正在使用Grafana搭配Prometheus监控由OpenTelemetry生成的指标,指标以不规则间隔发送。当间隔较大时,系统会生成“伪数据点”——将最后发送的指标值重复填充至下一个指标接收前的时段。我希望仅展示实际发送的指标值,而非这些伪数据点,是否有实现方法?

相关截图

  • Grafana图表:Grafana图表
  • Prometheus数据:Prometheus数据
  • 实际发送的指标值:实际发送的指标值

指标生成代码

from opentelemetry.sdk.resources import Resource
from opentelemetry import metrics
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from random import randint
import time

COLLECTOR_ENDPOINT = "http://otelcol:4317"

resource = Resource.create(
    {
        "deployment.environment": "dev"
    }
)

metric_reader = PeriodicExportingMetricReader(OTLPMetricExporter(endpoint=COLLECTOR_ENDPOINT, insecure=True))
provider = MeterProvider(metric_readers=[metric_reader], resource=resource)
metrics.set_meter_provider(provider)
meter = metrics.get_meter("python-otlp-test")

# Global variable to store the latest gauge value
latest_gauge_value = None

def observable_gauge_func(options):
    global latest_gauge_value
    if latest_gauge_value is not None:
        yield metrics.Observation(latest_gauge_value, {'label': 'simple_label'})
        latest_gauge_value = None  # Reset the value after yielding

gauge = meter.create_observable_gauge("test_gauge_otlp", [observable_gauge_func])


def send_gauge_metrics(metric_name='None', metric=None):
    global latest_gauge_value
    latest_gauge_value = int(metric) if metric is not None else None
    metric_reader.force_flush()
    print(f'Metric {metric_name}, value: {metric}, sent')

#here I'm just trying to simulate the metrics being sent 
for i in range(4):
    for y in range(6):
        rad_metric = randint(1, 20)
        send_gauge_metrics("test-gauge", rad_metric)
        time.sleep(10)
        if y % 2 == 0:
            send_gauge_metrics("test-gauge", 0)
        time.sleep(10)
    time.sleep(120)

Prometheus配置

# Configure Prometheus to scrape the OpenTelemetry collector endpoint
scrape_configs:
  - job_name: "otel-collector"
    scrape_interval: 1s
    static_configs:
      - targets: ["otelcol:8889"]

解决方案

可从指标生成逻辑、Prometheus配置、Grafana查询过滤三个层面解决伪数据点问题:

1. 调整OpenTelemetry指标生成逻辑(推荐)

当前代码使用observable_gauge,空采集周期会被Prometheus填充最后值。改为直接使用普通gauge,仅在需要发送时记录指标,从根源避免伪数据:

修改代码核心部分:

# 替换原有的observable_gauge定义,创建普通gauge
gauge = meter.create_gauge("test_gauge_otlp", description="Test gauge with on-demand updates")

def send_gauge_metrics(metric_name='None', metric=None):
    if metric is not None:
        # 直接记录指标值,无需依赖观测函数
        gauge.record(int(metric), {'label': 'simple_label'})
        metric_reader.force_flush()
        print(f'Metric {metric_name}, value: {metric}, sent')

这种方式下,只有调用record时才会生成指标数据,空时段不会产生默认值。

2. 修改Prometheus采集配置

Prometheus的1s采集间隔过于频繁,会放大伪数据点出现频率:

  • 增大scrape_interval,匹配指标发送的最小间隔(比如10s),减少空周期采集
  • 启用honor_labels,确保仅保留OTel发送的原始数据标签

更新后的Prometheus配置:

scrape_configs:
  - job_name: "otel-collector"
    scrape_interval: 10s
    honor_labels: true
    static_configs:
      - targets: ["otelcol:8889"]

3. Grafana查询层面过滤伪数据

如果无法修改上游逻辑,用PromQL的changes函数识别数据变化点,过滤伪数据:

使用以下查询语句:

test_gauge_otlp unless changes(test_gauge_otlp[1m]) == 0

或者更精准筛选变化时刻:

test_gauge_otlp and on() (changes(test_gauge_otlp[10s]) > 0)

解释:

  • changes(metric[interval])返回指定窗口内指标值变化次数
  • 变化次数为0时,说明是Prometheus填充的伪数据,用unless或and过滤

另外,在Grafana图表设置中,将连接方式改为Points或Staircase,可更直观展示离散的实际数据点。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 21:55:06