Example dashboards and layouts Stay organized with collections Save and categorize content based on your preferences.
This page illustrates how you can create dashboards byusing the Cloud Monitoring API. For each example, the dashboard definitionin JSON and the corresponding dashboard are shown. You can provideJSON to both Google Cloud CLI and to Cloud Monitoring API endpoints.
Cloud Monitoring also provides a curated set of dashboard definitionson GitHub. You can install these definitions in your Google Cloud project ascustom dashboards. For information about this repositoryand how to install these dashboards, seeInstall sample dashboards.
When to use the API or the Google Cloud CLI
The Cloud Monitoring API and the Google Cloud CLI provide you with a way ofmanaging many dashboards at once.While you can use theGoogle Cloud console to manage your dashboards,you might find it easier to use scripts that manage yourcustom dashboards in bulk.
You also need to use the API when you want to add the blank placeholder widgetto your dashboard.
Using MQL or PromQL with the API
You create dashboards by using thedashboards.createmethod. You pass to the API method aDashboard object, which containsone entry for each widget that the dashboard displays.
When a widget displays time-series data, such as a chart widget,its entry in theDashboard objectcontains aTimeSeriesQuery object.This object describes the time-series data tochart, and you specify that data by using aMonitoring filter, anMQL query, or aPromQL query:
To use Monitoring filters, populate the
timeSeriesFieldfield. The examples on this page use Cloud Monitoring filters.To use an MQL query, populate the
timeSeriesQueryLanguagefield.For more information, seeBuilding charts.To use a PromQL query, populate the
prometheusQueryfield.For general information, seePromQL in Cloud Monitoring.
Dashboard layouts
This section contains information about the different dashboard layoutsthat are available.
Dashboard inGridLayout
This dashboard shows aGridLayout with three widgets.
{ "displayName": "Grid Layout Example", "gridLayout": { "columns": "2", "widgets": [ { "title": "Widget 1", "xyChart": { "dataSets": { "timeSeriesQuery": { "timeSeriesFilter": { "filter": "metric.type=\"agent.googleapis.com/nginx/connections/accepted_count\"", "aggregation": { "perSeriesAligner": "ALIGN_RATE" } }, "unitOverride": "1" }, "plotType": "LINE" }, "timeshiftDuration": "0s", "yAxis": { "label": "y1Axis", "scale": "LINEAR" } } }, { "text": { "content": "Widget 2" } }, { "title": "Widget 3", "xyChart": { "dataSets": { "timeSeriesQuery": { "timeSeriesFilter": { "filter": "metric.type=\"agent.googleapis.com/nginx/connections/accepted_count\"", "aggregation": { "perSeriesAligner": "ALIGN_RATE" } }, "unitOverride": "1" }, "plotType": "STACKED_BAR" }, "timeshiftDuration": "0s", "yAxis": { "label": "y1Axis", "scale": "LINEAR" } } } ] }}The dashboard looks similar to the following example:

Dashboard inMosaicLayout
This dashboard shows aMosaicLayout with two widgets.
{ "displayName": "Mosaic Layout Example", "mosaicLayout": { "columns": 12, "tiles": [ { "xPos": 2, "yPos": 2, "width": 7, "height": 2, "widget": { "title": "CPU utilization in us-central1-a", "scorecard": { "timeSeriesQuery": { "timeSeriesFilter": { "filter": "metric.type=\"compute.googleapis.com/instance/cpu/utilization\" resource.type=\"gce_instance\" resource.label.zone=\"us-central1-a\"", "aggregation": { "perSeriesAligner": "ALIGN_MEAN", "crossSeriesReducer": "REDUCE_MAX" } }, "unitOverride": "1" }, "gaugeView": { "upperBound": 1.5 }, "thresholds": [ { "value": 0.8, "color": "YELLOW", "direction": "ABOVE" }, { "value": 1, "color": "RED", "direction": "ABOVE" } ] } } }, { "xPos": 1, "yPos": 5, "width": 4, "height": 4, "widget": { "title": "My Chart", "xyChart": { "dataSets": [ { "timeSeriesQuery": { "timeSeriesFilter": { "filter": "metric.type=\"compute.googleapis.com/instance/cpu/utilization\" resource.type=\"gce_instance\"", "aggregation": { "perSeriesAligner": "ALIGN_MEAN", "crossSeriesReducer": "REDUCE_MAX", "groupByFields": [ "resource.label.zone" ] } }, "unitOverride": "'1'" }, "plotType": "LINE", "minAlignmentPeriod": "60s" } ], "yAxis": { "label": "y1Axis", "scale": "LINEAR" } } } } ] }}The dashboard looks similar to the following example:

Dashboard inRowLayout
This dashboard displays aRowLayout with three widgets.
{ "displayName": "Row Layout Example", "rowLayout": { "rows": [ { "weight": "1", "widgets": [ { "text": { "content": "Widget 1", "format": "MARKDOWN" } }, { "text": { "content": "Widget 2", "format": "MARKDOWN" } }, { "text": { "content": "Widget 3", "format": "MARKDOWN" } } ] } ] }}The dashboard looks similar to the following example:

Dashboard inColumnLayout
This dashboard displays aColumnLayout with threewidgets.
{ "displayName": "Column Layout Example", "columnLayout": { "columns": [ { "weight": "1", "widgets": [ { "text": { "content": "Widget 1", "format": "MARKDOWN" } }, { "text": { "content": "Widget 2", "format": "MARKDOWN" } }, { "text": { "content": "Widget 3", "format": "MARKDOWN" } } ] } ] }}The dashboard looks similar to the following example:

