#!/usr/bin/env python3 import argparse from common import ( build_common_arg_parser, clinic_cluster_meta, clinic_metrics_query, clinic_session, find_metric_definition, inject_expression_variables, parse_clinic_link, remove_label_matcher, series_last_values, write_json, ) def main() -> int: parser = build_common_arg_parser( "Fetch metric values from a Clinic link by loading dashboard/panel expressions from tidb-perf-diagnosis knowledge" ) parser.add_argument("--dashboard-title", required=True, help="Dashboard title from tidb-perf-diagnosis knowledge") parser.add_argument("--panel-title", required=True, help="Panel title from tidb-perf-diagnosis knowledge") parser.add_argument("--expression-index", type=int, default=0, help="Expression index within the selected panel") parser.add_argument("--instance", default=".*", help="Regex for $instance / ${instance:regex}") parser.add_argument("--k8s-cluster", default="", help="Override $k8s_cluster; default empty") parser.add_argument("--step", default="60s", help="Query step") args = parser.parse_args() clinic_context = parse_clinic_link(args.link) session = clinic_session(base_url=args.base_url, profile_name=args.profile) cluster_meta = clinic_cluster_meta(session, clinic_context) metric_def = find_metric_definition(args.dashboard_title, args.panel_title) expressions = metric_def["expressions"] if args.expression_index < 0 or args.expression_index >= len(expressions): raise ValueError(f"expression_index out of range: {args.expression_index}") raw_expr = expressions[args.expression_index] final_expr = inject_expression_variables( raw_expr, clinic_context, variable_rules={ "k8s_cluster": args.k8s_cluster, "instance": args.instance, }, ) attempted_promqls = [final_expr] fallback_notes = [] metrics_payload = clinic_metrics_query(session, clinic_context, final_expr, step=args.step) result = (((metrics_payload or {}).get("data") or {}).get("result")) or [] fallback_expr = "" if not result and 'scope="' in final_expr: fallback_expr = remove_label_matcher(final_expr, "scope") if fallback_expr != final_expr: fallback_notes.append( "Primary query returned no series; retried once after removing the hard-coded scope matcher." ) attempted_promqls.append(fallback_expr) metrics_payload = clinic_metrics_query(session, clinic_context, fallback_expr, step=args.step) write_json( { "clinic_context": clinic_context, "cluster_meta": { "id": cluster_meta.get("id"), "name": cluster_meta.get("name"), "version": cluster_meta.get("version"), "deployType": cluster_meta.get("deployType"), "deployTypeV2": cluster_meta.get("deployTypeV2"), "topology": cluster_meta.get("topology"), "status": cluster_meta.get("status"), }, "knowledge_file": metric_def["knowledge_file"], "dashboard_title": metric_def["dashboard_title"], "panel_title": metric_def["panel_title"], "raw_expression": raw_expr, "final_promql": attempted_promqls[-1], "attempted_promqls": attempted_promqls, "fallback_notes": fallback_notes, "raw_series": metrics_payload, "last_values": series_last_values(metrics_payload), } ) return 0 if __name__ == "__main__": raise SystemExit(main())