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

使用Python脚本导出Prometheus数据到CSV时遇JSON解析错误

问题描述

我有一个名为yprom_csv.py的Python脚本,用来将Prometheus数据导出为CSV格式,但运行时出现JSON解析错误。

脚本代码

import csv
import requests
import sys
def GetMetrixNames(url):
    response = requests.get('{0}/api/v1/label/__name__/values'.format(url))
    names = response.json()['data']
    #Return metrix names
    return names
"""
Prometheus hourly data as csv.
"""
writer = csv.writer(sys.stdout)
if len(sys.argv) != 2:
    print('Usage: {0} http://localhost:9090'.format(sys.argv[0]))
    sys.exit(1)
metrixNames=GetMetrixNames(sys.argv[1])
writeHeader=True
for metrixName in metrixNames:
     #now its hardcoded for hourly
     response = requests.get('{0}/api/v1/query'.format(sys.argv[1]),
     params={'query': metrixName+'[1h]'})
     results = response.json()['data']['result']
     # Build a list of all labelnames used.
     #gets all keys and discard __name__
     labelnames = set()
      for result in results:
          labelnames.update(result['metric'].keys())
      # Canonicalize
      labelnames.discard('__name__')
      labelnames = sorted(labelnames)
      # Write the samples.
      if writeHeader:
          writer.writerow(['name', 'timestamp', 'value'] + labelnames)
          writeHeader=False
      for result in results:
          l = [result['metric'].get('__name__', '')] + result['values']
          for label in labelnames:
              l.append(result['metric'].get(label, ''))
              writer.writerow(l)

运行命令

python3 yprom_csv.py https://prometheus-k8s-openshift-monitoring.apps.XXXX-XXXXXXX.Xx8X.p1.openshiftapps.com

错误信息

Traceback (most recent call last):
File "/root/yprom_csv.py", line 16, in <module>
metrixNames=GetMetrixNames(sys.argv[1])
File "/root/yprom_csv.py", line 6, in GetMetrixNames
names = response.json()['data']
File "/usr/lib/python3.9/site-packages/requests/models.py", line 900, in json
return complexjson.loads(self.text,** kwargs)
File "/usr/lib64/python3.9/json/__init__.py", line 346, in loads
return _default_decoder.decode(s)
File "/usr/lib64/python3.9/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib64/python3.9/json/decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 2 column 1 (char 1)

解决方案

这个错误的核心是requests.get返回的响应不是有效的JSON格式,以下是针对性的解决步骤:

1. 先验证Prometheus API的可访问性

用浏览器或curl直接访问目标API地址:

curl https://prometheus-k8s-openshift-monitoring.apps.XXXX-XXXXXXX.Xx8X.p1.openshiftapps.com/api/v1/label/__name__/values

如果返回HTML页面(比如登录页、权限错误页),说明需要身份验证或URL存在问题。

2. 添加OpenShift身份验证

OpenShift上的Prometheus通常需要Bearer Token认证:

  • 先获取当前用户的Bearer Token:
    oc whoami -t
    
  • 修改脚本,添加认证头并更新参数逻辑:
    def GetMetrixNames(url, token):
        headers = {'Authorization': f'Bearer {token}'}
        response = requests.get(f"{url}/api/v1/label/__name__/values", headers=headers)
        # 先检查响应状态
        if response.status_code != 200:
            print(f"请求失败:状态码 {response.status_code},响应内容:{response.text}")
            sys.exit(1)
        try:
            data = response.json()
        except json.decoder.JSONDecodeError as e:
            print(f"JSON解析失败:{e}")
            sys.exit(1)
        return data['data']
    
    # 修改参数检查逻辑
    if len(sys.argv) != 3:
        print('Usage: {0} <prometheus-url> <bearer-token>'.format(sys.argv[0]))
        sys.exit(1)
    metrixNames=GetMetrixNames(sys.argv[1], sys.argv[2])
    
    # 后续查询请求也要添加认证头
    response = requests.get(f"{sys.argv[1]}/api/v1/query",
                           params={'query': f"{metrixName}[1h]"},
                           headers={'Authorization': f'Bearer {sys.argv[2]}'})
    

3. 排查响应内容(临时调试用)

在调用response.json()前,先打印响应的状态码和文本,确认返回内容:

def GetMetrixNames(url):
    response = requests.get('{0}/api/v1/label/__name__/values'.format(url))
    print(f"状态码:{response.status_code}")
    print(f"响应内容:{response.text[:500]}") # 打印前500字符
    try:
        data = response.json()
    except json.decoder.JSONDecodeError as e:
        print(f"解析失败:{e}")
        sys.exit(1)
    return data['data']

4. 处理SSL证书问题(可选)

如果是自签名SSL证书导致请求失败,可临时关闭证书验证(生产环境建议导入信任证书):

response = requests.get('{0}/api/v1/label/__name__/values'.format(url), verify=False)

5. 修复脚本缩进错误

原脚本中for result in results:一行缩进错误,会导致语法问题,修正为:

labelnames = set()
for result in results:
    labelnames.update(result['metric'].keys())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 18:43:21