Enable dashboard events, and add filters and labels
This section describes how you can add filters and labels to a dashboard,and how you can configure a dashboard to show events.
Enable events on dashboards
You can configure a dashboard toshow events,such as a Google Kubernetes Engine update event or a virtual machine failure event,by including anannotations field in theDashboardobject. Theannotations field contains an instance of aDashboardAnnotations object, which contains two fields:
The
defaultResourceNamefield lists the dashboard-level defaults for theGoogle Cloud projects to search for events. If you don't specify this field,then your selected project is searched.An array of
EventAnnotationobjects. Eachobject contains the following:- A
displayNamefield, which lets you define the label on theevent-specific toggle. When this field isn't specified or when the valueof this field is an empty string,the default name for the event is displayed. - An
enabledfield, which controls the value of the event's toggle.Whentrue, the toggle is in theonposition and events are shownon the dashboard. Whenfalse, the toggle is in theoffposition. - An
eventTypefield, which contains a value from theEventTypeenumeration. - A
filterfield, which lets you specify a query to append to theevent-specific query. When the value of this field is an empty string,then the event-specific query is used. - A
resourceNamesfield, which lets you define a list ofGoogle Cloud projects to search for events. When this fieldis an empty array, your selected project is searched.
- A
The following example shows anannotations field that specifies aGoogle Kubernetes Engine event:
{ "displayName": "Annotation example", "annotations": { "defaultResourceNames": [], "eventAnnotations": [ { "displayName": "", "enabled": true, "eventType": "GKE_CLUSTER_UPDATE", "filter": "resource.labels.cluster_name=my-cluster", "resourceNames": [] } ] }, "dashboardFilters": [], "mosaicLayout": { ... }, "labels": {}}In the previous example, thefilter field is used to restrict the queryto the clustermy-name. ThedisplayName field is set toan empty string, so the default name for the event type is displayed onthe event's toggle. Finally, because theresourceNames is set toan empty array, the log entries in your current Google Cloud projectare queried.
Add dashboard filters and variables
To control which data the widgets on a dashboard display, you can addvariables and pinned filters. Variables differ from pinned filters in thatthey apply to specific widgets.
If you create a pinned filter or variable, then Monitoringupdates the toolbar of your custom dashboard to display a filter.For pinned filters, the name of the toolbar filter is the name of the pinnedfilter. For variables, the name of the toolbar filter is a dollar sign$followed by the name of the variable. Each toolbar filter contains a menuthat lets you change the value of the associated pinned filter or variable.For variables, you canreplace the toolbar filter with a dashboard widget. To learn more, seeDashboard with aFilterControl widget.
For more information about variables and pinned filters, and to learn howto apply a variable to a widget, seeDashboard filters.
Add dashboard labels
This sample shows aDashboard object thatspecifies the label namedplaybook.
{ "displayName": "Example", "mosaicLayout": { "columns": 12, "tiles": [ ... ] }, "dashboardFilters": [], "labels": { "playbook": "" }}As the previous sample illustrates, thelabels field is implemented as amap, where thekey andvalue fields are both strings. When you add alabel to a dashboard, set thekey to the name of the label, and set thevalue field to an empty string.
Adding labels to a dashboard is optional.
Dashboards withWidgets
This section includes examples of dashboards that contain different typesof widgets.
Dashboard with anXyChart
This dashboard shows a dashboard with a basicXyChart. Ifyou ever used the Google Cloud console to create charts on dashboards, those chartsare instances of theXyChart widget.
Similar to the functionality provided in the Google Cloud console, the APIprovides options to change the chart'sPlotType or toconfigure the chart'sview modes.
{ "dashboardFilters": [], "displayName": "Example line chart", "labels": {}, "mosaicLayout": { "columns": 48, "tiles": [ { "height": 16, "widget": { "title": "VM Instance - CPU utilization [MEAN]", "xyChart": { "chartOptions": { "mode": "COLOR" }, "dataSets": [ { "minAlignmentPeriod": "60s", "plotType": "LINE", "targetAxis": "Y1", "timeSeriesQuery": { "timeSeriesFilter": { "aggregation": { "alignmentPeriod": "60s", "crossSeriesReducer": "REDUCE_MEAN", "groupByFields": [ "resource.label.\"zone\"" ], "perSeriesAligner": "ALIGN_MEAN" }, "filter": "metric.type=\"compute.googleapis.com/instance/cpu/utilization\" resource.type=\"gce_instance\"" } } } ], "thresholds": [], "yAxis": { "label": "", "scale": "LINEAR" } } }, "width": 24 } ] }}The chart on the dashboard looks similar to the following example:

The next section illustrates how to create a Log Analytics chart widget,how to display a threshold on a chart, and how to configure whether the chartuses the left Y-axis, right Y-axis, or both.
Dashboard with a Log Analytics chart
This dashboard shows a dashboard with a Log Analytics chart. Thesample JSON contains a SQL query.
{ "displayName": "Example", "dashboardFilters": [], "mosaicLayout": { "columns": 48, "tiles": [ { "width": 24, "height": 16, "widget": { "title": "Sample analytics chart", "xyChart": { "chartOptions": { "mode": "COLOR" }, "dataSets": [ { "breakdowns": [], "dimensions": [ { "column": "location", "columnType": "STRING", "maxBinCount": 5, "sortColumn": "location", "sortOrder": "SORT_ORDER_ASCENDING" } ], "measures": [ { "aggregationFunction": { "parameters": [], "type": "count" }, "column": "" } ], "plotType": "STACKED_BAR", "targetAxis": "Y1", "timeSeriesQuery": { "opsAnalyticsQuery": { "queryHandle": "", "sql": "SELECT\n CAST(JSON_VALUE(resource.labels.location) AS STRING) AS location,\n severity,\nFROM\n `VIEW`" } } } ], "thresholds": [], "yAxis": { "label": "", "scale": "LINEAR" } } } } ] }, "labels": {}}The chart on the dashboard looks similar to the following example:

