Skip to main content

Amazon CloudWatch

Amazon CloudWatch

Plugin: go.d.plugin Module: cloudwatch

Maintained by Netdata

Overview

Monitor AWS infrastructure through Amazon CloudWatch. The collector discovers your AWS resources and turns their CloudWatch metrics into Netdata charts, one chart instance per resource, for a curated set of AWS services and with minimal configuration.

Out of the box it covers:

AreaServices
Compute and containersAmazon EC2, AWS Lambda, Amazon ECS, Amazon EKS (Kubernetes control plane), AWS Auto Scaling
Databases and analyticsAmazon RDS, Amazon DynamoDB, Amazon ElastiCache, Amazon DocumentDB, Amazon Redshift, Amazon OpenSearch Service
StorageAmazon S3, Amazon EBS, Amazon EFS
Networking and content deliveryClassic (ELB), Application (ALB), and Network (NLB) load balancers, NAT Gateway, AWS PrivateLink endpoints and endpoint services, Amazon CloudFront, AWS Site-to-Site VPN
Messaging, streaming, and eventsAmazon SQS, Amazon SNS, Amazon Kinesis Data Streams, Amazon Data Firehose, Amazon MSK, Amazon EventBridge
Application services and AIAmazon API Gateway, AWS Step Functions, Amazon Bedrock
CostAWS Billing estimated month-to-date charges (opt-in)
  • Every resource becomes a chart instance labeled with its AWS account, region, and identifying dimensions (for example the EC2 instance_id).
  • Several AWS accounts can be monitored from one job by assuming roles.
  • Resources can be selected and labeled by their AWS tags.
  • Four collector-activity charts show the AWS API work the job performs, so its cost stays visible.

Coverage is defined by profiles: one YAML file per service and level of detail, 34 enabled by default and 13 opt-in. A service can be added or a chart changed without a code change; see the AWS CloudWatch profile format.

This collector reads runtime metrics. The AWS EC2 Compute instances integration (EC2 inventory and capacity) and the AWS Quota integration (AWS Service Quotas) use different AWS data sources and complement it.

The collector runs on the Netdata Agent and reads CloudWatch through the AWS API. It installs nothing in AWS and writes nothing there.

  • Authentication: each named credential source uses the AWS SDK default chain (environment variables, shared config and credentials files, instance profile, EKS IRSA) or static access keys, optionally assuming one IAM role per target. The AWS account behind a target is resolved once with sts:GetCallerIdentity.
  • Discovery: every discovery.refresh_every seconds (default 300) the collector lists the metrics of each selected service with cloudwatch:ListMetrics, once per target, region, and CloudWatch namespace, and matches them against the profile's dimensions to find the resources. Resource tag filters and labels are resolved with tag:GetResources (Resource Groups Tagging API).
  • Collection: every update_every seconds (default 60) it reads the newest complete datapoint of every selected metric and statistic with cloudwatch:GetMetricData, batched, and only for series whose CloudWatch period has moved on since the last read. Between reads the last value is repeated at no AWS cost.

Terms used on this page and in the options:

TermMeaning
ProfileA YAML file that maps one CloudWatch namespace and one dimension set to charts. Stock profiles ship with Netdata; user profiles extend or override them.
GrainThe exact dimension set a profile matches, such as one PrivateLink endpoint versus one endpoint per subnet.
TargetA named AWS identity to monitor: a credential source, used directly or through one assumed role.
RuleAn ordered configuration entry selecting targets, regions, profiles, and optionally exact metrics. The first rule that selects a series owns it.
SeriesOne metric and statistic for one resource: the unit the collector's limits count.

This collector is supported on all platforms.

This collector supports collecting metrics from multiple instances of this integration, including remote instances.

PermissionNeeded when
cloudwatch:GetMetricDataAlways, for every target.
cloudwatch:ListMetricsAny selected profile has an identifying dimension and therefore needs discovery. An all-constant profile such as billing_total is queried directly and does not need it.
sts:AssumeRoleA target sets assume_role; grant it on the credential source's identity for that role ARN.
tag:GetResourcesResource tag filters (rule_defaults.filters.resource_tags, rules[].filters.resource_tags) or resource tag labels (labels.resource_tags) are configured.

The collector also calls sts:GetCallerIdentity for account attribution, but AWS does not require an explicit permission grant for that operation. The collector only reads; it never writes to CloudWatch or changes a resource.

Default Behavior

Auto-Detection

No job runs until you write one: a job needs at least one credential source, one target, and one rule. There is no service discovery for this collector.

With a minimal rule (targets and regions only) the collector collects every default-enabled profile, 34 of them minus any your regions do not support (CloudFront exists only in us-east-1), with each profile's default metrics and statistics, and discovers the resources itself every discovery.refresh_every seconds (default 300). A chart appears once a resource reports data. Opt-in profiles and opt-in metrics are collected only when a rule names them.

Limits

  • The collection interval is at least 60 seconds. The CloudWatch period of a series (1 minute to 24 hours) decides how often it has new data; a shorter update_every does not make AWS publish more often.
  • limits.max_instances (default 1000): more distinct resources than this, after tag filtering, rejects the query plan instead of collecting a subset; the log names the bound. Raise it deliberately or narrow the rules.
  • limits.max_discovery_groups (default 64, at most 100): more unique target, region, and namespace combinations than this stops the job at start; split the collection across jobs.
  • The whole plan, evaluated as if every series were due at once, is refused above 20,000 series, 600,000 datapoints, or 40 GetMetricData requests, and a rule set is refused above 16,384 candidate or 4,096 compiled target, profile, and region combinations. Only very broad rules reach these bounds.
  • A job holds at most 64 credential sources, 64 targets, and 256 rules; each rule list (targets, regions, profiles, metrics) holds at most 256 entries; a tag filter holds at most 50 keys with 20 values each.
  • Query timing per series: period from 1 minute to 24 hours in whole minutes; lookback at least one period and at most 1,440 periods; publication_delay + lookback + period at most 14 days.
  • A discovery refresh that exceeds its internal bounds or the shared timeout is discarded as a whole: the previously discovered resources stay, and discovery retries after discovery.refresh_every. Recurring warnings of this kind are logged at most once per hour.

Performance Impact

The impact on the Agent host is negligible. The cost is on your AWS bill.

AWS bills every CloudWatch API request this collector makes

GetMetricData is billed per metric requested, about $0.01 per 1,000 in most regions; check CloudWatch pricing for yours. Up to five statistics of one metric in one request count as one metric requested, and the collector keeps them together as long as they share the same query timing. ListMetrics discovery is within the AWS free tier for most accounts and inexpensive beyond it. Broad rules across many regions and services cost real money; read this section before enabling a wide selection.

What drives the cost

DriverEffect
ResourcesEvery discovered resource adds its profile's metrics. Tag filters and limits.max_instances bound it.
Metrics and statisticsEach selected metric and statistic of each resource is one series. Most default profiles select one statistic per metric, a few select two or three; up to five statistics of one metric stay one metric request when they share the same query timing, and giving one statistic its own period or lookback splits the request and bills separately.
Request frequencyA series is read once per CloudWatch period, and at most once per update_every. A 1-minute period read every minute costs five times a 5-minute period.
LookbackA longer window requests more datapoints per read and can turn off the 3-hour recently-active discovery filter, which makes ListMetrics scans larger.
RetriesA read that fails transiently is retried after update_every, then with a doubling delay up to one period. Retries are billed.

Estimating before you run

metric requests per day = resources × metrics requested per resource × 86,400 / max(period, update_every) in seconds

Sum it over the groups of series that share a period. For example, one series at a 10-minute period read on every collection is 86,400 / 600 = 144 metric requests per day; 200 such series are 28,800 per day, about $0.29 per day at $0.01 per 1,000.

Watching the cost while running

Four collector-activity charts count the work as it happens: CloudWatch SDK Invocations (ListMetrics and GetMetricData calls, including failed calls and every result page), GetMetricData Calculated Metric Requests (the billable unit, per account and region), GetMetricData Profile Metric Request Estimates (the same split per profile for ranking; estimates are computed per profile and do not add up to the total), and GetMetricData Query Items (submitted queries, for plan tuning). They count only ListMetrics and GetMetricData, not STS or tag lookups, and they are inputs for cost visibility, not an invoice.

Reducing the cost

OptionEffect
rules[].profiles, rules[].metrics, rules[].regions, rules[].targetsCollect only the services, metrics, regions, and accounts you need.
rule_defaults.filters.resource_tags, rules[].filters.resource_tagsCollect only tagged resources.
rule_defaults.query.period with update_everyRead less often. A 5-minute period with update_every: 300 cuts a 1-minute selection by five.
discovery.refresh_everyScan for new resources less often.
discovery.recently_active_only (default on)Keep ListMetrics scans to resources active in the last 3 hours where the query horizon allows it.

