CloudWatch Deep Dive Basics
The Core section's CloudWatch page publishes one metric and creates one alarm. This page is the on-ramp into everything this deeper section covers: batching metrics, adding dimensions, writing EMF logs, querying Logs Insights, composing alarms, and shipping a dashboard as code.
Each example stays small. The dedicated pages later in this section go deeper on any one of these.
Python: pip install boto3 (boto3 1.43.x, Python 3.10+). TypeScript: npm install @aws-sdk/client-cloudwatch @aws-sdk/client-cloudwatch-logs (Node.js 18+).
Credentials configured via aws configure, environment variables, or an IAM role.
A default region; these examples assume us-east-1.
A CloudWatch Logs log group already created for the log-based examples (see the Logs Insights page for CreateLogGroup).
PutMetricData accepts up to 1,000 MetricDatum entries per call. Publish several related metrics in one request instead of one request each.
Python (boto3) TypeScript (AWS SDK v3)
One PutMetricData call can carry many different metric names at once.
Batching cuts request count, which matters for both latency and API-call cost.
Each MetricDatum still needs its own Unit - mixing units across a batch is fine.
The batch limit is 1,000 items and roughly 1MB of payload per call.
Related: Custom Metrics & Embedded Metric Format (EMF) .
Dimensions let you break one metric name down by service, environment, or any other axis you care about.
Python (boto3) TypeScript (AWS SDK v3)
Each unique combination of dimension values is billed as its own metric.
Keep dimension cardinality bounded - per-customer or per-request-id dimensions can explode costs.
Alarms and dashboard widgets must reference the exact same dimensions to find this data.
High-cardinality slicing is better served by EMF, covered next in this section.
Related: CloudWatch's Metrics/Logs/Alarms/Events Model .
Embedded Metric Format lets a single structured log line become a metric, with no separate metrics API call.
Python (boto3) TypeScript (AWS SDK v3)
The _aws.CloudWatchMetrics envelope is what tells CloudWatch to extract a metric from this log line.
No PutMetricData call happens - this is a normal log write that CloudWatch parses.
In Lambda, console.log/print output already goes to CloudWatch Logs, so EMF needs no extra plumbing.
Outside Lambda, ship the JSON line via PutLogEvents like any other log.
Related: Custom Metrics & Embedded Metric Format (EMF) .
Start an async query against a log group, then poll for results.
Python (boto3) TypeScript (AWS SDK v3)
StartQuery returns immediately with a queryId - it does not block until results are ready.
GetQueryResults must be polled until status is Complete; a fixed sleep is a placeholder, not production polling.
The query string is its own language (fields, filter, stats, sort) - it is not a CodeGroup target, just a string argument.
Results are capped by limit and by a maximum scanned data volume per query.
Related: CloudWatch Logs Insights Queries via SDK .
Combine two existing alarms with boolean logic to reduce noise from either one firing alone.
Python (boto3) TypeScript (AWS SDK v3)
AlarmRule references other alarms by name inside a boolean expression.
A composite alarm only fires when its rule is true, cutting single-alarm alert noise.
The referenced alarms (checkout-failures, checkout-latency-high) must already exist.
Composite alarms have their own AlarmActions, separate from their child alarms' actions.
Related: Composite Alarms & Anomaly Detection .
Alarm against a machine-learned baseline instead of a fixed number.
Python (boto3) TypeScript (AWS SDK v3)
PutAnomalyDetector trains a model for a metric+statistic pair; it does not create an alarm by itself.
The alarm's Metrics array feeds the raw metric plus an ANOMALY_DETECTION_BAND expression into the comparison.
ThresholdMetricId points the alarm at the anomaly band instead of a static Threshold.
The band needs time to learn a baseline - expect INSUFFICIENT_DATA for the first couple of weeks.
Related: Composite Alarms & Anomaly Detection .
Create or update a dashboard from a JSON widget-layout document.
Python (boto3) TypeScript (AWS SDK v3)
DashboardBody is a JSON string, not a typed structure - both SDKs just serialize a plain object.
PutDashboard is idempotent by name: calling it again with the same name replaces the layout.
Widget coordinates (x, y, width, height) are in a 24-column grid.
Version-controlling this JSON is what "dashboards as code" means in practice.
Related: Dashboards as Code via SDK .
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).