Monitoring the Estimated AWS Charges Using Amazon CloudWatch

Flow diagram showing an Amazon CloudWatch Events rule that invokes an AWS Lambda function. The Lambda function publishes a message to an Amazon SNS topic. Then, the message is delivered to an email subscriber of the SNS topic.

Last updated: July 7, 2019

The estimated AWS charges for your AWS account can be sent several times a day as metric data to CloudWatch in the US East (N. Virginia) region. You can enable this option in the Billing and Cost Management console.

To keep track of your AWS charges, you may want to configure a daily email notification. This blog post describes how to do it.

How to Configure a Daily Email Notification About the Current Estimated AWS Charges

In this procedure, you use a CloudFormation template to create an AWS Lambda function, an Amazon SNS topic, and an Amazon CloudWatch Events rule.

At the configured by you time the CloudWatch Events rule invokes the Lambda function. This function gets the billing metric data from the US East (N. Virginia) region and send a message to the SNS topic. Then, Amazon SNS delivers the message to the email subscriber of the SNS Topic.

For source code of the used Lambda function, see Appendix A, Lambda Function That Sends the Estimated AWS Charges Message to an SNS Topic (Python).

To configure a daily email notification about the current estimated AWS charges, perform the following steps:

  1. Enable billing alerts for your AWS account. Then, wait until billing metric data becomes available in CloudWatch in the US East (N. Virginia) region.
    • Usually, it takes about 15 minutes until billing metric data is delivered to CloudWatch for the first time after you enable billing alerts.
    To check if billing metric data is already available in CloudWatch, execute the following command:
    aws cloudwatch get-metric-statistics \
    --namespace 'AWS/Billing' --metric-name 'EstimatedCharges' \
    --dimensions Name=Currency,Value=USD \
    --start-time $(date -d yesterday --iso-8601=seconds) \
    --end-time $(date --iso-8601=seconds) \
    --period 60 --statistics 'Maximum' --region us-east-1 --output text
    
    The output must contain one or several lines that start with the DATAPOINTS word.
  2. Open CloudFormation Management Console at https://console.aws.amazon.com/cloudformation/home and switch to the AWS region where you want to create the AWS Lambda function, SNS topic, and CloudWatch Events rule. Then, use the following CloudFormation template to create a stack with all the required resources. The download URL of the send-estimated-aws-charges-notification.json CloudFormation template.
    • In the parameters of the stack you have to provide your valid email address. For the rest configuration parameters, you can accept the default values.
  3. Open the email message from AWS Notifications that you received on the configured email address and click the confirmation link.

Appendix A, Lambda Function That Sends the Estimated AWS Charges Message to an SNS Topic (Python)

The following Python code snippet shows how you can publish a message that contains the estimated charges of your AWS account to an SNS topic. The code is compatible with Python 2.7, Python 3.6, and Python 3.7.

Replace billing-topic with the actual name of your SNS topic in the following Python code.

# CloudBriefly.com

from __future__ import print_function
from datetime import datetime, timedelta
import boto3

def lambda_handler(event, context):
    topic_name = 'billing-topic'
    aws_region = context.invoked_function_arn.split(':')[3]
    aws_account_id = context.invoked_function_arn.split(':')[4]
    now = datetime.now()

    # Get billing metric data from the US East (N. Virginia) region
    cloudwatch_client = boto3.client('cloudwatch', region_name='us-east-1')
    metric_statistics = cloudwatch_client.get_metric_statistics(
        Namespace='AWS/Billing', MetricName='EstimatedCharges',
        Dimensions=[{'Name': 'Currency', 'Value': 'USD'}],
        StartTime=(now - timedelta(days=1)), EndTime=now, Period=60,
        Statistics=['Maximum']
    )
    if not metric_statistics['Datapoints']:
        raise Exception('Metric statistics is empty for the last 24 hours.')
    latest_datapoint = sorted(
        metric_statistics['Datapoints'], key=lambda t: t['Timestamp'])[-1]

    # Message
    message = 'At %s the estimated charges of the AWS account %s were %s USD.' % (
        latest_datapoint['Timestamp'], aws_account_id, str(latest_datapoint['Maximum'])
    )
    print(message)

    # Send the message
    sns_client = boto3.client('sns')
    sns_client.publish(
        TopicArn='arn:aws:sns:%s:%s:%s' % (aws_region, aws_account_id, topic_name),
        Subject='AWS estimated charges', Message=message
    )

Appendix B, How to Enable Billing Alerts for an AWS Account

To monitor your estimated charges using Amazon CloudWatch, you must enable billing alerts for your AWS account. You can do it only when you logged in with your AWS root account credentials. AWS root account credentials are the Email address and Password that you used to create your AWS account.

To enable billing alerts:

  1. Use your AWS account Email address and Password to sign in to the AWS Management Console as root user.
  2. Open the Billing Management Console at https://console.aws.amazon.com/billing/home.
  3. In Billing preferences, expand Cost Management Preferences and select Receive Billing Alerts. Screen capture showing the checkbox in the billing preferences that enables billing alerts.
  4. Choose Save preferences.