The opt-in Billing profiles use a 10-minute period, so each selected Billing series costs 144 metric requests per day before retries; their cardinality grows with services and linked accounts, so select only the grains you need.

Setup

You can configure the cloudwatch collector in two ways:

MethodBest forHow to
UIFast setup without editing filesGo to Nodes → Configure this node → Collectors → Jobs, search for cloudwatch, then click + to add a job.
FileIf you prefer configuring via file, or need to automate deployments (e.g., with Ansible)Edit go.d/cloudwatch.conf and add a job.
important

UI configuration requires paid Netdata Cloud plan.

Prerequisites

Create an AWS IAM identity with CloudWatch read access

The collector authenticates as an IAM user or role that can read CloudWatch. Attach this policy to it:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cloudwatch:ListMetrics",
"cloudwatch:GetMetricData"
],
"Resource": "*"
}
]
}
  • cloudwatch:ListMetrics and cloudwatch:GetMetricData do not support resource-level permissions, so "Resource": "*" is already the least privilege for these read actions (AWS reference).
  • Add tag:GetResources (also "Resource": "*") when you use resource tag filters or labels.
  • Add sts:AssumeRole on each role ARN a target assumes, and let the role's trust policy allow this identity.
  • A job that selects only the billing_total profile can omit cloudwatch:ListMetrics.

Verify as that identity: aws cloudwatch list-metrics --namespace AWS/EC2 --region <region> --max-items 1 should return without an access error.

Enable Billing metrics before selecting a Billing profile

The four Billing profiles are opt-in and collect nothing until AWS publishes estimated-charge metrics for your account.

  1. In the AWS Billing console open Billing preferences and enable Receive CloudWatch Billing Alerts (AWS documentation). For consolidated billing, do it in the management (payer) account.
  2. Wait about 15 minutes for the first data. AWS then publishes new estimates several times a day.

Enabling the preference needs the root user or an IAM principal allowed to view billing; the collector identity needs only the read policy above. AWS states that once enabled, Billing metric collection cannot be turned off; if the management (payer) account changes, enable it again in the new account. AWS publishes Billing metrics only in us-east-1, in USD, and not for APN accounts.

Add or override a profile (optional)

Stock profiles live under /usr/lib/netdata/conf.d/go.d/cloudwatch.profiles/default/. To add a service or change a chart, put a profile under /etc/netdata/go.d/cloudwatch.profiles/; a file with the same basename as a stock profile overrides it. Profiles are read once at startup, so restart Netdata after changing one. Format and rules: AWS CloudWatch profile format.

Configuration

Options

All options are set per job. update_every and autodetection_retry can also be set globally for the collector.

Config options
GroupOptionDescriptionDefaultRequired
Collectionupdate_everyData collection interval, in seconds, at least 60. All CloudWatch series are collected on this interval; a shorter metric period does not make Netdata query more often.60no
autodetection_retryHow often to retry the initial connection when the job fails to start, in seconds. Zero disables retries.0no
timeoutTimeout in seconds for AWS API calls; a whole discovery refresh and a whole resource-tag lookup each share one timeout.30no
CredentialscredentialsNamed credential sources that targets reference. Each uses the AWS SDK default chain or explicit static credentials.yes
credentials[].nameName that targets use to reference this credential source.yes
credentials[].typeHow this source obtains AWS credentials: the SDK default chain or explicit static credentials.yes
credentials[].type_staticExplicit AWS credentials, used only when the type is static. Prefer secret references over plaintext values.no
credentials[].type_static.access_key_idAWS access key ID. Use a secret reference such as ${env:AWS_ACCESS_KEY_ID}.no
credentials[].type_static.secret_access_keyAWS secret access key. Use a secret reference instead of a plaintext value.no
credentials[].type_static.session_tokenAWS session token, only for temporary credentials. Use a secret reference.no
TargetstargetsNamed AWS identities to monitor. A target uses one credential source directly or assumes one role with it.yes
targets[].nameName that collection rules use to reference this target.yes
targets[].credentialsName of a credential source defined on the Credentials tab.yes
targets[].assume_role.role_arnARN of the IAM role to assume with the target's credential source.no
targets[].assume_role.external_idExternal ID the role's trust policy expects, if it requires one. This is not a password or access key.no
RulesrulesOrdered collection rules. Each selects targets, profiles, regions, and optional metric overrides and resource filters; the first matching rule owns a series.yes
rules[].nameUnique rule name, shown in logs and diagnostics.yes
rules[].targetsNames of the targets this rule collects from, in order. Order breaks ties when rules overlap.yes
rules[].profiles.defaultsStart from every default-enabled profile before applying the include and exclude lists.yesno
rules[].profiles.includeProfile basenames to add. With defaults off, only this list is collected, including profiles disabled by default.no
rules[].profiles.excludeProfile basenames to remove from the selection. A profile cannot be both included and excluded.no
rules[].metricsPer-profile metric overrides. Leave empty to collect each selected profile's default-enabled metrics.no
rules[].metrics[].profileProfile basename to override. It must be selected by this rule's profiles and may appear in one metrics group only.yes
rules[].metrics[].defaultsKeep the profile's default-enabled metrics and add the included ones. Turn off for an exact-only selection.yesno
rules[].metrics[].statisticsStatistics for included metrics that do not list their own. Leave empty to use the profile's statistics.no
Rules / Query Policyrules[].metrics[].queryQuery timing for the series this group includes explicitly. Fields left empty inherit from the rule.no
rules[].metrics[].query.periodCloudWatch aggregation period for these series, from 1m to 24h in whole minutes.no
rules[].metrics[].query.lookbackWindow searched for the newest datapoint. At least one period, a whole multiple of it, and at most 1,440 periods.no
rules[].metrics[].query.publication_delayHow long to wait after a period closes before querying it. A scheduling policy, not an AWS guarantee.no
Rulesrules[].metrics[].includeExact, case-sensitive CloudWatch metric names this group adds. A name may repeat only with disjoint statistics.yes
rules[].metrics[].include[].nameExact, case-sensitive CloudWatch MetricName exported by the profile.yes
rules[].metrics[].include[].statisticsStatistics for this metric, replacing the group list. Leave empty to inherit.no
Rules / Query Policyrules[].metrics[].include[].queryQuery timing for this metric's series, overriding the group's. Fields left empty inherit.no
rules[].metrics[].include[].query.periodCloudWatch aggregation period for these series, from 1m to 24h in whole minutes.no
rules[].metrics[].include[].query.lookbackWindow searched for the newest datapoint. At least one period, a whole multiple of it, and at most 1,440 periods.no
rules[].metrics[].include[].query.publication_delayHow long to wait after a period closes before querying it. A scheduling policy, not an AWS guarantee.no
Rulesrules[].regionsAWS region codes this rule collects from. Profiles that support fewer regions are restricted automatically.yes
Rules / Query Policyrule_defaults.queryQuery timing inherited by every rule, field by field. Fields left empty fall back to profile or built-in values.no
rule_defaults.query.periodDefault CloudWatch aggregation period, from 1m to 24h in whole minutes. Rules, groups, and metrics may override it.no
rule_defaults.query.lookbackDefault window searched for the newest datapoint. At least one period, a whole multiple of it, and at most 1,440 periods.no
rule_defaults.query.publication_delayDefault wait after a period closes before querying it. A scheduling policy, not an AWS guarantee.no
rules[].queryQuery timing overrides for this rule. Fields left empty inherit the rule defaults; group and metric values take precedence.no
rules[].query.periodCloudWatch aggregation period for these series, from 1m to 24h in whole minutes.no
rules[].query.lookbackWindow searched for the newest datapoint. At least one period, a whole multiple of it, and at most 1,440 periods.no
rules[].query.publication_delayHow long to wait after a period closes before querying it. A scheduling policy, not an AWS guarantee.no
Rules / Resource Filtersrule_defaults.filters.resource_tagsResource tag filters inherited by rules that define none. A resource must match every key, with any listed value per key.no
rule_defaults.filters.resource_tags[].keyExact, case-sensitive AWS tag key. A filter list supports at most 50 keys.yes
rule_defaults.filters.resource_tags[].valuesAccepted values for this key, 1 to 20, exact and case-sensitive. Any of them matches.yes
rules[].filters.resource_tagsResource tag filters replacing the job defaults for this rule. Leave unset to inherit, or set an empty list to disable filtering.no
rules[].filters.resource_tags[].keyExact, case-sensitive AWS tag key. A filter list supports at most 50 keys.yes
rules[].filters.resource_tags[].valuesAccepted values for this key, 1 to 20, exact and case-sensitive. Any of them matches.yes
Resource Labelslabels.resource_tagsAWS resource tags copied to charts as labels. Presentation only; they never select resources.no
labels.resource_tags[].keyExact, case-sensitive AWS tag key to copy.yes
labels.resource_tags[].labelNetdata label key to use. Leave empty to derive it from the AWS key (Name becomes name).no
Limitslimits.max_instancesMaximum distinct resource instances that emit metrics. Exceeding it rejects the plan instead of collecting a subset.1000no
limits.max_discovery_groupsMaximum target, region, and namespace combinations discovered per job, 1 to 100. Split larger collection across jobs.64no
Discoverydiscovery.refresh_everyHow often to rediscover matching metrics and resources, in seconds, at least 60.300no
discovery.recently_active_onlyRestrict discovery to metrics active in the last three hours where possible, which keeps scans smaller and cheaper.yesno
Virtual NodevnodeAssociates this job with a Virtual Node.no
credentials

