记一次Prometheus的离奇经历
前情提要 书接上回,为了获取客户的 Prometheus 监控数据,我写了个脚本用来通过 API 获取监控数据,然后转换成 OpenMetrics 格式以方便传输和导入,代码如下。 import datetime import subprocess import requests import sys """ http://localhost:9090 """ prometheus_url = input("请输入Prometheus链接: ") username = input("请输入用户名: 如无认证,请回车跳过") password = input("请输入密码: 如无认证,请回车跳过") print("下面的两个变量只需填写一个或者不填使用默认值") step = input("请输入每两个数据点间隔(单位秒,建议为5的倍数): ") hours = input("请输入往前查询的小时数(单位小时,建议不填): ") auth = None metric_param = "e" # 将查询出所有带有elasticsearch的指标 if username != "" and password != "": auth = (username, password) # 检查用户输入是否为数字 def is_number(value): try: int(value) return True except ValueError: return False # 如果用户同时设置了hours和step,按用户的输入值查询 if hours != "" and step != "": hours = int(hours) step = int(step) print("将查询过去{}小时的数据,步长为{}秒".format(hours, step)) else: # 如果用户没有输入hours和step,使用默认值 if hours == "" and step == "": print("将使用默认值查询") hours = 30 step = 10 elif hours != "": hours = int(hours) # 根据用户输入的hours计算step step = int(60 * 60 / (11000 / hours)) + 1 print("将查询过去{}小时的数据,步长为{}秒".format(hours, step)) elif step != "": step = int(step) # 根据用户输入的step计算hours hours = int(11000 / (60 / step) / 60) print("将查询过去{}小时的数据,步长为{}秒".format(hours, step)) else: print("输入的小时数和步长必须为有效的数字。") sys.exit(1) end_time = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ") query_time = datetime.datetime.now() - datetime.timedelta(hours=hours) start_time = query_time.strftime("%Y-%m-%dT%H:%M:%SZ") series = requests.get('{}/api/v1/label/__name__/values'.format(prometheus_url), auth=auth) if series.status_code != 200: print("查询失败,请检查{}/api/v1/label/__name__/values的连通性".format(prometheus_url)) sys.exit(1) else: metric_list = [queryQL for queryQL in series.json()['data'] if '{}'.format(metric_param) in queryQL] # 将查询出所有带有elasticsearch的指标 print("本次一共查询了{}个指标".format(len(metric_list))) with open('openmetrics.txt', 'w') as f: line_count = 0 # 用于统计行数的计数器 for metric_name in metric_list: metric_response = requests.get( '{}/api/v1/query_range?query={}&start={}&end={}&step={}s'.format( prometheus_url, metric_name, start_time, end_time, step)) print(metric_response.url) if metric_response.status_code != 200: print("查询失败,状态码为{}".format(metric_response.status_code)) sys.exit(1) else: prometheus_data = metric_response.json() for result in prometheus_data['data']['result']: metric_name = result['metric']['__name__'] labels = [] for key, value in result['metric'].items(): if key != '__name__': labels.append(f'{key}="{value}"') labels = ','.join(labels) openmetrics = [] for value in result['values']: openmetrics.append(f'{metric_name}{{{labels}}} {value[1]} {value[0]}\n') openmetrics = ''.join(openmetrics) f.write(openmetrics) line_count += openmetrics.count('\n') # 统计写入的行数 f.write('# EOF\n') # 文档末尾标志必须添加,promtool才能正常识别 with open('./note.txt', 'a') as f: # 使用'a'模式来追加内容 f.write('\n') f.write("本次查询的时间范围数据为{},查询的步长为{}秒,共查询了{}种指标,共写入{}行数据".format( end_time, step, len(metric_list), line_count)) # print("写入完成,共写入{}行数据".format(line_count)) # subprocess.run(['gzip', 'openmetrics.txt']) # 脚本运行完毕后自动压缩文本文件 已知我本地测试的 Prometheus 采集频率是每秒一次,假设我们把一秒当作最小的单位,那么可以说采集到的监控数据是一条连续的线。根据代码中的公式 hours = int(11000 / (60 / step) / 60),我们说当步长越大时,跨步就越大,那么数据点的数量应该越小,就好比你走同一段路,你迈的步子越大,是不是需要的步数就越少。 为了记录每一次的步长,所以在代码的最后面将每次查询的参数记录到另一个文本中,如下所示: # 没有停止各种exporter,数据会不停地增加 本次查询的时间范围数据为2023-09-25T19:28:22Z,查询的步长为5秒,共查询了593种指标,共写入9265448行数据 本次查询的时间范围数据为2023-09-25T19:29:41Z,查询的步长为10秒,共查询了593种指标,共写入7027362行数据 本次查询的时间范围数据为2023-09-25T19:31:04Z,查询的步长为6秒,共查询了593种指标,共写入10554827行数据 本次查询的时间范围数据为2023-09-25T19:31:40Z,查询的步长为12秒,共查询了593种指标,共写入5942033行数据 本次查询的时间范围数据为2023-09-25T19:32:14Z,查询的步长为60秒,共查询了593种指标,共写入6093494行数据 本次查询的时间范围数据为2023-09-25T19:33:08Z,查询的步长为30秒,共查询了593种指标,共写入4305816行数据 本次查询的时间范围数据为2023-09-25T19:33:39Z,查询的步长为15秒,共查询了593种指标,共写入4897653行数据 本次查询的时间范围数据为2023-09-25T19:34:03Z,查询的步长为45秒,共查询了593种指标,共写入5551486行数据 本次查询的时间范围数据为2023-09-25T19:37:27Z,查询的步长为55秒,共查询了593种指标,共写入5826733行数据 本次查询的时间范围数据为2023-09-25T19:38:07Z,查询的步长为6秒,共查询了593种指标,共写入10711991行数据 # 停止了exporter但是并不是完全没有变动 本次查询的时间范围数据为2023-09-25T19:46:03Z,查询的步长为5秒,共查询了593种指标,共写入9281524行数据 本次查询的时间范围数据为2023-09-25T19:46:32Z,查询的步长为6秒,共查询了593种指标,共写入10808191行数据 本次查询的时间范围数据为2023-09-25T19:46:57Z,查询的步长为7秒,共查询了593种指标,共写入9272944行数据 本次查询的时间范围数据为2023-09-25T19:47:22Z,查询的步长为8秒,共查询了593种指标,共写入8113585行数据 本次查询的时间范围数据为2023-09-25T19:47:44Z,查询的步长为9秒,共查询了593种指标,共写入7386695行数据 本次查询的时间范围数据为2023-09-25T19:48:14Z,查询的步长为10秒,共查询了593种指标,共写入7019614行数据 本次查询的时间范围数据为2023-09-25T19:48:44Z,查询的步长为5秒,共查询了593种指标,共写入9267445行数据 本次查询的时间范围数据为2023-09-25T19:49:37Z,查询的步长为55秒,共查询了593种指标,共写入5840872行数据 本次查询的时间范围数据为2023-09-25T19:50:40Z,查询的步长为15秒,共查询了593种指标,共写入4990036行数据 本次查询的时间范围数据为2023-09-25T19:54:53Z,查询的步长为15秒,共查询了593种指标,共写入5005466行数据 求助智障 以下是和人工智障的对话内容: ...