Dashboard with anXyChart and a threshold
This dashboard shows a dashboard with a basicXyChart,a threshold, and the left Y-axis configured.
{ "dashboardFilters": [], "displayName": "Example line with threshold", "labels": {}, "mosaicLayout": { "columns": 48, "tiles": [ { "height": 16, "widget": { "title": "VM Instance - CPU utilization [MEAN]", "xyChart": { "chartOptions": { "mode": "COLOR" }, "dataSets": [ { "minAlignmentPeriod": "60s", "plotType": "LINE", "targetAxis": "Y1", "timeSeriesQuery": { "timeSeriesFilter": { "aggregation": { "alignmentPeriod": "60s", "crossSeriesReducer": "REDUCE_MEAN", "groupByFields": [ "resource.label.\"zone\"" ], "perSeriesAligner": "ALIGN_MEAN" }, "filter": "metric.type=\"compute.googleapis.com/instance/cpu/utilization\" resource.type=\"gce_instance\"" } } } ], "thresholds": [ { "label": "", "targetAxis": "Y1", "value": 0.2 } ], "yAxis": { "label": "", "scale": "LINEAR" } } }, "width": 24 } ] }}In the preceding example, the JSON specifies the use of the left Y-axis becauseit contains ay2Axis structure. In thetargetAxis field, use "Y1" for theright Y-axis and "Y2" for the left Y-axis. If you omit thetargetAxisfield, then the right Y-axis is used.
The chart on this dashboard looks similar to the following example:

You can construct charts that display multiple metric types and that usethe left and right axes. The previous example illustrated a chart witha single metric type, that is, there is one element in thedataSets array.When you chart two metric types, thedataSets array contains two elements,and each element specifies itstargetAxis.
Dashboard with anXyChart with aSTACKED_AREA PlotType
This dashboard shows anXyChart with aSTACKED_AREAPlotType.
{ "dashboardFilters": [], "displayName": "Example stacked area", "labels": {}, "mosaicLayout": { "columns": 48, "tiles": [ { "height": 16, "widget": { "title": "VM Instance - CPU utilization [MEAN]", "xyChart": { "chartOptions": { "mode": "COLOR" }, "dataSets": [ { "minAlignmentPeriod": "60s", "plotType": "STACKED_AREA", "targetAxis": "Y1", "timeSeriesQuery": { "timeSeriesFilter": { "aggregation": { "alignmentPeriod": "60s", "crossSeriesReducer": "REDUCE_MEAN", "groupByFields": [ "resource.label.\"zone\"" ], "perSeriesAligner": "ALIGN_MEAN" }, "filter": "metric.type=\"compute.googleapis.com/instance/cpu/utilization\" resource.type=\"gce_instance\"" } } } ], "thresholds": [], "yAxis": { "label": "", "scale": "LINEAR" } } }, "width": 24 } ] }}The chart on the dashboard looks similar to the following example:

Dashboard with an XyChart with aSTACKED_BAR PlotType
This dashboard shows anXyChart with aSTACKED_BARPlotType.
{ "dashboardFilters": [], "displayName": "Example stacked bar", "labels": {}, "mosaicLayout": { "columns": 48, "tiles": [ { "height": 16, "widget": { "title": "VM Instance - CPU utilization [MEAN]", "xyChart": { "chartOptions": { "mode": "COLOR" }, "dataSets": [ { "minAlignmentPeriod": "60s", "plotType": "STACKED_BAR", "targetAxis": "Y1", "timeSeriesQuery": { "timeSeriesFilter": { "aggregation": { "alignmentPeriod": "60s", "crossSeriesReducer": "REDUCE_MEAN", "groupByFields": [ "resource.label.\"zone\"" ], "perSeriesAligner": "ALIGN_MEAN" }, "filter": "metric.type=\"compute.googleapis.com/instance/cpu/utilization\" resource.type=\"gce_instance\"" } } } ], "thresholds": [], "yAxis": { "label": "", "scale": "LINEAR" } } }, "width": 24 } ] }}The dashboard looks similar to the following example:

Dashboard with a basicScorecard
This dashboard shows aScorecard without a gauge orsparkline. The example shows the Compute Engine CPU utilization and the scorecardhas two thresholds. One threshold uses the color yellow to indicate thatCPU utilization is over 70%, the other threshold uses red to indicate that theCPU utilization is over 90%.
Because the current CPU utilization is less than the specified thresholds, thecolor is green.
{ "dashboardFilters": [], "displayName": "Example-basic scorecard", "labels": {}, "mosaicLayout": { "columns": 48, "tiles": [ { "height": 8, "widget": { "scorecard": { "thresholds": [ { "color": "YELLOW", "direction": "ABOVE", "label": "", "value": 0.7 }, { "color": "RED", "direction": "ABOVE", "label": "", "value": 0.9 } ], "timeSeriesQuery": { "outputFullDuration": true, "timeSeriesFilter": { "aggregation": { "alignmentPeriod": "60s", "crossSeriesReducer": "REDUCE_MEAN", "groupByFields": [], "perSeriesAligner": "ALIGN_MEAN" }, "filter": "metric.type=\"compute.googleapis.com/instance/cpu/utilization\" resource.type=\"gce_instance\"" } } }, "title": "VM Instance - CPU utilization [MEAN]" }, "width": 16 } ] }}The dashboard looks similar to the following example:

