排查 Flashduty monitor 监控告警 - 数据不符合预期的场景
巴辉特
2025-12-19 21:58:45
问题说明
用户收到了 Flashduty monitor 监控告警,但是认为数据不符合预期,想要排查具体原因。本文侧重讲解 Prometheus 类型的数据源。
原理说明
Flashduty monitor 会周期性查询时序库(比如 Prometheus)中的监控数据,调用的是 /api/v1/query 接口(Prometheus 原生告警引擎也是这个逻辑),如果使用 Grafana 查看折线图数据,可能会发现数据不符合预期,通常原因是时序库的 query lookback 参数导致的。
咱们也可以不关心具体原理,就直接模仿 Flashduty monitor 的查询方式,去查询告警的时候的数据,看看结果是否符合预期即可。
排查脚本
下面用 AI 生成了一个 Python 脚本,可以用来查询:
import requests
import argparse
import time
from datetime import datetime, timezone, timedelta
promql = """mem_available_percent"""
def cst_to_unix(cst_str):
"""将东八区时间字符串转换为 Unix 时间戳"""
tz_cst = timezone(timedelta(hours=8))
cst_str = cst_str.replace('T', ' ')
dt = datetime.strptime(cst_str, '%Y-%m-%d %H:%M:%S')
dt_cst = dt.replace(tzinfo=tz_cst)
return int(dt_cst.timestamp())
def unix_to_cst_str(ts):
"""将 Unix 时间戳转换回人类易读的东八区时间字符串"""
tz_cst = timezone(timedelta(hours=8))
dt = datetime.fromtimestamp(ts, tz=tz_cst)
return dt.strftime('%Y-%m-%d %H:%M:%S')
def main():
parser = argparse.ArgumentParser(description="Prometheus Query Tool (SRE Debug Version)")
parser.add_argument("--prometheus_url", required=True, help="Prometheus base URL")
parser.add_argument("--start_time", required=True, help="Start time in CST (e.g., '2023-10-01 08:00:00')")
parser.add_argument("--end_time", required=True, help="End time in CST (e.g., '2023-10-01 08:10:00')")
# 第四个参数:步长
parser.add_argument("--step", type=int, default=15, help="Step in seconds (default: 15)")
args = parser.parse_args()
try:
start_ts = cst_to_unix(args.start_time)
end_ts = cst_to_unix(args.end_time)
except ValueError as e:
print(f"Time format error: {e}. Please use 'YYYY-MM-DD HH:MM:SS'")
return
api_endpoint = f"{args.prometheus_url.rstrip('/')}/api/v1/query"
current_ts = start_ts
print(f"\nQuerying: {args.start_time} to {args.end_time} with step {args.step}s\n")
while current_ts <= end_ts:
# 获取人类易读的时间字符串
readable_time = unix_to_cst_str(current_ts)
params = {
"query": promql,
"time": current_ts
}
try:
response = requests.get(api_endpoint, params=params, timeout=5)
response.raise_for_status()
data = response.text
# 修改后的打印语句:同时包含时间戳和易读时间
print(f"------------ {current_ts} | {readable_time} -----------")
print(data + "\n")
except Exception as e:
print(f"------------ {current_ts} | {readable_time} -----------\n")
print(f"Error: {str(e)}\n")
# 使用传入的步长参数进行递增
current_ts += args.step
print(f"Done!")
if __name__ == "__main__":
main()
最上面的 promql 变量可以修改成你想要查询的 PromQL 表达式。可以把脚本内容保存为 debug.py,然后用下面的命令运行:
python3 debug.py \
--prometheus_url http://10.99.1.107:9090 \
--start_time "2025-12-19 21:38:11" \
--end_time "2025-12-19 21:39:11" \
--step 15
- prometheus_url:Prometheus 的访问地址
- start_time:查询的开始时间,东八区时间
- end_time:查询的结束时间,东八区时间
- step:查询的时间步长,单位秒,默认是 15 秒,改成你的告警规则里的频率
比如 2025-12-19 21:39:10 告警了,规则里配置的是 15s 执行一次,连续 4 次告警,那么就可以把结束时间设置成 2025-12-19 21:39:11,开始时间设置成 2025-12-19 21:38:11,步长设置成 15 秒。然后查询测试,看看到底查到什么数据。
这里我故意把结束时间设置为告警时间往后一秒,是担心一些边界情况。具体测试时,你可以多尝试几次不同的时间戳,看看结果。
(py3venv) ulric@ulric-fcc01 misc % python3 debug.py \
--prometheus_url http://10.99.1.107:9090 \
--start_time "2025-12-19 21:38:11" \
--end_time "2025-12-19 21:39:11" \
--step 15
Querying: 2025-12-19 21:38:11 to 2025-12-19 21:39:11 with step 15s
------------ 1766151491 | 2025-12-19 21:38:11 -----------
{"status":"success","data":{"resultType":"vector","result":[{"metric":{"__name__":"mem_available_percent","ident":"cn-beijing.10.99.1.109"},"value":[1766151491,"21.608323685048916"]}]}}
------------ 1766151506 | 2025-12-19 21:38:26 -----------
{"status":"success","data":{"resultType":"vector","result":[{"metric":{"__name__":"mem_available_percent","ident":"cn-beijing.10.99.1.109"},"value":[1766151506,"22.473846026331397"]}]}}
------------ 1766151521 | 2025-12-19 21:38:41 -----------
{"status":"success","data":{"resultType":"vector","result":[{"metric":{"__name__":"mem_available_percent","ident":"cn-beijing.10.99.1.109"},"value":[1766151521,"21.02999645150345"]}]}}
------------ 1766151536 | 2025-12-19 21:38:56 -----------
{"status":"success","data":{"resultType":"vector","result":[{"metric":{"__name__":"mem_available_percent","ident":"cn-beijing.10.99.1.109"},"value":[1766151536,"21.231924036272368"]}]}}
------------ 1766151551 | 2025-12-19 21:39:11 -----------
{"status":"success","data":{"resultType":"vector","result":[{"metric":{"__name__":"mem_available_percent","ident":"cn-beijing.10.99.1.109"},"value":[1766151551,"22.203590456875407"]}]}}
Done!