Up to 64 credential sources. Several targets can share one source.

credentials[].name

Names are lowercase, start with a letter, use only letters, digits, _, and -, and are at most 64 characters. Target and rule names follow the same format.

credentials[].type
TypeBehaviorUse when
defaultAWS SDK default credential chain: environment variables, shared config and credentials files, EC2 instance profile, or EKS IRSANetdata runs inside AWS or the host already has an AWS identity
staticExplicit access key ID and secret access key, plus an optional session token, in type_staticKeys are provisioned externally; reference them as ${env:NAME} rather than writing them in the file
credentials[].type_static

Required when the type is static and not allowed otherwise. Inside it, access_key_id and secret_access_key are required; session_token only for temporary credentials.

targets

Up to 64 targets. Targets stay distinct even when they resolve to the same AWS account. Every target must be selected by at least one rule and every credential source used by at least one target; an unused entry stops the job with target "<name>" is not referenced by any rule.

targets[].assume_role.external_id

The role owner supplies the value; see AWS guidance for third-party access.

rules

Up to 256 rules. Explicit metric selections expand to at most 256 metric/statistic pairs per rule.

rules[].profiles.include

PrivateLink detail choices are privatelink_endpoint_subnet, privatelink_service_az, privatelink_service_load_balancer, privatelink_service_az_load_balancer, and privatelink_service_vpc_endpoint. Billing choices are billing_total, billing_service, billing_linked_account, and billing_linked_account_service.

A profile that supports fewer regions than the rule (CloudFront and the Billing profiles exist only in us-east-1) is skipped silently when selected by defaults, but stops the job when named here with only unsupported regions.

rules[].metrics[].statistics

Spell statistics as AWS does, case-insensitively: Average, Minimum, Maximum, Sum, SampleCount, or a percentile such as p90 or p99.9. The profile-file spelling sample_count is not accepted in a job.

rules[].metrics[].include[].statistics

Same spelling as the group list: Average, Minimum, Maximum, Sum, SampleCount, or p<N>. Each statistic must be one the profile declares for that metric.

rules[].regions

Use canonical lowercase region codes. CloudFront and the Billing profiles support only us-east-1.

rule_defaults.query

The resolved publication_delay + lookback + period horizon cannot exceed 14 days.

rule_defaults.query.period

The period that wins for a series (metric item, then group, then rule, then this default, then the profile's metric-level query, then the profile's query) is also the one used to normalize rate metrics to per-second values.

rule_defaults.query.publication_delay

Leaving it unset falls through to the profile value and then the built-in 10m fallback. Setting it overrides profile-specific delays for every inheriting rule, including the stock S3 storage profile's conservative 24h; AWS documents only that S3 storage metrics are reported once per day, so use a shorter default only after verifying each workload's publication timing.

rule_defaults.filters.resource_tags

The Resource Groups Tagging API performs the lookup and requires the tag:GetResources permission.

labels.resource_tags

Tag values may contain personal data, so expose only keys intended for Netdata. Requires the tag:GetResources permission.

limits.max_instances

Overflow rejects the refreshed plan; collection never truncates to the first N instances. In the configuration file 0 selects the default; the form does not accept 0.

limits.max_discovery_groups

Compatible rules and profiles share groups. One refresh can admit at most 100 groups that reach ListMetrics. In the configuration file 0 selects the default; the form does not accept 0.

discovery.refresh_every

Also the lifetime of resolved resource tags. In the configuration file 0 selects the default; the form does not accept 0.

discovery.recently_active_only

Profiles sharing one target, region, and namespace share one scan; the filter applies only while every participating series has publication_delay + lookback + period of three hours or less.

via UI

Configure the cloudwatch collector from the Netdata web interface:

  1. Go to Nodes.
  2. Select the node where you want the cloudwatch data-collection job to run and click the (Configure this node). That node will run the data collection.
  3. The Collectors → Jobs view opens by default.
  4. In the Search box, type cloudwatch (or scroll the list) to locate the cloudwatch collector.
  5. Click the + next to the cloudwatch collector to add a new job.
  6. Fill in the job fields, then click Test to verify the configuration and Submit to save.
    • Test runs the job with the provided settings and shows whether data can be collected.
    • If it fails, an error message appears with details (for example, connection refused, timeout, or command execution errors), so you can adjust and retest.

via File

The configuration file name for this integration is go.d/cloudwatch.conf.

The file format is YAML. Generally, the structure is:

update_every: 1
autodetection_retry: 0
jobs:
- name: some_name1
- name: some_name2

You can edit the configuration file using the edit-config script from the Netdata config directory.

cd /etc/netdata 2>/dev/null || cd /opt/netdata/etc/netdata
sudo ./edit-config go.d/cloudwatch.conf
Examples
Default credentials, single region

The minimal job. The Agent host already has an AWS identity (environment, shared config, instance profile, or IRSA), and every default-enabled profile is collected in one region.

Config
jobs:
- name: default_credentials
credentials:
- name: sdk_default
type: default
targets:
- name: base
credentials: sdk_default
rules:
- name: base-defaults
targets: [base]
regions: [us-east-1]

Static access keys

The Agent host has no AWS identity of its own. Use an access key pair from your AWS administrator, referenced from the environment rather than written in the file.

Config
jobs:
- name: static_keys
credentials:
- name: keys
type: static
type_static:
access_key_id: ${env:AWS_ACCESS_KEY_ID}
secret_access_key: ${env:AWS_SECRET_ACCESS_KEY}
targets:
- name: base
credentials: keys
rules:
- name: base-defaults
targets: [base]
regions: [us-east-1, eu-west-1]

Monitor several AWS accounts by assuming roles

One credential source assumes a different IAM role in each account you monitor. Each role needs the read policy from Prerequisites and a trust policy that allows this identity, with an external ID when the role owner requires one.

Config
jobs:
- name: cross_account
credentials:
- name: sdk_default
type: default
targets:
- name: production
credentials: sdk_default
assume_role:
role_arn: "arn:aws:iam::111111111111:role/netdata-cloudwatch-readonly"
external_id: ${env:AWS_EXTERNAL_ID}
- name: staging
credentials: sdk_default
assume_role:
role_arn: "arn:aws:iam::222222222222:role/netdata-cloudwatch-readonly"
rules:
- name: both-defaults
targets: [production, staging]
regions: [us-east-1, eu-west-1]

Collect a metric a profile leaves off by default

The EC2 profile declares CPU credit balance for burstable instances but does not collect it by default. Naming it adds it to the default EC2 metrics with the profile's statistic.

Config
jobs:
- name: ec2_with_cpu_credits
credentials:
- name: sdk_default
type: default
targets:
- name: base
credentials: sdk_default
rules:
- name: ec2
targets: [base]
profiles:
defaults: false
include: [ec2]
metrics:
- profile: ec2
include:
- name: CPUCreditBalance
regions: [us-east-1]

Read one metric at two resolutions

Lambda Duration as a five-minute average and as a one-minute p90. Each statistic is its own series with its own timing; the same metric and statistic cannot be listed twice.

Config
jobs:
- name: lambda_split_policy
credentials:
- name: sdk_default
type: default
targets:
- name: base
credentials: sdk_default
rules:
- name: lambda-duration
targets: [base]
profiles:
defaults: false
include: [lambda]
metrics:
- profile: lambda
defaults: false
query:
period: 5m
lookback: 30m
publication_delay: 10m
include:
- name: Duration
statistics: [Average]
- name: Duration
statistics: [p90]
query:
period: 1m
lookback: 5m
publication_delay: 5m
regions: [us-east-1]

Lower resolution to reduce cost

Everything at five-minute resolution with discovery every 15 minutes, for accounts where cost matters more than freshness. The daily S3 storage profile is excluded because a five-minute period with a fifteen-minute lookback can never find its once-a-day datapoint.