Dashboard with aScorecard withGaugeView
This dashboard adds a gauge to the basic scorecard in the previous example.TheGaugeView object can specify an upper and a lower bound, to specify therange of values to show on the gauge. Since the scorecard shows values from0 to 1, those upper and lower bounds are reasonable. To add the gauge, add thefollowing to the JSON for the basic scorecard:
"gaugeView": { "lowerBound": 0, "upperBound": 1, },The following shows the complete modified dashboard specification:The current value is under the thresholds, which are colored appropriatelyon the gauge.
{ "dashboardFilters": [], "displayName": "Example-Gauge", "labels": {}, "mosaicLayout": { "columns": 48, "tiles": [ { "height": 8, "widget": { "scorecard": { "gaugeView": { "lowerBound": 0, "upperBound": 1 }, "thresholds": [ { "color": "YELLOW", "direction": "ABOVE", "label": "", "value": 0.7 }, { "color": "RED", "direction": "ABOVE", "label": "", "value": 0.9 } ], "timeSeriesQuery": { "outputFullDuration": true, "timeSeriesFilter": { "aggregation": { "alignmentPeriod": "60s", "crossSeriesReducer": "REDUCE_MEAN", "groupByFields": [], "perSeriesAligner": "ALIGN_MEAN" }, "filter": "metric.type=\"compute.googleapis.com/instance/cpu/utilization\" resource.type=\"gce_instance\"" } } }, "title": "VM Instance - CPU utilization [MEAN]" }, "width": 16 } ] }}The chart on this dashboard looks similar to the following example:

Dashboard with aScorecard withSparkChartView
This dashboard replaces the gauge in the previous example with a sparkline.TheSparkChartView object can create line charts or bar charts on a scorecard.This example uses a line. As long as the value doesn't violate a threshold, itis green. To add the sparkline, replace thegaugeView JSON object in theprevious chart with the following:
"sparkChartView": { "sparkChartType": "SPARK_LINE" },The scorecard looks similar to the following example:

Dashboard with aPieChart widget
Dashboards can display data by using a pie chart. Each time series contributesone slice to the pie. Pie charts don't show data over time; instead,they show only the most recent value.
All pie charts are specified by thePieChart widget.To configure the chart to display the sum of the most recent measurements,set thechartType field toDONUT. Otherwise, set this field to thevalue ofPIE.
"pieChart": { "chartType": "DONUT",},The following example configures a dashboard with two pie charts, with onepie chart configured as a donut:
{ "dashboardFilters": [], "displayName": "Example Pie Donut", "labels": {}, "mosaicLayout": { "columns": 48, "tiles": [ { "height": 16, "widget": { "pieChart": { "chartType": "DONUT", "dataSets": [ { "minAlignmentPeriod": "60s", "timeSeriesQuery": { "timeSeriesFilter": { "aggregation": { "alignmentPeriod": "60s", "perSeriesAligner": "ALIGN_RATE" }, "filter": "metric.type=\"compute.googleapis.com/instance/disk/read_bytes_count\" resource.type=\"gce_instance\"", "secondaryAggregation": { "alignmentPeriod": "60s", "perSeriesAligner": "ALIGN_MEAN" } } } } ] }, "title": "VM Instance - Disk read bytes [MEAN]" }, "width": 24 }, { "height": 16, "widget": { "pieChart": { "chartType": "PIE", "dataSets": [ { "minAlignmentPeriod": "60s", "timeSeriesQuery": { "timeSeriesFilter": { "aggregation": { "alignmentPeriod": "60s", "perSeriesAligner": "ALIGN_RATE" }, "filter": "metric.type=\"compute.googleapis.com/instance/disk/read_bytes_count\" resource.type=\"gce_instance\"", "secondaryAggregation": { "alignmentPeriod": "60s", "perSeriesAligner": "ALIGN_MEAN" } } } } ] }, "title": "VM Instance - Disk read bytes [MEAN]" }, "width": 24, "xPos": 24 }, ] }}As shown in the following screenshot, both widgets display data as a pie chart,with one widget displaying the sum of the most recent values:

Dashboard with aTreemap widget
To view the most recent data as a series of nested rectangles, where eachrectangle corresponds to a unique collection of label values, add a tree map.Assume that you've aggregated the data you are charting by thezone label.If you set the widget type to treemap, then each rectangle on thetreemap corresponds to one zone. The color saturation of a rectangle isproportional to the value it represents.
When exploring a treemap, use your pointer to activate the tooltip forthe rectangle.
Note: To use a treemap, you must aggregate your data by at least one label.The following JSON configures aTreemap widget whichaggregates the time series by zone and storage type:
{ "displayName": "Example Treemap", "dashboardFilters": [], "labels": {}, "mosaicLayout": { "columns": 48, "tiles": [ { "xPos": 24, "height": 16, "width": 24, "widget": { "title": "VM Instance - Write read bytes [SUM]", "id": "", "treemap": { "dataSets": [ { "breakdowns": [], "measures": [], "timeSeriesQuery": { "outputFullDuration": true, "timeSeriesFilter": { "aggregation": { "alignmentPeriod": "60s", "crossSeriesReducer": "REDUCE_SUM", "groupByFields": [ "resource.label.\"zone\"", "metric.label.\"storage_type\"" ], "perSeriesAligner": "ALIGN_RATE" }, "filter": "metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" resource.type=\"gce_instance\"" }, "unitOverride": "" } } ], "treemapHierarchy": [ "resource.label.\"zone\"", "metric.label.\"storage_type\"" ] } } } ] }}The following screenshot shows the treemap widget with the previousconfiguration:

