Cloud Monitoring Chart Generation Skill (cloud-monitoring-chart-generation)
Transforms PromQL queries and metric metadata into valid Server-Driven UI
(SDUI) google.monitoring.dashboard.v1.Widget Protocol Buffer textprotos.
These generated textprotos are designed to be ingested by the Cloud Monitoring
Dashboards API, gcloud CLI, or declarative dashboard provisioning pipelines.
[!CAUTION]
CRITICAL EXECUTION & WORKING DIRECTORY RULES:
- DO NOT CHANGE WORKING DIRECTORY: Keep your working directory at your
workspace root. Do NOT
cd into skill subdirectories.
- NO DISCOVERY OR SEARCH RULE: The metric descriptor, PromQL query,
unit, and resource type are ALWAYS present in the conversation context.
NEVER run file or codebase search tools, such as grep, find, directory
listings, or codebase queries, to discover metric metadata or inspect
repository structures.
- SCRIPT EXECUTION: Execute the bundled Python scripts directly using
python3, for example:
python3 scripts/assemble_widget_proto.py ....
- OUTPUT GENERATION: The
assemble_widget_proto script automatically
generates deterministic sequential filenames like chart.textproto and chart_2.textproto
and saves them to the active workspace. The script will handle naming and saving
automatically, and will print the generated filename to the console.
Prerequisites: Environment Setup
Install the required dependencies in your environment or sandbox:
pip install -r scripts/requirements.txt
3-Stage Pipeline Workflow
[ Stage 1: compute_labels ] ---> [ Stage 2: LLM Synthesis ] ---> [ Stage 3: assemble_widget_proto ]
Generates candidate labels Formulates SemanticPlotSpec Emits validated widget textproto
Stage 1: Baseline Candidate Synthesis
Run Stage 1 using python3:
python3 scripts/compute_labels.py \
--metric_display_name "METRIC_DISPLAY_NAME" \
--resource_type "RESOURCE_TYPE" \
--metric_unit "UNIT" \
--promql_query "PROMQL_QUERY"
Stage 2: SemanticPlotSpec Prediction (LLM)
Review the user prompt, PromQL query structure, and Stage 1 baseline
candidates to formulate a 4-key SemanticPlotSpec JSON object:
title: Polish titleCandidate to ensure it is concise, human-readable,
and under 80 characters.
yAxisLabel: Set this to a concise, human-readable quantitative
descriptor or metric concept, such as "Utilization", "Bytes", or
"Bytes Rate". Do NOT append unit symbols or suffixes such as "(%)",
"(/s)", or "(By)" to the label, because units are rendered automatically
via unitOverride.
plotType: Default to LINE. Use STACKED_AREA if requested by the
user or for distribution queries.
unitOverride: Set this to the Unified Code for Units of Measure
(UCUM) unit string, derived from the PromQL query by applying the Unit
Override Computation Rules below.
Unit Override Computation Rules:
Rate Functions (rate(...), irate(...)): Convert cumulative counters
into per-second rates. Append /s to the raw metric unit. For example, a raw
metric unit of By with rate(...) results in unitOverride: "By/s".
Ratios & Percentages (100 * ... / ...): Ratios of identical metric
units multiplied by 100 represent percentages, resulting in
unitOverride: "%".
Normalizations: Normalize 10^2.% to "%", per the Unified Code for
Units of Measure (UCUM) standard.
Preserved Units: For aggregation functions like avg_over_time(...) or
sum by (...), retain and output the underlying metric unit without
modification. For example, output "%", "By", or "s" unchanged.
Legend Template: Do NOT configure the legend_template field. It is
intentionally omitted so that the Cloud Monitoring frontend dynamically
renders its multi-column table legend at runtime.
Example SemanticPlotSpec:
{
"title": "VM CPU Utilization (us-central1-a)",
"yAxisLabel": "Utilization",
"plotType": "LINE",
"unitOverride": "%"
}
Stage 3: Protobuf Assembly & Output
Run Stage 3 using python3 to generate and save the widget textproto:
python3 scripts/assemble_widget_proto.py \
--promql_query "PROMQL_QUERY" \
--spec_json 'SEMANTIC_PLOT_SPEC_JSON'
[!IMPORTANT]
MANDATORY FILE OUTPUT CONTRACT:
The script automatically names and saves output files like chart.textproto and chart_2.textproto directly in your workspace root without subdirectories.
- Assigned Filename Feedback: Whenever an output file is saved, the script logs the file path to stderr, for example:
Wrote widget textproto to: .../chart.textproto. Read your command execution logs for the exact filename created so you can target it in Stage 4 validation.
- Text Chat Output: Enclose the generated SDUI widget textproto inside a
```textproto code block in your response:
title: "..."
xy_chart {
...
}
Stage 4: Mandatory Self-Verification & Auto-Retry Loop
[!CAUTION]
DO NOT FINISH YOUR TURN UNTIL FILE VERIFICATION PASSES:
- Run Validation Check: Execute the validator script against the
generated file, such as
chart.textproto or the sequential filename like
chart_2.textproto output from Stage 3:python3 scripts/validate_chart.py --input_file "GENERATED_FILE.textproto"
- Auto-Retry if Missing or Failed: If
validate_chart reports that the
file is missing or invalid, verify your script parameters and immediately re-run Stage 3:python3 scripts/assemble_widget_proto.py \
--promql_query "PROMQL_QUERY" \
--spec_json 'SEMANTIC_PLOT_SPEC_JSON'
- Validation & Retries: Run
validate_chart to verify the generated
textproto. If validation fails due to a schema or syntax error, correct
the parameters and retry up to 2 times. If validation still fails after 2
retries, stop retrying, notify the user of the validation error, and
present the best-effort textproto.
- Execution vs. Validation Errors: Note that schema/syntax validation
errors from
validate_chart.py are distinct from OS or environment
execution restrictions, such as Permission denied or Command not found,
which are handled below in Graceful Sandbox Fallback.
Graceful Sandbox Fallback
If compute_labels.py, assemble_widget_proto.py, or validate_chart.py
cannot be executed due to environment or sandbox restrictions, do the
following:
- Notify the user which script cannot be executed and why.
- Synthesize and output the complete widget textproto directly in your
response, following all formatting and unit rules.
- Provide a "Local Verification" section containing the standalone python3
commands so the user can run and validate the schema locally if desired.
Supporting Links
1---2name: cloud-monitoring-chart-generation3description: Generates Google Cloud Monitoring Server-Driven UI (SDUI) Widget and XyChart Protocol Buffer textprotos from resolved PromQL queries. Use when: - Generating valid google.monitoring.dashboard.v1.Widget textprotos, containing PrometheusQuery datasets, for use with the Cloud Monitoring Dashboards API, gcloud CLI, or declarative dashboard definitions. - Synthesizing Server-Driven UI (SDUI) widget titles, axis labels, and plot types for Prometheus queries. Don't use for: - Metric discovery or PromQL query generation. For those tasks, use the cloud-monitoring-metric-selection or cloud-monitoring-promql-query skills.4---56# Cloud Monitoring Chart Generation Skill (`cloud-monitoring-chart-generation`)78Transforms PromQL queries and metric metadata into valid Server-Driven UI9(SDUI) `google.monitoring.dashboard.v1.Widget` Protocol Buffer textprotos.10These generated textprotos are designed to be ingested by the Cloud Monitoring11Dashboards API, gcloud CLI, or declarative dashboard provisioning pipelines.1213> [!CAUTION]14> **CRITICAL EXECUTION & WORKING DIRECTORY RULES**:15> - **DO NOT CHANGE WORKING DIRECTORY**: Keep your working directory at your16> workspace root. Do NOT `cd` into skill subdirectories.17> - **NO DISCOVERY OR SEARCH RULE**: The metric descriptor, PromQL query,18> unit, and resource type are ALWAYS present in the conversation context.19> **NEVER** run file or codebase search tools, such as grep, find, directory20> listings, or codebase queries, to discover metric metadata or inspect21> repository structures.22> - **SCRIPT EXECUTION**: Execute the bundled Python scripts directly using23> python3, for example: `python3 scripts/assemble_widget_proto.py ...`.24> - **OUTPUT GENERATION**: The `assemble_widget_proto` script automatically25> generates deterministic sequential filenames like `chart.textproto` and `chart_2.textproto`26> and saves them to the active workspace. The script will handle naming and saving27> automatically, and will print the generated filename to the console.2829## Prerequisites: Environment Setup3031Install the required dependencies in your environment or sandbox:3233```bash34pip install -r scripts/requirements.txt35```3637## 3-Stage Pipeline Workflow3839```40[ Stage 1: compute_labels ] ---> [ Stage 2: LLM Synthesis ] ---> [ Stage 3: assemble_widget_proto ]41 Generates candidate labels Formulates SemanticPlotSpec Emits validated widget textproto42```4344### Stage 1: Baseline Candidate Synthesis4546Run Stage 1 using python3:4748```bash49python3 scripts/compute_labels.py \50 --metric_display_name "METRIC_DISPLAY_NAME" \51 --resource_type "RESOURCE_TYPE" \52 --metric_unit "UNIT" \53 --promql_query "PROMQL_QUERY"54```5556### Stage 2: SemanticPlotSpec Prediction (LLM)5758Review the user prompt, PromQL query structure, and Stage 1 baseline59candidates to formulate a 4-key `SemanticPlotSpec` JSON object:60611. **`title`**: Polish `titleCandidate` to ensure it is concise, human-readable,62 and under 80 characters.632. **`yAxisLabel`**: Set this to a concise, human-readable quantitative64 descriptor or metric concept, such as `"Utilization"`, `"Bytes"`, or65 `"Bytes Rate"`. Do NOT append unit symbols or suffixes such as `"(%)"`,66 `"(/s)"`, or `"(By)"` to the label, because units are rendered automatically67 via `unitOverride`.683. **`plotType`**: Default to `LINE`. Use `STACKED_AREA` if requested by the69 user or for distribution queries.704. **`unitOverride`**: Set this to the Unified Code for Units of Measure71 (UCUM) unit string, derived from the PromQL query by applying the **Unit72 Override Computation Rules** below.7374#### Unit Override Computation Rules:75- **Rate Functions (`rate(...)`, `irate(...)`)**: Convert cumulative counters76 into per-second rates. Append `/s` to the raw metric unit. For example, a raw77 metric unit of `By` with `rate(...)` results in `unitOverride: "By/s"`.78- **Ratios & Percentages (`100 * ... / ...`)**: Ratios of identical metric79 units multiplied by 100 represent percentages, resulting in80 `unitOverride: "%"`.81- **Normalizations**: Normalize `10^2.%` to `"%"`, per the Unified Code for82 Units of Measure (UCUM) standard.83- **Preserved Units**: For aggregation functions like `avg_over_time(...)` or84 `sum by (...)`, retain and output the underlying metric unit without85 modification. For example, output `"%"`, `"By"`, or `"s"` unchanged.8687- **Legend Template**: Do NOT configure the `legend_template` field. It is88 intentionally omitted so that the Cloud Monitoring frontend dynamically89 renders its multi-column table legend at runtime.9091Example `SemanticPlotSpec`:92```json93{94 "title": "VM CPU Utilization (us-central1-a)",95 "yAxisLabel": "Utilization",96 "plotType": "LINE",97 "unitOverride": "%"98}99```100101### Stage 3: Protobuf Assembly & Output102103Run Stage 3 using python3 to generate and save the widget textproto:104105```bash106python3 scripts/assemble_widget_proto.py \107 --promql_query "PROMQL_QUERY" \108 --spec_json 'SEMANTIC_PLOT_SPEC_JSON'109```110111> [!IMPORTANT]112> **MANDATORY FILE OUTPUT CONTRACT**:113> The script automatically names and saves output files like `chart.textproto` and `chart_2.textproto` directly in your workspace root without subdirectories.114115- **Assigned Filename Feedback**: Whenever an output file is saved, the script logs the file path to stderr, for example: `Wrote widget textproto to: .../chart.textproto`. Read your command execution logs for the exact filename created so you can target it in Stage 4 validation.116- **Text Chat Output**: Enclose the generated SDUI widget textproto inside a ```` ```textproto ```` code block in your response:117118```textproto119title: "..."120xy_chart {121 ...122}123```124125### Stage 4: Mandatory Self-Verification & Auto-Retry Loop126127> [!CAUTION]128> **DO NOT FINISH YOUR TURN UNTIL FILE VERIFICATION PASSES**:129> 1. **Run Validation Check**: Execute the validator script against the130> generated file, such as `chart.textproto` or the sequential filename like131> `chart_2.textproto` output from Stage 3:132> ```bash133> python3 scripts/validate_chart.py --input_file "GENERATED_FILE.textproto"134> ```135> 2. **Auto-Retry if Missing or Failed**: If `validate_chart` reports that the136> file is missing or invalid, verify your script parameters and immediately re-run Stage 3:137> ```bash138> python3 scripts/assemble_widget_proto.py \139> --promql_query "PROMQL_QUERY" \140> --spec_json 'SEMANTIC_PLOT_SPEC_JSON'141> ```142> 3. **Validation & Retries**: Run `validate_chart` to verify the generated143> textproto. If validation fails due to a schema or syntax error, correct144> the parameters and retry up to 2 times. If validation still fails after 2145> retries, stop retrying, notify the user of the validation error, and146> present the best-effort textproto.147> 4. **Execution vs. Validation Errors**: Note that schema/syntax validation148> errors from `validate_chart.py` are distinct from OS or environment149> execution restrictions, such as `Permission denied` or `Command not found`,150> which are handled below in **Graceful Sandbox Fallback**.151152#### Graceful Sandbox Fallback153If `compute_labels.py`, `assemble_widget_proto.py`, or `validate_chart.py`154cannot be executed due to environment or sandbox restrictions, do the155following:1561. Notify the user which script cannot be executed and why.1572. **Synthesize and output the complete widget textproto directly in your158 response**, following all formatting and unit rules.1593. Provide a **"Local Verification"** section containing the standalone python3160 commands so the user can run and validate the schema locally if desired.161162## Supporting Links163164- [Dashboards API](https://docs.cloud.google.com/monitoring/dashboards/api-dashboard)165- [Prometheus Docs](https://prometheus.io/docs/prometheus/latest/querying/)