Config
jobs:
- name: low_resolution
update_every: 300
credentials:
- name: sdk_default
type: default
targets:
- name: base
credentials: sdk_default
rule_defaults:
query:
period: 5m
lookback: 15m
rules:
- name: five-minute-defaults
targets: [base]
profiles:
exclude: [s3]
regions: [us-east-1]
discovery:
refresh_every: 900

AWS Billing estimated charges

Month-to-date estimated charges, in total and split by service and linked account. Enable Billing metrics first (Prerequisites); they exist only in us-east-1 and have no resource tags, so any inherited tag filter is disabled for this rule.

Config
jobs:
- name: billing_estimated_charges
credentials:
- name: sdk_default
type: default
targets:
- name: billing
credentials: sdk_default
rules:
- name: billing-grains
targets: [billing]
profiles:
defaults: false
include:
- billing_total
- billing_service
- billing_linked_account
- billing_linked_account_service
regions: [us-east-1]
filters:
# Billing is not an RGTA resource. This explicitly
# disables any inherited resource-tag filter.
resource_tags: []

PrivateLink endpoints tagged environment=production, with per-minute connection metrics and six-hour byte totals for the same endpoints.

Config
jobs:
- name: privatelink_endpoints
credentials:
- name: sdk_default
type: default
targets:
- name: base
credentials: sdk_default
rule_defaults:
filters:
resource_tags:
- key: environment
values: [production]
rules:
- name: endpoint-split-timing
targets: [base]
profiles:
defaults: false
include: [privatelink_endpoint]
metrics:
- profile: privatelink_endpoint
defaults: false
query:
period: 1m
lookback: 5m
publication_delay: 5m
include:
- name: ActiveConnections
statistics: [Average]
- name: BytesProcessed
statistics: [Average]
- name: NewConnections
statistics: [Average]
- name: BytesProcessed
statistics: [Sum]
query:
period: 6h
lookback: 6h
publication_delay: 5m
regions: [us-east-1]
labels:
resource_tags:
- key: Name

The per-subnet detail grain for PrivateLink endpoints tagged environment=production. One endpoint produces one chart instance per subnet, and the subnet charts inherit the endpoint's tags.

Config
jobs:
- name: privatelink_endpoint_subnets
credentials:
- name: sdk_default
type: default
targets:
- name: base
credentials: sdk_default
rule_defaults:
filters:
resource_tags:
- key: environment
values: [production]
rules:
- name: endpoint-subnets
targets: [base]
profiles:
defaults: false
include: [privatelink_endpoint_subnet]
regions: [us-east-1]
labels:
resource_tags:
- key: Name

The provider side of PrivateLink, for services tagged environment=production. Per-minute traffic, a five-minute connected-endpoint count, and six-hour byte totals.

Config
jobs:
- name: privatelink_services
credentials:
- name: sdk_default
type: default
targets:
- name: base
credentials: sdk_default
rule_defaults:
filters:
resource_tags:
- key: environment
values: [production]
rules:
- name: service-split-timing
targets: [base]
profiles:
defaults: false
include: [privatelink_service]
metrics:
- profile: privatelink_service
defaults: false
query:
period: 1m
lookback: 5m
publication_delay: 5m
include:
- name: ActiveConnections
statistics: [Average]
- name: BytesProcessed
statistics: [Average]
- name: NewConnections
statistics: [Average]
- name: RstPacketsSent
statistics: [Average]
- name: EndpointsCount
statistics: [Average]
query:
period: 5m
lookback: 5m
publication_delay: 5m
- name: BytesProcessed
statistics: [Sum]
query:
period: 6h
lookback: 6h
publication_delay: 5m
regions: [us-east-1]
labels:
resource_tags:
- key: Name

Everything, including opt-in profiles

Every default profile plus every opt-in grain in one region. Read the cardinality and cost notes under Metrics and Performance Impact before using this on a large account.

Config
jobs:
- name: defaults_and_opt_in
credentials:
- name: sdk_default
type: default
targets:
- name: base
credentials: sdk_default
rules:
- name: expanded-services
targets: [base]
profiles:
defaults: true
include:
- alb_target
- dynamodb_operation
- s3_requests
- ebs_stalled_io
- privatelink_endpoint_subnet
- privatelink_service_az
- privatelink_service_load_balancer
- privatelink_service_az_load_balancer
- privatelink_service_vpc_endpoint
- billing_total
- billing_service
- billing_linked_account
- billing_linked_account_service
regions: [us-east-1]

Filter resources by tag and add tag labels

Only resources tagged managed-by=platform, with the Name and owner tags shown as chart labels. Profiles Netdata ships no resource-tag association for (CloudFront, API Gateway, ElastiCache, MSK, Auto Scaling, Bedrock, the ALB and NLB target-health grains) cannot be tag-filtered and are skipped by a filtered rule; collect them from a second rule that disables the inherited filter, as the CloudFront rule does.

Config
jobs:
- name: tagged_resources
credentials:
- name: sdk_default
type: default
targets:
- name: base
credentials: sdk_default
rule_defaults:
filters:
resource_tags:
- key: managed-by
values: [platform]
rules:
- name: filtered-defaults
targets: [base]
regions: [us-east-1]
- name: unfiltered-cloudfront
targets: [base]
profiles:
defaults: false
include: [cloudfront]
regions: [us-east-1]
filters:
resource_tags: []
labels:
resource_tags:
- key: Name
- key: owner
label: resource_owner

Present AWS metrics on a virtual node

Show the AWS charts as their own Netdata node instead of on the host running the collector. The virtual node must already exist in the Agent's vnodes configuration.

Config
jobs:
- name: aws_production
vnode: aws-production
credentials:
- name: sdk_default
type: default
targets:
- name: base
credentials: sdk_default
rules:
- name: base-defaults
targets: [base]
regions: [us-east-1]

Alerts

The following alerts are available:

Alert nameOn metricDescription
aws_cloudwatch_ec2_status_check_failed cloudwatch.ec2.status_check_failedEC2 instance ${label:instance_id} in ${label:region} has failed AWS status checks.
aws_cloudwatch_ec2_attached_ebs_status_check_failed cloudwatch.ec2.status_check_failedEC2 instance ${label:instance_id} in ${label:region} has an attached EBS volume failing AWS status checks.
aws_cloudwatch_alb_target_group_unhealthy_hosts cloudwatch.alb_target_health.unhealthy_hostsALB target group ${label:target_group} on load balancer ${label:load_balancer} in ${label:region} has sustained unhealthy registered targets.
aws_cloudwatch_nlb_target_group_unhealthy_hosts cloudwatch.nlb_target_health.unhealthy_hostsNLB target group ${label:target_group} on load balancer ${label:load_balancer} in ${label:region} has sustained unhealthy registered targets.
aws_cloudwatch_ebs_stalled_io_check_failed cloudwatch.ebs_stalled_io.stalled_io_checkEBS volume ${label:volume_id} in ${label:region} has failed AWS stalled I/O checks.
aws_cloudwatch_nat_gateway_port_allocation_errors cloudwatch.nat_gateway.errorsNAT Gateway ${label:nat_gateway_id} in ${label:region} is reporting source-port allocation failures.
aws_cloudwatch_efs_io_limit_reached cloudwatch.efs.io_limitEFS file system ${label:file_system_id} in ${label:region} is at its AWS PercentIOLimit threshold.
aws_cloudwatch_efs_burst_credits_exhausted cloudwatch.efs.burst_creditEFS file system ${label:file_system_id} in ${label:region} has exhausted burst credits.
aws_cloudwatch_ecs_cpu_utilization cloudwatch.ecs.utilizationECS service ${label:service_name} in cluster ${label:cluster_name} (${label:region}) has sustained CPU utilization above the AWS recommended alarm threshold.
aws_cloudwatch_ecs_memory_utilization cloudwatch.ecs.utilizationECS service ${label:service_name} in cluster ${label:cluster_name} (${label:region}) has sustained memory utilization above the AWS recommended alarm threshold.
aws_cloudwatch_ecs_ebs_filesystem_utilization cloudwatch.ecs.ebs_filesystem_utilizationECS service ${label:service_name} in cluster ${label:cluster_name} (${label:region}) has sustained EBS filesystem utilization above the AWS recommended alarm threshold.
aws_cloudwatch_opensearch_cluster_status_red cloudwatch.opensearch.cluster_statusOpenSearch domain ${label:domain_name} in ${label:region} is reporting red cluster status.
aws_cloudwatch_opensearch_cluster_status_yellow cloudwatch.opensearch.cluster_statusOpenSearch domain ${label:domain_name} in ${label:region} is reporting yellow cluster status.
aws_cloudwatch_opensearch_index_writes_blocked cloudwatch.opensearch.index_writes_blockedOpenSearch domain ${label:domain_name} in ${label:region} is blocking index write requests.
aws_cloudwatch_opensearch_jvm_memory_pressure cloudwatch.opensearch.jvm_memory_pressureOpenSearch domain ${label:domain_name} in ${label:region} has sustained JVM memory pressure above the AWS recommended alarm threshold.
aws_cloudwatch_opensearch_cpu_utilization cloudwatch.opensearch.cpuOpenSearch domain ${label:domain_name} in ${label:region} has sustained maximum CPU utilization above the AWS recommended alarm threshold.
aws_cloudwatch_opensearch_automated_snapshot_failure cloudwatch.opensearch.automated_snapshot_failureOpenSearch domain ${label:domain_name} in ${label:region} has a failed automated snapshot.
aws_cloudwatch_opensearch_old_gen_jvm_memory_pressure cloudwatch.opensearch.old_gen_jvm_memory_pressureOpenSearch domain ${label:domain_name} in ${label:region} has sustained old-generation JVM memory pressure above the AWS recommended alarm threshold.
aws_cloudwatch_elasticache_engine_cpu_utilization cloudwatch.elasticache.cpuElastiCache node ${label:cache_cluster_id}/${label:cache_node_id} in ${label:region} has sustained engine CPU utilization above the AWS recommended alarm threshold.
aws_cloudwatch_msk_active_controller_missing cloudwatch.msk_cluster.active_controllersMSK cluster ${label:cluster_name} in ${label:region} has had no active controller for a sustained period.
aws_cloudwatch_msk_multiple_active_controllers cloudwatch.msk_cluster.active_controllersMSK cluster ${label:cluster_name} in ${label:region} has had more than one active controller for a sustained period.
aws_cloudwatch_msk_offline_partitions cloudwatch.msk_cluster.offline_partitionsMSK cluster ${label:cluster_name} in ${label:region} has had offline partitions for a sustained period.
aws_cloudwatch_msk_cpu_utilization cloudwatch.msk.cpuMSK broker ${label:broker_id} in cluster ${label:cluster_name} (${label:region}) has sustained CpuUser plus CpuSystem above the AWS best-practice threshold.
aws_cloudwatch_msk_data_logs_disk_used cloudwatch.msk.disk_usedMSK broker ${label:broker_id} in cluster ${label:cluster_name} (${label:region}) has sustained data-log disk utilization above the AWS best-practice threshold.
aws_cloudwatch_msk_heap_memory_after_gc cloudwatch.msk.heap_memory_after_gcMSK broker ${label:broker_id} in cluster ${label:cluster_name} (${label:region}) has sustained heap memory after GC above the AWS best-practice threshold.
aws_cloudwatch_msk_under_replicated_partitions cloudwatch.msk.partitionsMSK broker ${label:broker_id} in cluster ${label:cluster_name} (${label:region}) has had under-replicated partitions for a sustained period. This can happen during planned MSK rolling maintenance, but outside expected maintenance it means replicas are not fully caught up.
aws_cloudwatch_msk_under_min_isr_partitions cloudwatch.msk.under_min_isrMSK broker ${label:broker_id} in cluster ${label:cluster_name} (${label:region}) has had partitions below the configured minimum in-sync replica count for a sustained period.
aws_cloudwatch_rds_replica_lag cloudwatch.rds.replica_lagRDS instance ${label:db_instance_identifier} in ${label:region} has sustained replica lag above the AWS recommended alarm threshold.
aws_cloudwatch_rds_maximum_used_transaction_ids cloudwatch.rds.maximum_used_transaction_idsRDS instance ${label:db_instance_identifier} in ${label:region} is above the AWS recommended transaction ID alarm threshold.
aws_cloudwatch_rds_ebs_byte_balance cloudwatch.rds.ebs_balanceRDS instance ${label:db_instance_identifier} in ${label:region} has sustained EBS byte balance below the AWS recommended alarm threshold.
aws_cloudwatch_rds_ebs_io_balance cloudwatch.rds.ebs_balanceRDS instance ${label:db_instance_identifier} in ${label:region} has sustained EBS I/O balance below the AWS recommended alarm threshold.
aws_cloudwatch_vpn_tunnel_down cloudwatch.vpn.tunnel_stateSite-to-Site VPN ${label:vpn_id} in ${label:region} has one or more tunnels down.
aws_cloudwatch_sns_invalid_notification_attributes cloudwatch.sns.invalid_notificationsSNS topic ${label:topic_name} in ${label:region} has sustained notifications filtered out because of invalid attributes.
aws_cloudwatch_sns_invalid_notification_body cloudwatch.sns.invalid_notificationsSNS topic ${label:topic_name} in ${label:region} has sustained notifications filtered out because of invalid message bodies.
aws_cloudwatch_sns_notifications_redriven_to_dlq cloudwatch.sns.dlq_redriveSNS topic ${label:topic_name} in ${label:region} has sustained notifications moved to a dead-letter queue.
aws_cloudwatch_sns_notifications_failed_to_redrive_to_dlq cloudwatch.sns.dlq_redriveSNS topic ${label:topic_name} in ${label:region} has sustained notifications that could not be moved to a dead-letter queue.

Metrics

Metrics grouped by scope.

The scope defines the instance that the metric belongs to. An instance is uniquely identified by a set of labels.

Charts come from the selected profiles. Each stock profile is linked below and is the authoritative list of its metrics, statistics, dimensions, and charts; to see exactly what one job collects, open the Metrics tab of its dashboard.

Every chart instance is one AWS resource, identified by account_id, region, and the profile's identifying dimensions (for example EC2 instance_id, or S3 bucket_name and storage_type). A dimension that is the same for every resource of a profile (CloudFront's Region=Global) is matched but not shown as a label. Tags selected with labels.resource_tags are added as labels that are not part of the chart identity, so a changed tag changes the label, not the chart. Charts land on the job's vnode when one is set, otherwise on the node running the collector; AWS resources never become separate Netdata nodes. CloudWatch publishes with a delay, so allow a few minutes for the first datapoints.

The four collector-activity charts in the scopes below are fixed and present in every job. They count the collector's own AWS API work for cost visibility (see Performance Impact).

Default profiles, collected by any rule that does not restrict profiles:

ProfileMetric prefixDescription
Amazon EC2cloudwatch.ec2.*CPU utilization, network traffic, disk operations, status-check failures, attached-EBS status-check failures
Amazon RDScloudwatch.rds.*CPU utilization, database connections, freeable memory, swap usage, free storage space, disk queue depth, disk and network throughput, IOPS, latency, replica lag, PostgreSQL transaction ID usage, EBS credit balance
Classic Load Balancer (ELB)cloudwatch.elb.*request count, backend and load-balancer response codes, backend connection errors, latency, host count, spillover count
Application Load Balancer (ALB)cloudwatch.alb.*request count, target and load-balancer response codes, connection rate, active connections, processed traffic, target response time, consumed LCUs
ALB Target Healthcloudwatch.alb_target_health.*per-target-group unhealthy host count
Network Load Balancer (NLB)cloudwatch.nlb.*active and new flow counts, processed bytes and packets, consumed LCUs, TCP resets
NLB Target Healthcloudwatch.nlb_target_health.*per-target-group unhealthy host count
Amazon S3cloudwatch.s3.*bucket size, number of objects (daily storage metrics)
AWS Lambdacloudwatch.lambda.*invocations, errors and throttles, duration
Amazon SQScloudwatch.sqs.*message throughput, empty receives, queue depth, maximum age of oldest message, sent message size
Amazon DynamoDBcloudwatch.dynamodb.*consumed and provisioned capacity, throttle events
Amazon API Gatewaycloudwatch.api_gateway.*requests, errors, latency
AWS Step Functionscloudwatch.step_functions.*executions, throttled events, execution time
NAT Gatewaycloudwatch.nat_gateway.*traffic, active connections, connection rate, errors, idle timeouts
AWS PrivateLink endpointscloudwatch.privatelink_endpoint.*endpoint-level active and new connections, processed bytes, dropped packets, and received reset packets
AWS PrivateLink endpoint servicescloudwatch.privatelink_service.*provider-side active and new connections, connected endpoints, processed bytes, and sent reset packets
Amazon Kinesis Data Streamscloudwatch.kinesis.*data throughput, records, GetRecords iterator age, operation latency, throughput exceeded, PutRecords rejected
Amazon Data Firehosecloudwatch.firehose.*records, throughput, put requests, throttled records, S3 delivery freshness and success
Amazon SNScloudwatch.sns.*messages published, notifications, invalid notification filters, DLQ redrive, published message size
Amazon EBScloudwatch.ebs.*volume throughput, IOPS, queue length, idle time, burst balance
Amazon EFScloudwatch.efs.*I/O throughput, metered vs permitted throughput, percent I/O limit, burst credit balance, client connections
Amazon ECScloudwatch.ecs.*service utilization, EBS filesystem utilization, live task count
Amazon ElastiCachecloudwatch.elasticache.*CPU utilization, memory, database memory usage, current and new connections, cache hits and misses, evictions, network traffic
Amazon OpenSearch Servicecloudwatch.opensearch.*cluster status, index writes blocked, automated snapshot failures, nodes, CPU utilization, JVM memory pressure, old-gen JVM memory pressure, free storage space, search and indexing rate, search and indexing latency
Amazon DocumentDBcloudwatch.docdb.*CPU utilization, freeable memory, connections, buffer cache hit ratio, disk IOPS, latency, throughput, replica lag, cursors timed out
Amazon Redshiftcloudwatch.redshift.*health, CPU utilization, disk space used, database connections, disk IOPS, throughput, network throughput
Amazon MSKcloudwatch.msk.*broker throughput, messages in, CPU, disk used, memory, heap memory after GC, partitions, under-min-ISR partitions, connections
Amazon MSK Clustercloudwatch.msk_cluster.*active controllers and offline partitions
Amazon CloudFrontcloudwatch.cloudfront.*requests, downloaded and uploaded traffic, total/4xx/5xx error rates (us-east-1 only)
AWS Auto Scalingcloudwatch.auto_scaling.*group sizing (min/max/desired/total) and instances by state (in-service, pending, standby, terminating)
Amazon Bedrockcloudwatch.bedrock.*invocations, invocation errors, token throughput, invocation and time-to-first-token latency
Amazon EventBridgecloudwatch.eventbridge.*target invocations, rule activity (matched events, triggered rules), ingestion-to-invocation latency
AWS Site-to-Site VPNcloudwatch.vpn.*tunnel traffic (in/out) and tunnel state (fraction of tunnels up)
Amazon EKScloudwatch.eks.*control-plane health: API server request rate, errors, p99 latency, and in-flight requests; etcd database size; scheduler pending pods and scheduling attempts