In the screenshot, the tooltip is shown for one rectangle.
Dashboard with aTimeSeriesTable widget
Dashboards can display data in a tabular format, where there is onerow for each combination of unique label values. Tables don't show data overtime; instead, they show either the most recent value or an aggregated value.
All tables are specified by theTimeSeriesTable widget:
To configure the time series to display, use the
dataSetsfield. Eachobject in thedataSetsarray corresponds to a single metric type.If you query for multiple metric types, the Google Cloud consoleattempts to display the most recent value for each query in the sametable row. For more information, seeHow tables merge data from multiple metric types.- The
TimeSeriesQueryfield specifies the metric type. - If you want the table to display the aggregated value, where the datais aggregated over the time-range value set by your dashboard, set the
timeSeriesQuery.outputFullDurationfield totrue.
- The
To configure the maximum number of rows to display, set the
pickTimeSeriesFilterfield. For example, to display only the two timeseries with the largest average value over the previous 10 minutes,include the following:"pickTimeSeriesFilter": { "direction": "TOP", "numTimeSeries": 2, "rankingMethod": "METHOD_MEAN"},If you omit the
pickTimeSeriesFilterfield, then the table displaysa maximum of 300 rows.To configure how the table displays the data,use the
metricVisualizationfield:- To display only a value like "25%", either omit this field or set thevalue to
"NUMBER". When you use this configuration, theGoogle Cloud console displays the widget as aTable widget. - To display the value and a visual indicator of the value compared to therange of possible values, set the value of this field to
"BAR".When you use this configuration, theGoogle Cloud console displays the widget as aTop List widget.
- To display only a value like "25%", either omit this field or set thevalue to
To configure which columns are displayed and the properties of the column,use the
columnSettingsarray. If this field isn't specified, thenthe table displays one column for each label.The value of the
"column"field must be set to label key or tovalue,which refers to the latest value of the time series. You can set thedisplay name for a column, and you can configure the alignment of thedata within the table cell:- To customize the column header, set the
displayNamefield. - To color the cell that displays the most recent value based on how thevalue compares to a threshold, add a
thresholdsobject. - To change the text alignment, add an
alignmentfield.
The following example illustrates two columns:
"columnSettings": [ { "column": "device_name", "displayName": "Device", "visible": true }, { "alignment": "CENTER", "column": "value", "displayName": "Disk Write Bytes", "thresholds": [ { "color": "YELLOW", "direction": "ABOVE", "value": 4000 }, { "color": "RED", "direction": "ABOVE", "value": 5000 } ], "visible": true }],- To customize the column header, set the
The following JSON describes a dashboard with two tables. The first tabledisplays two metric types, the number of bytes read from instances and thenumber of bytes written to instances. An aggregated value is shown along witha reference bar. The second table shows the latest value of one metric type,and the value column has been configured to color code the cell based onhow the value compares to a threshold:
{ "displayName": "Example", "mosaicLayout": { "columns": 48, "tiles": [ { "width": 44, "height": 17, "widget": { "title": "VM Instance - Disk read bytes [RATE], Disk write bytes [RATE]", "timeSeriesTable": { "dataSets": [ { "timeSeriesQuery": { "timeSeriesFilter": { "filter": "metric.type=\"compute.googleapis.com/instance/disk/read_bytes_count\" resource.type=\"gce_instance\"", "aggregation": { "alignmentPeriod": "60s", "perSeriesAligner": "ALIGN_RATE", "groupByFields": [] }, "pickTimeSeriesFilter": { "rankingMethod": "METHOD_MEAN", "numTimeSeries": 30, "direction": "TOP" } }, "unitOverride": "", "outputFullDuration": true }, "tableTemplate": "", "minAlignmentPeriod": "60s" }, { "timeSeriesQuery": { "timeSeriesFilter": { "filter": "metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" resource.type=\"gce_instance\"", "aggregation": { "alignmentPeriod": "60s", "perSeriesAligner": "ALIGN_RATE", "groupByFields": [] }, "pickTimeSeriesFilter": { "rankingMethod": "METHOD_MEAN", "numTimeSeries": 30, "direction": "TOP" } }, "unitOverride": "", "outputFullDuration": true }, "tableTemplate": "", "minAlignmentPeriod": "60s" } ], "metricVisualization": "BAR", "columnSettings": [ { "column": "Name (from instance_id)", "visible": true }, { "column": "zone", "visible": true }, { "column": "device_name", "visible": true }, { "column": "storage_type", "visible": true }, { "column": "device_type", "visible": true }, { "column": "value", "visible": true, "displayName": "Read bytes" }, { "column": "value-1", "visible": true, "displayName": "Written bytes" } ], "opsAnalyticsSettings": { "maxRows": "0", "showFilterBar": false, "pageSize": "0" }, "displayColumnType": false }, "id": "" } }, { "yPos": 17, "width": 44, "height": 16, "widget": { "title": "VM Instance - Disk write bytes [RATE]", "timeSeriesTable": { "columnSettings": [ { "column": "device_name", "displayName": "Device", "visible": true }, { "alignment": "LEFT", "column": "instance_name", "displayName": "Instance name", "visible": true }, { "column": "storage_type", "displayName": "Storage type", "visible": true }, { "column": "device_type", "displayName": "Device Type", "visible": true }, { "alignment": "CENTER", "column": "value", "displayName": "Disk Write Bytes", "thresholds": [ { "color": "YELLOW", "direction": "ABOVE", "label": "", "value": 4000 }, { "color": "RED", "direction": "ABOVE", "label": "", "value": 5000 } ], "visible": true }, { "alignment": "LEFT", "column": "Name (from instance_id)", "displayName": "ID", "visible": true } ], "dataSets": [ { "minAlignmentPeriod": "60s", "timeSeriesQuery": { "timeSeriesFilter": { "aggregation": { "alignmentPeriod": "60s", "perSeriesAligner": "ALIGN_RATE" }, "filter": "metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" resource.type=\"gce_instance\"" } } } ], "displayColumnType": false, "metricVisualization": "NUMBER", "opsAnalyticsSettings": { "maxRows": "0", "pageSize": "0", "showFilterBar": false } } } } ] }, "dashboardFilters": [], "labels": {}}The following screenshot illustrates the previously-defined table:

