# CloudWatch Dashboards Widget types, cross-account/region patterns, dynamic labels, and recommended defaults. ## Contents - [Widget types](#widget-types) - [Cross-account and cross-region](#cross-account-and-cross-region) - [Dynamic labels](#dynamic-labels) - [Dashboard variables](#dashboard-variables) - [Sharing constraints](#sharing-constraints) - [Best-practice defaults](#best-practice-defaults) - [CDK patterns](#cdk-patterns) --- ## Widget types | Widget | Use case | |--------|----------| | **Line** | Time series trends (latency, request count) | | **Stacked area** | Composition over time (error types breakdown) | | **Number** | Single KPI value (current error rate) | | **Bar** | Comparisons across categories | | **Table** | Tabular metric data display | | **Pie** | Proportional breakdown | | **Gauge** | Current value against a range | | **Explorer** | Dynamic resource group metrics (auto-discovers new resources) | | **Logs table** | Log Insights query results inline | | **Alarm status** | Alarm state visualization | | **Markdown** | Free-form text, links, section headers | --- ## Cross-account and cross-region ### Prerequisites - CloudWatch Observability Access Manager (OAM) configured - Monitoring account + source account links established - IAM roles for cross-account access ### Dashboard body JSON Each widget supports `accountId` and `region` parameters: ```json { "type": "metric", "properties": { "metrics": [["AWS/Lambda", "Errors", "FunctionName", "my-fn"]], "region": "us-west-2", "accountId": "123456789012" } } ``` ### Limitations - Search expressions operate within the widget's configured region (set `region` per widget for cross-region search) - Cross-account composite alarms are not supported. However, with OAM, metric alarms in a monitoring account can watch metrics from source accounts. - Cross-account alarms do NOT support ANOMALY_DETECTION_BAND, INSIGHT_RULE, or SERVICE_QUOTA functions --- ## Dynamic labels Use dynamic values in metric widget labels (common tokens shown; AWS supports 28+ tokens including time-based variants like `${MAX_TIME}`, `${LAST_TIME_RELATIVE}`, and property tokens like `${PROP('MetricName')}`, `${PROP('Region')}`): | Token | Value | |-------|-------| | `${MAX}` | Maximum value in visible range | | `${MIN}` | Minimum value | | `${AVG}` | Average value | | `${SUM}` | Sum | | `${LAST}` | Most recent value | | `${FIRST}` | First value | | `${LABEL}` | Default metric label | | `${PROP('Dim.Name')}` | Dimension value | | `${DATAPOINT_COUNT}` | Number of data points | Example: `"label": "${PROP('FunctionName')} p99=${MAX}ms"` Max 6 dynamic values per label. `${LABEL}` can only be used once per label. --- ## Dashboard variables Variables add dropdown/radio/text inputs that dynamically filter all widgets on a dashboard. Up to 25 variables per dashboard. Two types: - **Property variables**: Populate from CloudWatch dimension values (e.g., all `FunctionName` values in `AWS/Lambda`) - **Pattern variables**: Free-text input matched against metric patterns Variables are a top-level `variables` array in the dashboard body JSON, peer to `widgets`. They eliminate the need for per-function or per-instance dashboards. Shared dashboard viewers cannot change variable values — the dashboard renders with the default value only. --- ## Sharing constraints - Shared users **cannot see** composite alarm widgets, Logs Insights widgets, or custom widgets unless you add the corresponding permissions (`DescribeAlarms`, CloudWatch Logs query permissions, Lambda invoke) to the sharing IAM policy - `cloudwatch:GetMetricData` and `ec2:DescribeTags` **cannot be scoped** — shared users can query all metrics and EC2 tags in the account - Cognito resources are created in **us-east-1** regardless of dashboard region --- ## Best-practice defaults | Setting | Default | Best practice | |---------|----------|------------| | `start` | `-PT3H` | **`-PT8H`** (covers a shift) | | `periodOverride` | AUTO | **`INHERIT`** (let widgets control) | | Layout width | varies | **24** for full-width, **12** for side-by-side | | Alarm widgets | none | **Always include** alarm status row at top | ### Dashboard structure pattern 1. **Row 1**: Markdown header + alarm status widgets (24-wide) 2. **Row 2**: Key business metrics (Number widgets, 6-wide each) 3. **Row 3**: Request/error rate graphs (Line widgets, 12-wide) 4. **Row 4**: Latency percentiles (Line widget, 24-wide) 5. **Row 5**: Log Insights query results (Logs table, 24-wide) ### Sharing - Share publicly or with specific email addresses via Amazon Cognito - Shared dashboards accessible via URL without AWS console login - Check the [CloudWatch pricing page](https://aws.amazon.com/cloudwatch/pricing/) for current dashboard costs ### API limits - PutDashboard, GetDashboard, ListDashboards, DeleteDashboards: all 10 TPS (adjustable) --- ## CDK patterns ### Dashboard with alarm and graph widgets ```typescript import { Dashboard, AlarmWidget, GraphWidget, TextWidget, PeriodOverride } from 'aws-cdk-lib/aws-cloudwatch'; const dashboard = new Dashboard(this, 'ServiceDashboard', { dashboardName: `${serviceName}-${stage}`, start: '-PT8H', periodOverride: PeriodOverride.INHERIT, }); dashboard.addWidgets( new TextWidget({ width: 24, height: 1, markdown: '# Service Health' }), new AlarmWidget({ width: 12, height: 6, title: 'Error Rate', alarm: errorRateAlarm }), new AlarmWidget({ width: 12, height: 6, title: 'Latency P99', alarm: latencyAlarm }), new GraphWidget({ width: 24, height: 6, title: 'Invocations & Errors', left: [fn.metricInvocations({ period: Duration.minutes(1) })], right: [fn.metricErrors({ period: Duration.minutes(1) })], }), ); ``` ### Automatic dashboards Pre-built per-service dashboards are available by default (EC2, Lambda, S3, etc.). No setup required. Use these as starting points, then customize.