AWS CloudWatch metrics in Osuite
Overview
Section titled “Overview”Osuite ingests Amazon CloudWatch metrics through the OpenTelemetry Collector. The awscloudwatch receiver polls the CloudWatch GetMetricData API on an interval, converts each series to OTLP, and forwards it through the otlp/osuite exporter, where it correlates with the rest of your telemetry.
The receiver runs anywhere the Collector runs — an EC2 instance, a container, or a Kubernetes pod — and pulls metrics for the AWS account and region it is configured against. One Collector can cover many namespaces.
There are two collector-based paths for CloudWatch metrics:
- Pull with the
awscloudwatchreceiver (documented below) — the Collector callsGetMetricDataon a schedule. Simplest to run: no inbound endpoint, no extra AWS resources. CloudWatch charges per metric API request. - Push with CloudWatch Metric Streams — a metric stream delivers metrics through Amazon Data Firehose to the Collector’s
awsfirehosereceiver(encoding: cwmetrics). Lower latency and no polling cost, but the Collector must expose a public HTTPS endpoint on port 443 for Firehose to reach, and you provision a stream plus a Firehose delivery stream. Prefer this at high metric volume where API-request cost or freshness matters.
This page covers the pull path.
Prerequisites
Section titled “Prerequisites”- An OpenTelemetry Collector from the Contrib distribution (
otelcol-contrib) that includes theawscloudwatchreceiver. - Your Osuite ingest endpoint and token.
- AWS credentials available to the Collector through the standard AWS SDK chain: environment variables (
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY), a shared credentials file, or an instance/role identity (IMDS on EC2, IRSA on EKS). - An IAM policy granting the Collector read access to CloudWatch metrics:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "cloudwatch:GetMetricData", "cloudwatch:ListMetrics" ], "Resource": "*" } ]}GetMetricData reads the data points; ListMetrics is required only if you use auto-discovery instead of explicit queries.
Collector config
Section titled “Collector config”This configuration polls two explicit metrics and forwards them to Osuite. Set region to the AWS region whose metrics you want.
receivers: awscloudwatch: region: us-east-1 metrics: collection_interval: 5m period: 300s delay: 10m queries: - namespace: AWS/EC2 metric_name: CPUUtilization stats: - Average - namespace: AWS/RDS metric_name: FreeStorageSpace stats: - Average
processors: batch:
exporters: otlp/osuite: endpoint: ingest.<region>.osuite.io:443 tls: insecure: false headers: x-osuite-ingest-token: <your-ingest-token>
service: pipelines: metrics: receivers: [awscloudwatch] processors: [batch] exporters: [otlp/osuite]To collect metrics for a single resource, add its CloudWatch dimensions to a query:
queries: - namespace: AWS/EC2 metric_name: CPUUtilization dimensions: InstanceId: i-1234567890abcdef0 stats: - AverageTo collect a whole namespace without listing every metric, use auto-discovery instead of queries (the two are mutually exclusive):
metrics: collection_interval: 5m period: 300s delay: 10m discovery: filters: namespace: AWS/EC2 limit: 200Validate
Section titled “Validate”Start the Collector and confirm it logs no GetMetricData authorization or throttling errors. Then check Osuite.
Verify in Osuite
Section titled “Verify in Osuite”What you should see
CloudWatch metrics appear in Dashboards → Explore metrics within a few minutes, named amazonaws.com/AWS/EC2/CPUUtilization and similar. Filter by the resource attribute cloud.provider = aws to isolate them.
Data collected
Section titled “Data collected”Metric names follow the CloudWatch Metric Streams OpenTelemetry 1.0.0 format: amazonaws.com/{Namespace}/{MetricName}, with CloudWatch casing preserved. Each data point carries the Namespace, MetricName, and Dimensions attributes; resource attributes include cloud.provider = aws and cloud.region.
Whatever you query is collected. Common namespaces:
| Namespace | Covers |
|---|---|
AWS/EC2 | Instance CPU, network, disk, status checks |
AWS/RDS | Database CPU, connections, free storage, IOPS |
AWS/Lambda | Invocations, errors, duration, throttles, concurrency |
AWS/ApplicationELB | Request count, target response time, HTTP 5xx |
AWS/S3 | Bucket size, object count, request metrics |
AWS/DynamoDB | Consumed capacity, throttled requests, latency |
AWS/SQS | Queue depth, message age, sent/received counts |
By default (no stats), the receiver fetches Sum, SampleCount, Minimum, and Maximum and emits a Summary data point. Listing explicit stats emits a Gauge per statistic, tagged with a stat attribute, and costs fewer API sub-queries.
Troubleshooting
Section titled “Troubleshooting”Empty or partial data usually means the query window is wrong or a metric has no data points for the requested statistic. Increase delay if points are missing, confirm the namespace/metric_name/dimensions match exactly what CloudWatch reports, and watch for ThrottlingException in the Collector logs — widen collection_interval or split queries across Collectors if you hit CloudWatch API limits.
No data in Osuite after a few minutes? Work through these checks.
- Endpoint — confirm the exporter targets exactly
ingest.<region>.osuite.io:443for your region, over TLS. - Token — confirm the ingest header carries a valid
<your-ingest-token>and has not been rotated. - Pipeline — confirm the signal you expect (traces, logs, or metrics) is wired into an active pipeline with the
otlp/osuiteexporter attached. - Export errors — check the application or Collector logs for OTLP export failures (auth, DNS, TLS, connection refused).
- Network — confirm the host has outbound access to the ingest endpoint on port
443. - Timing — allow up to a minute for the first data to appear before assuming a failure.
Still stuck? Ask the Investigation Agent or contact support.
Next steps
Section titled “Next steps”- Dashboards — build views over your CloudWatch metrics.
- Alerts — alert on CloudWatch thresholds with PromQL.