Dashboard with aText widget
This example shows a dashboard with aText widget.
{ "dashboardFilters": [], "displayName": "DB2+TE", "labels": {}, "mosaicLayout": { "columns": 48, "tiles": [ ... { "height": 16, "widget": { "text": { "content": "# Support information\n\n\nContact information: my-support-team@example.com\nOnline help: [Playbooks](https://example.com)\n\n", "format": "MARKDOWN", "style": { "backgroundColor": "", "fontSize": "FS_LARGE", "horizontalAlignment": "H_LEFT", "padding": "P_EXTRA_SMALL", "textColor": "", "verticalAlignment": "V_TOP" } } }, "width": 24, "yPos": 14 } ] }}The text widget looks similar to the following example:

Dashboard with anAlertChart widget
This dashboard shows a dashboard with anAlertChartwidget:
{ "category": "CUSTOM", "displayName": "Alerting policy chart example", "mosaicLayout": { "columns": 12, "tiles": [ { "height": 4, "widget": { "alertChart": { "name": "projects/my-project/alertPolicies/14205854094151528373" } }, "width": 6, } ] }}Unlike other dashboard widgets, you don't specify a title or a metric filterfor these widgets. Instead, you specify the resource name for an alertingpolicy. The last entry in thename field is the alerting policy identifier.
The chart on the dashboard looks similar to the following example:

In this example, the alerting policy is monitoring the CPU usage of twodifferent virtual machines. The dashed line shows the condition threshold,which is set to 50%. The green chip with the labelNo incidentsindicates that there are no open incidents for the alerting policy. Ifyou place your pointer on the incidents chip, then a dialog opens thatlinks to the underlying alerting policy.
Dashboard with anErrorReportingPanel widget
This dashboard shows a dashboard with anErrorReportingPanelwidget:
{ "dashboardFilters": [], "displayName": "Error reporting widget", "labels": {}, "mosaicLayout": { "columns": 48, "tiles": [ { "height": 16, "widget": { "errorReportingPanel": { "projectNames": [ "projects/my-project" ], "services": [], "versions": [] }, "title": "Error Reporting Panel" }, "width": 24, } ] }}We recommend that you configure the height of an error-reporting panel to be atleast 16 units, and its width to be at least 24 units. In the previousexample, the widget has a height of 16 units and width of 24 units.
The error-reporting panel displays theerror groups from the selectedproject, and this panel can restrict the error groups to a specific resourcetype, service, or version of a service. The following example illustratesan error-reporting panel:

Dashboard with aFilterControl widget
If you create a variable, then Monitoring updates the toolbarof your custom dashboard to display a filter for the variable. The nameof the filter is a dollar sign$ followed by the name of the variable.For example,$my-variable. Each filter contains a menu that lets youchange the value of the variable.
Managing the value of a variable by using a toolbar filter might not beoptimal. For example, suppose you have a dashboard with many charts and thatyou have a variable that applies to only two charts.For this scenario, you might do the following:
- Add a
CollapsibleGroupwidgetto your dashboard and place those two charts in the group. Add a
FilterControlwidget to your dashboard.You configure this widget for the variable and you also add this widgetto the group.The group widget contains the
FilterControlwidget that lets you changethe value of the variable, and the widgets to which the variable applies.Additionally, the dashboard toolbar no longer displays a filter for thevariable.
The following dashboard contains aFilterControl widget:
{ "displayName": "Dashboard with filter control widget", "dashboardFilters": [ { "filterType": "RESOURCE_LABEL", "labelKey": "project_id", "stringValue": "my-project", "templateVariable": "proj", "valueType": "STRING" } ], "description": "", "labels": {}, "mosaicLayout": { "columns": 48, "tiles": [ { "yPos": 70, "height": 5, "width": 16, "widget": { "title": "Project control", "filterControl": { "templateVariable": "proj" } } } ] }}The previous example defines one variable,proj, and adds oneFilterControl widget. With this configuration, the menu for variableis moved from the dashboard toolbar into the widget with the widgettitledProject control. That widget, contains a menu that you can useto select the project.
Dashboard with anIncidentList widget
This dashboard shows a dashboard with anIncidentListwidget:
{ "category": "CUSTOM", "dashboardFilters": [], "displayName": "Incident widget", "labels": {}, "mosaicLayout": { "columns": 12, "tiles": [ { "height": 5, "widget": { "incidentList": { "monitoredResources": [], "policyNames": [] }, "title": "Incidents" }, "width": 8, "xPos": 0, "yPos": 0 } ] }}The previous example sets thetitle field toIncidents, and it configuresthe widget to display all incidents for resources of typegce_instance.When you configure this widget, you can select multiple alerting policies ormultiple resource types.
The incident widget on the dashboard looks similar to the following example:

Dashboard with aLogsPanel widget
This dashboard shows a dashboard with aLogsPanelwidget:
{ "category": "CUSTOM", "displayName": "Logs Panel", "mosaicLayout": { "columns": 12, "tiles": [ { "height": 4, "widget": { "logsPanel": { "filter": "", "resourceNames": [ "projects/012012012012" ] }, "title": "Logs Panel" }, "width": 6, "xPos": 0, "yPos": 0 } ] }}We recommend that you configure the height of a logs panel to be atleast 3 units, and its width to be at least 4 units. In the previous example,the widget has a height of 4 units and width of 6 units.
The logs panel displays the logs from the Google Cloud projects listedin theresourceNames field. The previous example specifies only one project;however, you can include multiple projects in this list.
The logs panel looks similar to the following example:

For troubleshooting information, seeAPI call to create dashboard with a logs panel fails.
Dashboard with aCollapsibleGroup widget
This dashboard shows a dashboard with aCollapsibleGroupwidget:
{ "category": "CUSTOM", "displayName": "Group testing", "mosaicLayout": { "columns": 12, "tiles": [ { "height": 4, "widget": { "collapsibleGroup": { "collapsed": false }, "title": "My group" }, "width": 12, "xPos": 0, "yPos": 0 }, { "height": 4, "widget": { "title": "VM Instance - CPU utilization [MEAN]", "xyChart": { "chartOptions": { "mode": "COLOR" }, "dataSets": [ { "minAlignmentPeriod": "60s", "plotType": "LINE", "targetAxis": "Y1", "timeSeriesQuery": { "apiSource": "DEFAULT_CLOUD", "timeSeriesFilter": { "aggregation": { "alignmentPeriod": "60s", "crossSeriesReducer": "REDUCE_NONE", "perSeriesAligner": "ALIGN_MEAN" }, "filter": "metric.type=\"compute.googleapis.com/instance/cpu/utilization\" resource.type=\"gce_instance\"", "secondaryAggregation": { "alignmentPeriod": "60s", "crossSeriesReducer": "REDUCE_NONE", "perSeriesAligner": "ALIGN_NONE" } } } } ], "thresholds": [], "timeshiftDuration": "0s", "yAxis": { "label": "y1Axis", "scale": "LINEAR" } } }, "width": 6, "xPos": 0, "yPos": 0 } ] }}In the previous example, the collapsible group widget contains a single chartthat displays the CPU utilization of a VM instance. Collapsible group widgetsspan an entire row of a table. A widget is included in a group when thegroup's (x,y) position and height specifications include the (x,y)position of the widget. In the previous example, the group is at the positionof (0,0) and its height is 4. ThexyChart is at the position of (0,0), soit is included in the group. However, if the position of that chart ischanged to be (0,5), then the chart is excluded from the group. Lastly, whena widget's (x,y) position result in the widget being included in the group, theheight of the collapsible group widget might be expanded.
To include a group widget on a dashboard, the dashboard must have aMosaicLayout.
The collapsible group widget looks similar to the following example:

