Greengrass custom monitoring metrics not appearing in CloudWatch after component deployment

We deployed a custom Greengrass v2 component that publishes monitoring metrics to CloudWatch, but the metrics never appear in the console. The component runs successfully on edge devices - logs show it’s executing the metric publication code every 60 seconds without errors.

The component uses the AWS SDK to put custom metrics under the EdgeMonitoring namespace with dimensions for device ID and metric type. We’ve verified the CloudWatch namespace configuration in the component recipe and the IAM role attached to the Greengrass token exchange service has cloudwatch:PutMetricData permission.

Component logs show Publishing metric: cpu_usage value: 45.2 messages, but searching for EdgeMonitoring namespace in CloudWatch returns no results even after 24 hours. The Greengrass core device is online and other AWS service integrations work correctly. What could prevent custom metrics from reaching CloudWatch?

Checked the Greengrass core configuration and the token exchange role ARN matches what’s in IAM. The trust policy has credentials.iot.amazonaws.com as the principal. But I noticed the role was recently updated - could there be a caching issue where the core device is using old credentials?

Check the IAM permissions more carefully. The token exchange role needs cloudwatch:PutMetricData, but it also needs to be in the trust relationship for the Greengrass service. Also, if you’re using metric dimensions, make sure the namespace and dimension names don’t contain special characters or exceed CloudWatch limits (10 dimensions max, 255 chars per dimension value).

Another thing: verify the metric values are valid numbers. CloudWatch silently drops metrics with NaN or infinite values. Add error handling in your code to catch SDK exceptions - just because logs show “publishing” doesn’t mean the API call succeeded.

Excellent troubleshooting - you’ve identified the core issue. Greengrass custom metrics not appearing in CloudWatch typically involves three configuration layers that must align:

CloudWatch Namespace Configuration: Your component recipe must specify the correct namespace and region. In the recipe YAML:

ComponentConfiguration:
  DefaultConfiguration:
    CloudWatchNamespace: "EdgeMonitoring"
    CloudWatchRegion: "us-east-1"

Verify the namespace name matches exactly what your code uses (case-sensitive). CloudWatch can take 2-3 minutes for new namespaces to appear, but 24 hours indicates a deeper issue.

IAM Permissions Structure: The token exchange role needs the permission policy AND must be properly attached to the Greengrass core. Required policy:

{
  "Effect": "Allow",
  "Action": "cloudwatch:PutMetricData",
  "Resource": "*"
}

Note: CloudWatch PutMetricData doesn’t support resource-level permissions, so Resource must be “*”.

The trust policy must include:

{
  "Effect": "Allow",
  "Principal": {"Service": "credentials.iot.amazonaws.com"},
  "Action": "sts:AssumeRole"
}

Greengrass Component Configuration: This is likely where your issue lies. When you update the IAM role, Greengrass cores cache credentials for up to 1 hour. Your AccessDeniedException suggests the core is still using credentials from before the role was updated.

Solutions:

  1. Restart the Greengrass core service to force credential refresh:
sudo systemctl restart greengrass
  1. Or wait for automatic refresh (can take up to 60 minutes)

  2. Verify the role is correctly configured in the core device settings:

    • Go to IoT Console → Greengrass → Core devices → Your device
    • Check “Token exchange role” matches the updated IAM role ARN
    • If it shows an old ARN, update it and deploy

After restarting Greengrass, your component should successfully publish metrics. Verify by checking:

  • Component logs for successful API responses (not just “publishing” messages)
  • CloudWatch console for the EdgeMonitoring namespace (refresh after 2-3 minutes)
  • CloudWatch API using AWS CLI: `aws cloudwatch list-metrics --namespace EdgeMonitoring For production deployments, implement retry logic with exponential backoff in your component code to handle transient credential refresh periods gracefully.

The AccessDeniedException despite having the permission usually means the role isn’t being assumed correctly. For Greengrass v2, check two things:

  1. The token exchange role ARN in your Greengrass core device configuration
  2. The role’s trust policy allowing credentials.iot.amazonaws.com to assume it

If the core device is using an outdated role ARN or the trust policy is missing, components won’t be able to access AWS services even with correct permissions.

Region configuration looks correct - component recipe specifies us-east-1 which matches our Greengrass deployment region. SDK initialization also explicitly sets the region. Still no metrics visible in CloudWatch console for that region.