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

- 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
相关产品推荐
相关产品推荐