Dashboard with aSingleViewGroup widget
ASingleViewGroup widget displays one member of agroup at a time. You specify the charts and other widgets that are membersin the group. Also, you control which widget in the group is displayedby using a menu on theSingleViewGroup widget.
TheSingleViewGroup widget supports two display styles,DROPDOWN andTAB. The difference between these two styles is how youselect which member of the group to show. Widgets with aDROPDOWN styleprovide a menu. Widgets with aTAB style provide tabs on thewidget's toolbar:
{ "dashboardFilters": [], "displayName": "Example", "labels": {}, "mosaicLayout": { "columns": 48, "tiles": [ { "height": 16, "widget": { "singleViewGroup": { "displayType": "DROPDOWN" }, "title": "Untitled group" }, "width": 24, "yPos": 16 }, { "height": 16, "widget": { "title": "VM Instance - Disk read bytes [RATE]", "xyChart": { "chartOptions": { "mode": "COLOR" }, "dataSets": [ { "minAlignmentPeriod": "60s", "plotType": "LINE", "targetAxis": "Y1", "timeSeriesQuery": { "timeSeriesFilter": { "aggregation": { "alignmentPeriod": "60s", "perSeriesAligner": "ALIGN_RATE" }, "filter": "metric.type=\"compute.googleapis.com/instance/disk/read_bytes_count\" resource.type=\"gce_instance\"" } } } ], "thresholds": [], "yAxis": { "label": "", "scale": "LINEAR" } } }, "width": 24, "yPos": 16 }, { "height": 16, "widget": { "title": "VM Instance - Disk write bytes [RATE]", "xyChart": { "chartOptions": { "mode": "COLOR" }, "dataSets": [ { "minAlignmentPeriod": "60s", "plotType": "LINE", "targetAxis": "Y1", "timeSeriesQuery": { "timeSeriesFilter": { "aggregation": { "alignmentPeriod": "60s", "perSeriesAligner": "ALIGN_RATE" }, "filter": "metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" resource.type=\"gce_instance\"" } } } ], "thresholds": [], "yAxis": { "label": "", "scale": "LINEAR" } } }, "width": 24, "yPos": 16 } ] }}As shown in the previous example, thetiles array contains oneSingleViewGroup object; however, that object doesn't specify which objectsit contains. Instead, membership in theSingleViewGroup object is determinedby the values of thewidth andyPos fields. Objects whose values for thewidth andyPos fields match thevalues of theSingleViewGroup object are contained by theSingleViewGroup object. In the previous example, theSingleViewGroup objectcontains two charts.
Dashboard with aSectionHeader widget
ASectionHeader widget creates a horizontal divider inyour dashboard, and it creates an entry in the dashboard's table ofcontents. You can customize the entry in the table of contents, and includeadditional information in the widget. You can also configure the widgetto add a divider to the table of contents after the section header entry.
This dashboard shows a dashboard with a single chart andaSectionHeader widget:
{ "dashboardFilters": [], "displayName": "Example", "labels": {}, "mosaicLayout": { "columns": 48, "tiles": [ { "height": 16, "widget": { "title": "VM Instance - Disk write bytes [RATE]", "xyChart": { "chartOptions": { "mode": "COLOR" }, "dataSets": [ { "minAlignmentPeriod": "60s", "plotType": "LINE", "targetAxis": "Y1", "timeSeriesQuery": { "timeSeriesFilter": { "aggregation": { "alignmentPeriod": "60s", "perSeriesAligner": "ALIGN_RATE" }, "filter": "metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" resource.type=\"gce_instance\"" } } } ], "thresholds": [], "yAxis": { "label": "", "scale": "LINEAR" } } }, "width": 24, "yPos": 4 }, { "height": 4, "widget": { "sectionHeader": { "dividerBelow": true, "subtitle": "Instance metrics" }, "title": "Metrics" }, "width": 48 } ] }}In theSectionHeader object, the value of thetitle field is displayedboth in the widget and in the table of contents. The value of thesubtitle field is displayed only by the widget. When the value ofdividerBelow istrue, then a divider is added to the table of contents.
Dashboard with an SLO widget
This dashboard shows a dashboard with a SLO widget:
{ "dashboardFilters": [], "displayName": "Example", "labels": {}, "mosaicLayout": { "columns": 48, "tiles": [ { "height": 16, "widget": { "title": "SLO Error Budget: 99.5% - Distribution Cut - Calendar month", "xyChart": { "chartOptions": { "mode": "COLOR" }, "dataSets": [ { "breakdowns": [], "dimensions": [], "legendTemplate": "Remaining error requests before SLO is burned", "measures": [], "plotType": "LINE", "targetAxis": "Y1", "timeSeriesQuery": { "timeSeriesFilter": { "aggregation": { "perSeriesAligner": "ALIGN_NEXT_OLDER" }, "filter": "select_slo_budget(\"projects/Project_Number/services/SERVICE_ID/serviceLevelObjectives/SLO_ID\")", }, "unitOverride": "1" } } ], "thresholds": [] } }, "width": 24 } ] }}As the previous JSON shows, SLO charts are represented asXyChart objects. These objects specify allaggregation fields, thresholds, and thevalue of thefilter field is a time-series selector. For more informationabout these selectors, seeRetrieving SLO data.
The SLO widget looks similar to the following example:

Dashboard with a blank widget
This example shows a dashboard with an empty, placeholder widget.The value of thedisplayName field appears in the widget.
{ "displayName": "Demo Dashboard", "gridLayout": { "widgets": [ { "blank": {} } ] }}The dashboard looks similar to the following example:

Dashboard with widget-visibility configured
This dashboard contains a text widget and a variable. The value of the variabledetermines whether the text widget is displayed or hidden:
The variable named
showhas a default value ofa. Thevalues of the variable are defined asa,b, andc. Because thevalueTypefield isSTRING_ARRAY, the variable can also be setto values likea or b.In the text widget, the entry labeled
visibilityConditiondefines thevisibility of the widget. When the value of the variableshowincludesb,then the text widget is displayed. Otherwise, the text widget isn't displayed.
{ "displayName": "Conditional Widget Example", "mosaicLayout": { "columns": 48, "tiles": [ { "yPos": 16, "width": 24, "height": 16, "widget": { "title": "A text widget", "text": { "content": "Example showing how to use a custom variable to control visibility.", "format": "MARKDOWN", "style": { "backgroundColor": "#FFFFFF", "fontSize": "FS_LARGE", "horizontalAlignment": "H_LEFT", "padding": "P_EXTRA_SMALL", "pointerLocation": "POINTER_LOCATION_UNSPECIFIED", "textColor": "#212121", "verticalAlignment": "V_TOP" } }, "visibilityCondition": { "templateVariableCondition": { "templateVariable": "show", "templateVariableValue": "b", "comparator": "REGEX_FULL_MATCH" } } } } ] }, "dashboardFilters": [ { "labelKey": "", "templateVariable": "show", "stringArrayValue": { "values": [ "a" ] }, "filterType": "VALUE_ONLY", "valueType": "STRING_ARRAY", "stringArray": { "values": [ "a", "b", "c" ] } } ], "labels": {}}For restrictions related to configuring the visibility of a widget, seeSet the visibility of a widget.
Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2026-02-19 UTC.