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

Python应用重启时如何保留Prometheus Gauge与Counter指标值?

解决Prometheus指标重启丢失的问题

默认情况下,Prometheus Python客户端的指标是内存存储的,应用重启后会重置为初始值。要维持指标数值,核心思路是把指标值持久化到外部存储,重启时从存储读取恢复。以下是几种可行方案:

方案1:持久化到JSON文件

这是最简单的方式,适合标签维度不多的场景。

实现步骤:

  • 应用启动时,读取JSON文件中的历史指标值,恢复到Gauge中
  • 定时(比如每30秒)将当前指标值写入JSON文件,或者在指标更新时触发保存

代码示例:

from prometheus_client import Gauge, start_http_server
import json
import time
from threading import Timer

# 定义持久化文件路径
PERSIST_FILE = "prom_metrics.json"
# 初始化Gauge指标
visits = Gauge('visit_count', 'No. of connected customers', ['mobile'])

def save_metrics():
    """保存当前指标值到JSON文件"""
    metrics_data = {}
    # 遍历所有mobile标签的指标值
    for label_values in visits._metrics:
        mobile = label_values[0]
        metrics_data[mobile] = visits.labels(mobile)._value.get()
    with open(PERSIST_FILE, 'w') as f:
        json.dump(metrics_data, f)
    # 定时30秒后再次保存
    Timer(30.0, save_metrics).start()

def load_metrics():
    """从JSON文件加载历史指标值"""
    try:
        with open(PERSIST_FILE, 'r') as f:
            metrics_data = json.load(f)
        for mobile, value in metrics_data.items():
            visits.labels(mobile).set(value)
    except FileNotFoundError:
        # 文件不存在时跳过,指标保持初始值0
        pass

if __name__ == "__main__":
    # 启动时加载历史数据
    load_metrics()
    # 启动Prometheus HTTP服务
    start_http_server(addr='X.X.X.X', port=8001)
    # 启动定时保存任务
    save_metrics()
    
    # 模拟业务逻辑更新指标
    while True:
        visits.labels("ios").inc()
        visits.labels("android").inc()
        time.sleep(1)

方案2:使用SQLite数据库存储

如果你的指标标签维度复杂,或者需要更可靠的存储,SQLite是轻量级的选择。

实现步骤:

  • 创建SQLite表,存储指标名、标签键值、指标数值
  • 指标更新时同步写入数据库
  • 应用启动时查询数据库,恢复所有指标值

代码示例:

from prometheus_client import Gauge, start_http_server
import sqlite3
import time
from threading import Timer

DB_NAME = "prom_metrics.db"
visits = Gauge('visit_count', 'No. of connected customers', ['mobile'])

def init_db():
    """初始化SQLite数据库表"""
    conn = sqlite3.connect(DB_NAME)
    cursor = conn.cursor()
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS metrics (
            metric_name TEXT,
            label_key TEXT,
            label_value TEXT,
            value REAL,
            PRIMARY KEY (metric_name, label_key, label_value)
        )
    ''')
    conn.commit()
    conn.close()

def save_metrics():
    """保存当前指标到数据库"""
    conn = sqlite3.connect(DB_NAME)
    cursor = conn.cursor()
    # 先删除旧数据,再插入新数据
    cursor.execute("DELETE FROM metrics WHERE metric_name = 'visit_count'")
    for label_values in visits._metrics:
        mobile = label_values[0]
        value = visits.labels(mobile)._value.get()
        cursor.execute('''
            INSERT INTO metrics (metric_name, label_key, label_value, value)
            VALUES (?, ?, ?, ?)
        ''', ('visit_count', 'mobile', mobile, value))
    conn.commit()
    conn.close()
    Timer(30.0, save_metrics).start()

def load_metrics():
    """从数据库加载指标"""
    conn = sqlite3.connect(DB_NAME)
    cursor = conn.cursor()
    cursor.execute("SELECT label_value, value FROM metrics WHERE metric_name = 'visit_count'")
    for mobile, value in cursor.fetchall():
        visits.labels(mobile).set(value)
    conn.close()

if __name__ == "__main__":
    init_db()
    load_metrics()
    start_http_server(addr='X.X.X.X', port=8001)
    save_metrics()
    
    # 模拟业务逻辑
    while True:
        visits.labels("ios").inc()
        visits.labels("android").inc()
        time.sleep(1)

注意事项

  • 持久化频率:不要过于频繁写入,避免IO性能问题,根据业务需求调整(比如30秒到5分钟一次)
  • 并发安全:如果多个线程更新指标,需要注意文件/数据库的并发访问,可加锁处理
  • 数据一致性:如果应用异常退出,最后一次的指标值可能没保存,可结合事务(数据库方案)或原子写入(文件方案,比如先写临时文件再替换)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 01:46:13