Opt-in profiles, collected when a rule names them in profiles.include:

ProfileMetric prefixDescription
ALB Target Groupscloudwatch.alb_target.*per-target-group host count, requests per target, response time, response codes, connection errors
DynamoDB Operationscloudwatch.dynamodb_operation.*per-operation successful request latency, system errors, throttled requests, returned items
EBS Stalled I/Ocloudwatch.ebs_stalled_io.*per-volume stalled I/O health check; the EBS stalled I/O alert fires only when a rule opts into this profile
S3 Request Metricscloudwatch.s3_requests.*requests, request errors, request latency, request data transfer; needs per-bucket request metrics enabled in AWS
AWS PrivateLink endpoints by subnetcloudwatch.privatelink_endpoint_subnet.*the endpoint metrics split by subnet_id; one endpoint can produce several chart instances, which inherit the endpoint's tags
AWS PrivateLink services by Availability Zonecloudwatch.privatelink_service_az.*provider-side traffic split by availability_zone and service_id
AWS PrivateLink services by load balancercloudwatch.privatelink_service_load_balancer.*provider-side traffic split by load_balancer_arn and service_id
AWS PrivateLink services by Availability Zone and load balancercloudwatch.privatelink_service_az_load_balancer.*provider-side traffic split by availability_zone, load_balancer_arn, and service_id
AWS PrivateLink services by VPC endpointcloudwatch.privatelink_service_vpc_endpoint.*provider-side traffic split by service_id and consumer vpc_endpoint_id; tags come from the parent endpoint service, never from the consumer endpoint
AWS Billing totalcloudwatch.billing_total.*latest worldwide estimated month-to-date charge
AWS Billing by servicecloudwatch.billing_service.*estimated charges by service_name
AWS Billing by linked accountcloudwatch.billing_linked_account.*estimated charges by linked_account_id, when the payer account publishes this grain
AWS Billing by linked account and servicecloudwatch.billing_linked_account_service.*estimated charges by linked_account_id and service_name, when available
Opt-in profiles can be high-cardinality or metered by AWS

S3 Request Metrics are billed by AWS at custom-metric rates once enabled on a bucket. The PrivateLink detail grains multiply chart instances by subnets, Availability Zones, load balancers, and consumer endpoints. The Billing service and linked-account grains grow with the payer's services and accounts. Select only the grains you need.

A stock profile can also declare opt-in metrics (disabled: true on the metric); enable one through rules[].metrics[].include without copying the profile. Billing charts show the latest published month-to-date estimate in USD for the whole account; region=us-east-1 is where AWS publishes them, not where the charge occurred, and around the UTC month boundary the previous month's value stays until AWS publishes the new one.

Per AWS account, region, and operation

Collector-issued CloudWatch SDK work attributed to one resolved AWS account, region, and SDK operation.

Labels:

LabelDescription
account_idResolved AWS account ID.
regionAWS region where the collector attempted the SDK invocation.
operationCollector-issued CloudWatch SDK operation (list_metrics or get_metric_data).

Metrics:

MetricDescriptionDimensionsUnit
cloudwatch.collector_sdk_invocationsCloudWatch SDK Invocationsinvocationsinvocations

Per AWS account and region

Calculated CloudWatch metric requests attributed to one resolved AWS account and region.

Labels:

LabelDescription
account_idResolved AWS account ID.
regionAWS region where the collector submitted the metric requests.

Metrics:

MetricDescriptionDimensionsUnit
cloudwatch.collector_get_metric_data_calculated_metric_requestsGetMetricData Calculated Metric Requestscalculated_metric_requestsmetric requests

Per AWS account, region, and profile

CloudWatch metric-data request estimates and query items attributed to their source profile for cost ranking and collection-plan tuning.

Labels:

LabelDescription
account_idResolved AWS account ID.
regionAWS region where the collector submitted the requests.
profileCloudWatch profile that produced the submitted query items.

Metrics:

MetricDescriptionDimensionsUnit
cloudwatch.collector_get_metric_data_profile_metric_request_estimatesGetMetricData Profile Metric Request Estimatesestimated_metric_requestsmetric requests
cloudwatch.collector_get_metric_data_query_itemsGetMetricData Query Itemsquery_itemsquery items

Troubleshooting

Diagnostics

Debug Mode

Important: Debug mode is not supported for data collection jobs created via the UI using the Dyncfg feature.

To troubleshoot issues with the cloudwatch collector, run the go.d.plugin with the debug option enabled. The output should give you clues as to why the collector isn't working.

  • Navigate to the plugins.d directory, usually at /usr/libexec/netdata/plugins.d/. If that's not the case on your system, open netdata.conf and look for the plugins setting under [directories].

    cd /usr/libexec/netdata/plugins.d/
  • Switch to the netdata user.

    sudo -u netdata -s
  • Run the go.d.plugin to debug the collector:

    ./go.d.plugin -d -m cloudwatch

    To debug a specific job:

    ./go.d.plugin -d -m cloudwatch -j jobName

Getting Logs

If you're encountering problems with the cloudwatch collector, follow these steps to retrieve logs and identify potential issues:

  • Run the command specific to your system (systemd, non-systemd, or Docker container).
  • Examine the output for any warnings or error messages that might indicate issues. These messages should provide clues about the root cause of the problem.
System with systemd

Use the following command to view logs generated since the last Netdata service restart:

journalctl _SYSTEMD_INVOCATION_ID="$(systemctl show --value --property=InvocationID netdata)" --namespace=netdata --grep cloudwatch
System without systemd

Locate the collector log file, typically at /var/log/netdata/collector.log, and use grep to filter for collector's name:

grep cloudwatch /var/log/netdata/collector.log

Note: This method shows logs from all restarts. Focus on the latest entries for troubleshooting current issues.

Docker Container

If your Netdata runs in a Docker container named "netdata" (replace if different), use this command:

docker logs netdata 2>&1 | grep cloudwatch

Known Errors

AWS request failed (code=AccessDeniedException, status=403, request_id=...)

When

Logged as part of a CloudWatch <operation> failed for N target/region operation(s) warning, where the operation is account resolution, discovery, GetMetricData, query client creation, or resource tag lookup. The codes AccessDenied, NotAuthorized, and Forbidden mean the same.

Cause

The IAM identity behind the named target is not allowed the AWS action that operation uses: cloudwatch:ListMetrics for discovery, cloudwatch:GetMetricData for reads, tag:GetResources for tag lookups, or sts:AssumeRole when the target assumes a role. The collector never prints the AWS message itself, only the code, HTTP status, and request id.

