ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Cloud Monitoring 仪表盘 Widget 生成:从 PromQL / ListTimeSeries 查询到 SDUI textproto 的三阶段工作流

Cloud Monitoring 仪表盘 Widget 生成:从 PromQL / ListTimeSeries 查询到 SDUI textproto 的三阶段工作流 Cloud Monitoring 仪表盘 Widget 生成从 PromQL / ListTimeSeries 查询到 SDUI textproto 的三阶段工作流【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills本文基于skills/cloud/cloud-monitoring-chart-generation技能Agent Skill讲解如何将已解析好的 PromQL 查询或 ListTimeSeries JSON 请求转换为可直接被 Cloud Monitoring Dashboards API、gcloud CLI 或声明式仪表盘供给流水线消费的google.monitoring.dashboard.v1.WidgetProtocol Buffer textproto。读完本文你将掌握该技能的三阶段流水线基线标签计算 → LLM 合成 SemanticPlotSpec → textproto 组装、两条 API 的互斥约束、UCUM 单位归一化规则以及配套的 schema 校验与自动重试机制。技能定位与核心约束该技能位于 SKILL.md其元数据声明了明确的适用边界适用生成包含PrometheusQuery或TimeSeriesFilter数据集的合法 Widget textproto为 Prometheus 或 ListTimeSeries 查询合成 SDUI 组件的标题、坐标轴标签和绘图类型。不适用指标发现或 PromQL 查询生成本身——这些任务应交给仓库中的cloud-monitoring-metric-selection和 cloud-monitoring-promql-query 技能。仓库根目录的 index.json 中同样登记了这一分工可见本技能是整个 Cloud Monitoring 技能族中查询已就绪、只差落盘成仪表盘组件的最后一公里。文档开篇给出了三条必须严格遵守的规则原文 IMPORTANT 提示框API 偏好除非用户显式要求 PromQL或指标数学上必须使用 PromQL否则始终优先生成ListTimeSeriestime_series_filter配置。互斥查询一个 widget 数据集的time_series_query中只能包含time_series_filter或prometheus_query二者之一绝不允许同时填充两个字段。严格透传必须逐字符拷贝上下文中已提供的 PromQL 查询或 ListTimeSeries JSON filter 字符串禁止发明、改写或修改查询。此外还有两条执行纪律原文 CAUTION 提示框保持工作目录在 workspace 根目录、禁止cd进入技能子目录禁止运行任何文件/代码库搜索工具去发现指标元数据——指标描述符、查询、单位、资源类型在会话上下文中永远已经存在直接用 python3 执行随附脚本assemble_widget_proto会自动生成基于 UUID 的独立文件名以避免并行执行冲突并以前缀 Wrote widget textproto to: 打印到 stderr后续校验阶段必须从日志中解析这一前缀来定位产物。环境准备依赖安装只有一条命令requirements.txt 声明核心脚本仅使用 Python 3.10 标准库模块运行时无需外部 PyPI 包pip install -r scripts/requirements.txt三阶段流水线总览整个工作流是一条固定管线[ Stage 1: compute_labels ] --- [ Stage 2: LLM Synthesis ] --- [ Stage 3: assemble_widget_proto ] Generates candidate labels Formulates SemanticPlotSpec Emits validated widget textproto即脚本先产出候选标题与单位LLM 基于候选值做语义精修得到SemanticPlotSpec最后一个脚本把 spec 与查询一起组装成校验通过的 textproto 文件并由校验器闭环验证。Stage 1基线候选合成compute_labelsStage 1 由 compute_labels.py 驱动根据查询类型分两种调用方式# For PromQL: python3 scripts/compute_labels.py \ --metric_display_name METRIC_DISPLAY_NAME \ --resource_type RESOURCE_TYPE \ --metric_unit UNIT \ --promql_query PROMQL_QUERY # For ListTimeSeries: python3 scripts/compute_labels.py \ --metric_display_name METRIC_DISPLAY_NAME \ --resource_type RESOURCE_TYPE \ --metric_unit UNIT \ --filter_string metric.typem... \ --per_series_aligner ALIGN_RATE \ --cross_series_reducer REDUCE_SUM脚本最终向 stdout 打印一个三键 JSONtitleCandidate、yAxisLabelCandidate、unitOverrideCandidate供 Stage 2 消费。源码视角标题是如何合成的阅读 compute_labels.py 可以发现候选标题并非随意拼接而是一套有明确约束的模板资源类型展示名映射内置COMMON_RESOURCE_DISPLAY_MAP覆盖 30 余种标准受监控资源如gce_instance→ VM Instance、k8s_pod→ Kubernetes Pod、spanner_instance→ Cloud Spanner Instance、gcs_bucket→ GCS Bucket 等。当指标名存在歧义时is_ambiguous_metric_name为真标题会以 VM Instance - CPU Utilization 这种资源 - 指标格式前缀化。筛选与分组从 PromQL 的标签匹配器或 LTS filter 字符串中提取等值条件剔除project_id、resource.type等噪声键标题追加for 前两个筛选值group by (...)字段会被清洗掉metric.label./resource.前缀后追加by 字段。聚合标注聚合方式如RATE、SUM以大写[AGG]后缀呈现。compute_labels_test.py 中有对应断言输入 Disk Read Bytes gce_instance zone 筛选 device_name分组 SUM聚合产出精确等于Disk Read Bytes for us-east1-d by device_name [SUM]。80 字符硬约束超过 80 字符时先压缩过长的 group 部分替换为 (grouped)、筛选部分替换为 (filtered)仍超长则截断至 77 字符并补 ...。测试test_compute_widget_title_long_truncation验证了截断结果必然endswith(...)且长度不超过 80。源码视角PromQL 特征提取对 PromQL 分支extract_promql_features会先做三步净化——移除字符串字面量双引号/单引号/反引号、移除模板变量${...}、$var、[[...]]、移除标签匹配器块{...}——然后再做用\b(rate|irate)\s*\(检测速率函数在净化后的查询中查找第一个聚合关键字sum/avg/count/min/max/stddev/stdvar/topk/bottomk/count_values/quantile并刻意跳过compute_googleapis_com:这类带:、.、/的指标标识符片段避免把命名空间误判为聚合函数用\bby\s*\(([^)])\)提取分组字段。对 LTS 分支extract_filter_features从 filter 字符串中解析metric.type、resource.type和其余等值条件且has_rate直接由per_series_aligner ALIGN_RATE判定——也就是说 LTS 流程中是否速率完全由对齐器表达。源码视角UCUM 单位归一化normalize_ucum_unit实现了文档中 LTS 单位策略 背后的数学处理空单位或哨兵值{not_a_unit}→ 空字符串去除空白把字面量(rate)替换为/s若存在 rate aligner 且单位尚未以/s结尾则自动追加/sBy→By/s1→1/s剥离{...}形式的维度标注例如s{CPU}/s归一化为s/s10^2.%统一归一化为%。归一化结果再查CANONICAL_UNIT_DISPLAY_MAP得到坐标轴展示名%/10^2.%→ UtilizationBy→ BytesBy/s→ Bytes Rates/s→ Utilization1/s→ Operations Rate 等。compute_axis_label在单位集合唯一且非空时直接返回该展示名多指标单位不一致时回退为指标展示名列表用逗号连接完全无单位时返回兜底值 PromQL Metric Axis。测试文件 compute_labels_test.py 覆盖了10^2.%→ Utilization、By rate → Bytes Rate、多单位回退到 Disk Read Bytes, Read Latency 等关键路径。这正是 SKILL.md 中 Trust the Candidate 策略的依据LTS 流程下unitOverrideCandidate已经是数学处理后的结果Stage 2 直接照抄即可。Stage 2SemanticPlotSpec 合成LLM审阅用户提示词、查询结构和 Stage 1 候选值后LLM 需要产出一个四键JSON 对象SemanticPlotSpectitle在titleCandidate基础上润色保证简洁、人类可读、且不超过 80 字符yAxisLabel简洁的定量描述词或指标概念如Utilization、Bytes、Bytes Rate。不要在标签后追加单位符号或后缀如(%)、(/s)、(By)因为单位会经由unitOverride自动渲染plotType默认LINE用户要求或分布类查询时使用STACKED_AREAunitOverride设为 UCUM 单位字符串按以下两套策略推导。LTS 单位策略直接采用 Stage 1 产出的unitOverrideCandidate。Stage 1 会数学化处理ALIGN_RATE例如输出By/s、对ALIGN_PERCENT_CHANGE强制输出%并无条件正确输出原生归一化结果——compute_labels.py 中per_series_aligner ALIGN_PERCENT_CHANGE时unit_override被硬性覆盖为%与此说明一一对应。PromQL 单位策略LLM 手动推导由于 PromQL 表达式可以几何级组合例如histogram_quantile(..., rate(...))最终单位必须由 LLM 的语义推理决定速率函数rate(...)、irate(...)把累积计数器转为每秒速率在原始指标单位后追加/s。例如原始单位为By且套了rate(...)则unitOverride: By/s。例外若rate()出现在histogram_quantile()内部输出是原始桶单位如s而不是速率。比率与百分比100 * (A / B)相同单位的比率通常表示百分比unitOverride: %。归一化10^2.%归一化为%。保留单位简单的聚合函数如avg_over_time(...)、sum by (...)保持底层指标单位不变。文档还特别强调不要配置legend_template字段——它被刻意省略以便 Cloud Monitoring 前端在运行时动态渲染其多列表格图例。这一点在源码中同样有体现assemble_widget_proto.py 的assemble_widget_textproto不输出任何legend_template行且 assemble_widget_proto_test.py 用assertNotIn(legend_template:, proto_text)做了硬断言。文档给出的示例 spec{ title: VM CPU Utilization us-central1-a, yAxisLabel: Utilization, plotType: LINE, unitOverride: % }Stage 3Protobuf 组装与输出assemble_widget_protoStage 3 由 assemble_widget_proto.py 执行按查询类型二选一# For PromQL: python3 scripts/assemble_widget_proto.py \ --promql_query PROMQL_QUERY \ --spec_json SEMANTIC_PLOT_SPEC_JSON # For ListTimeSeries: python3 scripts/assemble_widget_proto.py \ --lts_request_json {filter: ..., aggregation: {...}} \ --spec_json SEMANTIC_PLOT_SPEC_JSON文档在此处的文件输出契约MANDATORY FILE OUTPUT CONTRACT要求不要猜测或强制指定输出文件名。脚本自动生成保证唯一性的文件名并把路径打印到 stderr需从 stderr 中搜索前缀 Wrote widget textproto to: 确定性地捕获该文件名再作为 Stage 4 校验的目标。源码印证了这一契约get_auto_output_path以uuid.uuid4().hex[:8]生成chart_8位hex.textproto并循环检查避免撞名main结尾执行print(fWrote widget textproto to: {output_path}, filesys.stderr)assemble_widget_proto.py、#L272-L277。测试test_get_auto_output_path断言产物必然以chart_开头、以.textproto结尾。--spec_json中的四个键会覆盖命令行上的--title/--plot_type/--y_axis_label/--unit_overrideLTS 分支的--lts_request_json是必填filter键的 JSON缺失时脚本以退出码 1 报错。最终在聊天回复中生成的 textproto 应包裹在textproto代码块中呈现title: ... xy_chart { ... }源码视角textproto 的精确结构与合法值白名单assemble_widget_textproto生成的结构完全固定widget { title, xy_chart { chart_options { mode: COLOR }, data_sets { time_series_query, plot_type, target_axis: Y1 }, y_axis { label, scale } } }。其中几个校验点值得注意绘图类型白名单只接受LINE、STACKED_AREA、STACKED_BAR、HEATMAP非法值静默回退为LINEassemble_widget_proto.py对齐器/归约器白名单perSeriesAligner必须在 19 个VALID_ALIGNERS内ALIGN_NONE、ALIGN_DELTA、ALIGN_RATE、ALIGN_INTERPOLATE、ALIGN_NEXT_OLDER、ALIGN_MIN/MAX/MEAN/COUNT/SUM/STDDEV、ALIGN_COUNT_TRUE/FALSE、ALIGN_FRACTION_TRUE、ALIGN_PERCENTILE_99/95/50/05、ALIGN_PERCENT_CHANGEcrossSeriesReducer必须在 14 个VALID_REDUCERS内REDUCE_NONE至REDUCE_PERCENTILE_05任一非法都抛出ValueError并以退出码 1 终止#L9-L46时长解析aggregation.alignmentPeriod支持s/m/h/d后缀的健壮解析如60s→seconds: 60字符串转义format_proto_string对\和做 protobuf 文本格式转义保证查询中内嵌引号常见于 LTS filter 的metric.type...不会被破坏。以一个典型的 ListTimeSeries CPU 利用率 widget 为例组装结果形如widget { title: GCE Instance CPU Utilization xy_chart { chart_options { mode: COLOR } data_sets { time_series_query { time_series_filter { filter: metric.type\compute.googleapis.com/instance/cpu/utilization\ aggregation { alignment_period { seconds: 60 } per_series_aligner: ALIGN_MEAN cross_series_reducer: REDUCE_NONE } } unit_override: % } plot_type: LINE target_axis: Y1 } y_axis { scale: LINEAR } } }而 validate_chart_test.py 中的真实样例展示了 PromQL 分支的产物形态widget { title: GCE Instance CPU Utilization xy_chart { chart_options { mode: COLOR } data_sets { time_series_query { prometheus_query: 100 * avg(compute_googleapis_com:instance_cpu_utilization) unit_override: % } plot_type: LINE target_axis: Y1 } y_axis { label: Utilization (%) scale: LINEAR } } }注意两个分支的差异LTS 分支输出time_series_filter { filter aggregation }PromQL 分支输出单行prometheus_query: ...——二者在结构上天然互斥与文档 IMPORTANT 框的第 2 条规则严格一致。校验与自动重试validate_chart文档将校验通过设为结束回合的前置条件DO NOT FINISH YOUR TURN UNTIL FILE VERIFICATION PASSES流程为验证产物对 Stage 3 生成的文件运行校验器PromQL 与 LTS 图表分别用不同子串参数# For PromQL charts: python3 scripts/validate_chart.py --input_file GENERATED_FILE.textproto \ --expected_promql_substring SOME_IDENTIFYING_SUBSTRING_FROM_QUERY \ --expected_unit_override UNIT_OVERRIDE_CANDIDATE # For ListTimeSeries (LTS) charts: python3 scripts/validate_chart.py --input_file GENERATED_FILE.textproto \ --expected_lts_filter_substring SOME_IDENTIFYING_SUBSTRING_FROM_FILTER \ --expected_unit_override UNIT_OVERRIDE_CANDIDATE必须始终提供识别子串和 Stage 1 的单位候选值以确认数据未被篡改。为多个指标生成多张图表时必须对每个文件独立运行一次校验。缺失或失败时自动重试若validate_chart报告文件缺失或非法核对参数后立即重跑 Stage 3。重试上限因 schema 或语法错误导致的校验失败修正参数后最多重试 2 次2 次后仍失败则停止重试向用户报告校验错误并给出尽力而为的 textproto。区分错误类型validate_chart.py的 schema/语法校验错误与环境/沙箱执行限制是两类问题后者走下面的优雅回退流程。validate_chart.py 的验证逻辑与文档描述逐项对应结构校验Phase 1标题非空且不超过 80 字符必须存在xy_chart且至少一个data_set每个data_set必须恰好含prometheus_query或time_series_filter之一两者皆无或皆有都会抛错——测试test_validate_widget_dual_query_fails专门断言同时填充两者时报 cannot contain BOTH。断言校验Phase 2在任一data_set上匹配--expected_promql_substring/--expected_lts_filter_substring/--expected_unit_override/--expected_plot_type注意 LTS 子串匹配的是time_series_filter.filter字段。输入来源--input_file支持具体路径、-STDIN或留空glob 工作目录下全部*.textproto。底层解析器零依赖的 textproto 语法校验校验依赖 textproto_util.py它不依赖 protobuf 运行时而是实现了一个轻量级的基于语法的解析器tokenize_textproto把文本切成SYM/STR/{/}/:token支持注释行、单双引号字符串和反斜杠转义parse_textproto_tokens递归地把 token 流解析为嵌套字典重复键自动转列表符合 textproto 的 repeated 语义dict_to_widget映射到Widget → XyChart → DataSet → TimeSeriesQuery → TimeSeriesFilter/Aggregation的 dataclass 层次并做严格字段边界检查——任何一层出现未知键如顶层多了字段、aggregation里冒出alignment_period之外的键都会抛出ValueError。这意味着校验器不只是能解析还保证产物不会携带 Dashboards API 语义之外的多余字段。validate_chart_test.py 覆盖了带widget { }外层包裹、不带包裹、空标题失败、双查询失败、STDIN 输入--input_file -配合rate(compute_googleapis_com:instance_disk_read_bytes_count[1m])unit_override: By/s断言等场景与文档的 Stage 4 行为闭环。沙箱优雅回退当compute_labels.py、assemble_widget_proto.py或validate_chart.py因环境或沙箱限制无法执行时文档要求告知用户哪个脚本无法执行及原因在回复中直接合成并输出完整的 widget textproto遵循全部格式与单位规则附一个Local Verification小节包含独立的 python3 命令方便用户本地运行校验 schema。与相邻技能的衔接关系在本仓库的技能族中cloud-monitoring-chart-generation处于明确的流水线末端指标选择由 cloud-monitoring-metric-selection 负责ListTimeSeries 请求体构造由 cloud-monitoring-list-time-series-request 负责PromQL 表达式编写由 cloud-monitoring-promql-query 负责这些技能产出的已解析查询 指标元数据display name、resource type、unit正是本技能 Stage 1 的四个必填输入。文档的 No Discovery Or Search Rule 之所以成立正是因为上游技能已经完成了发现工作——这也是理解该技能执行纪律的关键。小结该技能把把一条已就绪的监控查询变成合法仪表盘组件这件事拆成了三个职责单一的环节确定性脚本负责候选标签与单位数学可被 compute_labels_test.py 等测试精确断言、LLM 负责语义层的标题润色与 PromQL 单位推理、确定性脚本负责 proto 组装与白名单校验plot_type、aligner、reducer最后由零依赖的 textproto 解析器做闭环验证。配合 UUID 文件名、stderr 前缀契约和最多重试 2 次的止损策略整条管线既适合单指标手工操作也适合在并行会话中批量生成多个 widget 文件。配套参考文档 Supporting Links 指向的官方资源Cloud Monitoring Dashboards API 文档与 Prometheus 查询语言文档仓库内可进一步阅读 SKILL.md 与 scripts/ 目录下的完整实现与测试。【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表