Fix

Attach the policy from Prerequisites to that identity, adding tag:GetResources if the job uses tag filters or labels. For a target with assume_role, allow sts:AssumeRole on the role ARN for the source identity and let the role's trust policy accept it. The next discovery refresh or collection cycle retries automatically.

AWS request failed (code=ExpiredToken, status=403, request_id=...)

When

Also ExpiredTokenException, InvalidClientTokenId, UnrecognizedClientException, or SignatureDoesNotMatch.

Cause

The credential source is expired, revoked, mistyped, or belongs to a different AWS partition than the regions it is used for.

Fix

Renew or correct the credentials. For a static source, check the access_key_id and secret_access_key values and, for temporary keys, the session_token; prefer ${env:NAME} references so a rotated key is picked up without editing the file. For the default source, check what the AWS SDK finds on the Agent host (aws sts get-caller-identity as the netdata user).

AWS request failed

When

The message carries no code= and no status=.

Cause

The request never reached AWS or got no AWS answer: DNS resolution, an outbound firewall or proxy, or TLS interception on the Agent host. Provider-side detail is deliberately not logged.

Fix

From the Agent host, as the netdata user, run aws sts get-caller-identity --region <region> and aws cloudwatch list-metrics --region <region> --max-items 1; the AWS CLI shows the underlying network or TLS error. Allow outbound HTTPS to the CloudWatch, STS, and Tagging endpoints of every selected region, or configure the proxy through the standard HTTPS_PROXY environment of the Netdata service.

AWS request timed out

Cause

An AWS call exceeded timeout (default 30 seconds). A whole discovery refresh and a whole resource tag lookup share one timeout; each GetMetricData and STS call has its own.

Fix

Raise timeout, or make the work smaller: fewer regions and profiles per rule, resource tag filters, or split the job. A timed-out discovery refresh is discarded and retried after discovery.refresh_every; a timed-out read is retried on the next collection.

AWS request failed (code=Throttling, status=400, request_id=...)

When

Also ThrottlingException or RequestLimitExceeded.

Cause

The account exceeded the CloudWatch API request rate. The AWS SDK already attempts each call up to five times with a short backoff before this is logged, so the job is well above the rate.

Fix

Reduce request volume: a longer period in rule_defaults.query, a longer update_every, fewer metrics or regions, or split targets across jobs that do not run at the same second. Retried reads are billed.

no AWS target could be resolved (N failed); last failure for target "<name>" region "<region>": ...

Cause

sts:GetCallerIdentity failed for every target, so the job has no AWS account to attribute metrics to. The trailing text is one of the AWS request ... messages above and names the actual reason.

Fix

Fix the credentials or network problem named in the trailing message. Targets that fail while others succeed are retried every cycle without failing the job; only total failure stops collection.

target "<name>" is not referenced by any rule

When

Also credential "<name>" is not referenced by any target. The job does not start.

Cause

Every target must be selected by at least one rule and every credential source used by at least one target; an unused entry is treated as a configuration mistake rather than ignored.

Fix

Reference the entry from a rule (or target), or remove it.

'credentials' must contain at least one entry

When

Together with 'targets' must contain at least one entry and 'rules' must contain at least one entry when the job has no configuration at all.

Cause

The job is missing one of the three required blocks. Nothing is collected by default.

Fix

Add at least one credential source, one target that references it, and one rule with targets and regions; see the first example under Setup.

rules[N].name "<name>" must match "^[a-z][a-z0-9_-]{0,63}$"

When

The same for credentials[N].name and targets[N].name.

Cause

Names are lowercase, start with a letter, use only letters, digits, _ and -, and are at most 64 characters. Duplicate names produce duplicate rule name "<name>" (or target, credential).

Fix

Rename the entry and update the places that reference it (targets[].credentials, rules[].targets).

rules[N].regions[M] "US-EAST-1" is not canonical; use "us-east-1"

When

Also rules[N].regions[M] "<value>" is not a valid AWS region.

Cause

Regions must be the lowercase AWS region code such as us-east-1 or eu-west-1.

Fix

Correct the region code.

target "<name>" spans multiple AWS partitions across regions [...]

When

Also target "<name>" role partition "aws" does not match selected region partition "aws-us-gov".

Cause

All regions collected for one target must belong to one AWS partition (standard aws, GovCloud aws-us-gov, China aws-cn), and an assumed role's ARN must belong to the same partition.

Fix

Give each partition its own target (and rule), or split the job per partition, and use a role ARN of the matching partition.

rules[N] explicitly includes profile "cloudfront", but none of regions [...] are supported

Cause

Some profiles exist only in us-east-1 (CloudFront and the four Billing profiles). When such a profile is selected by defaults it is silently skipped for other regions; when it is named in profiles.include or in a rules[].metrics[] group with only unsupported regions the job refuses to start.

Fix

Add us-east-1 to the rule's regions, or collect that profile from a separate rule limited to us-east-1.

rules[N].profiles.include references unknown profile "<name>"

Cause

No loaded profile has that basename: a typo, or a user profile that was added after the plugin started. Profiles are read once at startup.

Fix

Use the basename of a file under /usr/lib/netdata/conf.d/go.d/cloudwatch.profiles/default/ or /etc/netdata/go.d/cloudwatch.profiles/; after adding a profile, restart Netdata.

rules[N].metrics[M].include[K].name references unknown MetricName "<name>" in profile "<profile>"

When

Also ... "<statistic>" is not exported for MetricName "<name>" in profile "<profile>".

Cause

An explicit metric selection must name a metric the profile declares, spelled exactly as AWS does (CPUUtilization, not cpu_utilization), with a statistic the profile declares for it.

Fix

Open the profile file and copy the metric_name and statistics from its metrics list.

rules[N].metrics[M].statistics[K] is not valid (use Average|Minimum|Maximum|Sum|SampleCount|p<N>)

Cause

In job configuration statistics use the AWS spelling, case-insensitively: Average, Minimum, Maximum, Sum, SampleCount, or a percentile such as p90 or p99.9. The message does not echo the value that failed; the common case is the profile-file spelling sample_count, which a job does not accept.

Fix

Write SampleCount.

rules[N] derives N discovery groups (unique target, region, namespace combinations); exceeds limits.max_discovery_groups=64; ...

Cause

Every unique combination of target, region, and CloudWatch namespace is one ListMetrics discovery group. Many targets times many regions times many services exceeds the safeguard, which defaults to 64 and cannot exceed 100.

Fix

Check that the rule does not select more targets, regions, or profiles than intended. For intentional scale, raise limits.max_discovery_groups up to 100; beyond that, split the collection across jobs (for example one job per target or per region group).

CloudWatch query plan contains more than limits.max_instances=1000 final instances

Cause

After discovery and tag filtering the job would collect more resources than limits.max_instances. The collector refuses the plan rather than collecting a subset, so no metrics are collected until it fits.

Fix

Narrow the selection (rules[].regions, rules[].profiles, resource tag filters) or raise limits.max_instances deliberately, knowing that every resource adds to the AWS bill.

CloudWatch query plan would exceed maximum 20000 queries

When

Also CloudWatch query plan requires more than 600000 datapoints per all-due pass or ... more than 40 GetMetricData batches per all-due pass.

Cause

The whole plan, evaluated as if every series were due at once, is larger than the collector will query safely. Only very broad rules across many regions, services, and resources reach these bounds.

Fix

Narrow regions, profiles, or metrics, use resource tag filters, or split the collection across jobs.

CloudWatch discovery refresh was discarded atomically: ...

When

Also CloudWatch discovery stage timed out, or a CloudWatch discovery failed for N target/region operation(s) warning. Logged at most once per hour.

Cause

A discovery refresh exceeded timeout or one of its internal size bounds. The previous set of resources stays in use and discovery retries after discovery.refresh_every; on a job's first refresh only profiles with constant dimensions (billing_total) can collect until discovery succeeds.

Fix

Raise timeout, narrow the rule's regions and profiles, or split the job. If the failure names a specific target and region, check that identity's cloudwatch:ListMetrics permission.

CloudWatch GetMetricData returned Forbidden for N metric result(s): ...; verify each target identity is allowed cloudwatch:GetMetricData

Cause

AWS accepted the request but refused some of the metrics in it, which happens when a target's identity lacks cloudwatch:GetMetricData or a policy condition excludes the namespace.

Fix

Grant cloudwatch:GetMetricData without namespace conditions to the identity of the target named in the message.

CloudWatch GetMetricData left N metric result(s) unresolved: ...; retained values are replayed and retries use per-query exponential backoff

Cause

AWS returned PartialData or InternalError for some metrics, or a result did not come back. The collector keeps showing the last value it has and retries with a doubling delay up to one period.

Fix

Nothing, unless it persists across many collections; then check the AWS Health Dashboard for the region and reduce the request volume (fewer metrics, longer period).

all due CloudWatch queries failed transiently and no retained observations are available

Cause

Every read due in this collection failed and the job has no earlier values to repeat, so the collection cycle fails. On a new job this usually means AWS is unreachable or throttling; on a running job it follows a long outage.

Fix

Look for the AWS request ... warning logged just before it and follow its entry above.

CloudWatch discovered N instances; this scales GetMetricData cost — narrow collection rules if this is unexpected

Cause

Discovery found 1,000 or more resources. Collection is not truncated; the warning exists because every resource multiplies the AWS bill.

Fix

If the count is expected, ignore it. Otherwise narrow regions, profiles, or add resource tag filters, and read the Performance Impact section.

CloudWatch collection plan: rule "<name>" has N metric selection(s) shadowed by earlier rules; example: ...

When

Also CloudWatch collection rules shadowed N duplicate exported series; earliest matching rule/target order owns each series.

Cause

Two rules select the same series for the same target and region. The earlier rule (and, within it, the earlier target) owns the series; the later selection is ignored, including its query timing.

Fix

Make the rules disjoint (different profiles, regions, or targets), or move the selection you want to win into the earlier rule.

CloudWatch collection plan: rule "<name>" skips default profiles unsupported in its regions: ...

Cause

A default-enabled profile that exists only in us-east-1 (CloudFront, Billing) was selected by defaults for a rule whose regions do not include it. It is skipped there; no error.

Fix

Nothing, or add a rule for us-east-1 if you want that service.

CloudWatch tags (profile "<profile>"): skipped tag "<tag>": label "<label>" collides with a dimension label (rename it)

Cause

A tag selected in labels.resource_tags would become a label that the profile already uses for a dimension (or one of the reserved account_id and region labels). The tag is not attached.

Fix

Set labels.resource_tags[].label to another name for that key.

load CloudWatch profiles: validate profile "<name>": ...

When

Also unmarshal profile "<name>": ... (invalid YAML) or normalize profile "<name>": .... Every CloudWatch job on the Agent fails, not only the one that uses the profile.

Cause

A profile under /etc/netdata/go.d/cloudwatch.profiles/ does not parse or breaks a profile rule; the trailing text names the field. Profiles are loaded once for the whole plugin, so one bad file stops all jobs.

Fix

Fix or remove the file following the profile format and restart Netdata.

rules[N] explicitly includes profile "<name>" with resource tag filtering, but it has no safe tag association: profile is not registered

When

The non-fatal sibling for profiles selected by defaults is CloudWatch collection plan: rule "<name>" skips default profiles without a safe resource-tag association: ....

Cause

Resource tag filters need a mapping from the profile's CloudWatch dimensions to a taggable AWS resource, and Netdata ships none for this profile (CloudFront and the Billing profiles, among others). A profile named explicitly under a tag filter cannot be filtered, so the job refuses to start; a default-selected one is skipped with a warning.

Fix

Give that profile its own rule with filters: {resource_tags: []} to collect it unfiltered, or drop it from the filtered rule.

credentials[N].type_static is required

When

Also credentials[N].type_static is not allowed when credentials[N].type is "default", credentials[N].type "<value>" is invalid: expected one of "default", "static", credentials[N].type_static.access_key_id is required, or ... must not contain surrounding whitespace.

Cause

The credential block does not match its type: static needs type_static with access_key_id and secret_access_key; default takes no type_static; values must not be padded with spaces.

Fix

Shape the block as the two examples under Setup show (type: default alone, or type: static with type_static).

rules[N].profiles.include must not be empty when defaults is false

When

Also rules[N].profiles selects no profiles (exclusions removed everything) or rules[N] compiles to no collection scopes (every selected profile was filtered away by regions or tag associations).

Cause

The rule ends up selecting nothing. Narrowing with defaults: false, exclude, region-restricted profiles, or tag filters went one step too far.

Fix

Name at least one profile in include, remove the exclusion that empties the set, or add a region the selected profiles support.

targets[N].assume_role.role_arn is invalid: expected an IAM role ARN

When

Also ... is invalid: invalid ARN syntax.

Cause

The value is not a role ARN of the form arn:<partition>:iam::<12-digit-account>:role/<name>.

Fix

Copy the role ARN from the IAM console; it must name the iam service, have no region, a 12-digit account id, and a role/ resource.

candidate collection scopes exceed maximum 16384

When

Also compiled collection scopes exceed maximum 4096.

Cause

Targets times profiles times regions, before or after filtering, is larger than the collector will compile. Only rules that combine many targets, all profiles, and many regions reach this.

Fix

Split the collection across jobs, for example one job per target or per region group.

CloudWatch resource tag filtering reserved N exported series from lower-priority rules while membership was unknown

When

Preceded by CloudWatch resource tag lookup failed for N target/region operation(s): ... (retaining fail-closed membership and last-known labels).

Cause

The tag lookup (tag:GetResources) failed, so the collector does not know which resources match the filter. It keeps the last known membership and labels, and resources whose membership is unknown stay uncollected rather than being collected unfiltered.

Fix

Follow the AWS request ... message inside the lookup failure (usually a missing tag:GetResources permission or a timeout on a large tagged estate; raise timeout for the latter). Collection resumes on the next successful lookup.

No charts appear although the job runs without errors

Cause

CloudWatch has nothing for the selection yet. Typical reasons: the resources are idle (several services, such as EventBridge and Bedrock, publish a metric only when its value is non-zero); the metric is not enabled on the AWS side (Auto Scaling group metrics need enable-metrics-collection; EKS control-plane metrics exist only for Kubernetes 1.28 or later; S3 request metrics need per-bucket request-metrics configuration; Billing needs the preference from Prerequisites); or the first datapoint has not been published yet, which takes a few minutes and up to a day for the daily S3 storage metrics.

Fix

Confirm in the AWS CloudWatch console that the resource publishes the metric in that region, enable the AWS-side feature if needed, and give a new job a few minutes. If the console shows data but Netdata does not, read the Diagnostics output for one of the AWS request ... messages above.

Charts have gaps or show a stale value

Cause

CloudWatch publishes each period late and irregularly; the collector reads a series only when a new period is complete and repeats the newest value in between. A gap means no datapoint existed within the lookback window; a value that seems old is the newest one AWS has, and during an AWS outage the last good value stays until a read succeeds.

Fix

Keep period at or above the metric's real publication cadence (a shorter period cannot make AWS publish more often). If a workload publishes later than the profile expects, raise publication_delay at the rule or metric level; if datapoints are sparse, widen lookback (a whole multiple of the period). Do not lower rule_defaults.query.publication_delay below a profile's own value unless you have verified the publication timing; the S3 storage profile uses one day for a reason.

A user profile does not take effect

Cause

Profiles are read once when the plugin starts and cached for its lifetime, so a file added or edited under /etc/netdata/go.d/cloudwatch.profiles/ is not seen by a running plugin. A user profile whose chart id collides with another profile's is loaded but the colliding chart is dropped, with a warning logged under the cloudwatch/cwprofiles component rather than the job.

Fix

Restart Netdata after changing profiles. Give every chart in a user profile an id that no other loaded profile uses.

A service I use has no profile

Cause

Coverage is defined by the profiles shipped with Netdata, one per service and grain. A missing service means nobody has authored its profile yet; no code change is needed to add one.

Fix

Open a feature request and attach the service's CloudWatch metric schema, captured with this read-only command, which prints only metric and dimension names (no resource ids, ARNs, or values):

aws cloudwatch list-metrics --namespace "AWS/<Service>" --region <your-region> --output json \
| jq -c '[.Metrics[] | {metric: .MetricName, dimensions: ([.Dimensions[].Name] | sort)}] | unique'

Replace AWS/<Service> with the namespace (for example AWS/AmazonMQ) and <your-region> with a region where the service runs. Or author the profile yourself following the profile format.

The AWS bill is higher than expected

Cause

Cost scales with resources, selected metrics and statistics, request frequency, and lookback; see the drivers table under Performance Impact. The most common causes are a 1-minute period on many resources, opt-in detail grains (PrivateLink, DynamoDB operations, Billing by linked account and service), and broad rules that select every default profile in many regions.

Fix

Read the GetMetricData Profile Metric Request Estimates chart to see which profiles drive the requests, then narrow rules[].profiles, rules[].metrics, and rules[].regions, add resource tag filters, or raise rule_defaults.query.period together with update_every.


Do you have any feedback for this page? If so, you can open a new issue on our netdata/learn repository.