AWS Developer Tools Blog

Monitoring Your Estimated Costs with Windows PowerShell

The documentation for Amazon CloudWatch contains this sample scenario for setting up alarms to monitor your estimated charges. Apart from a one-time operation to enable billing alerts for your account, the same capability can be set up and maintained using the AWS Tools for Windows PowerShell.

Enabling Alerts

The first step is to enable billing alerts for your account. To do this one-time operation, you need to use the AWS Billing console.

Important Note: This is a one-way step! Once you enable alerts for an account, you cannot turn them off.

  1. Once you are logged into the console, click Preferences and then select the Receive Billing Alerts check box.
  2. Click the Save preferences button and then log out of the console.

It can take around 15 minutes after enabling this option before you can view billing data and set alarms—plenty of time to read the rest of this post!

The remainder of this post assumes you are working in a PowerShell console prompt (or environment like the PowerShell ISE), have the AWSPowerShell module loaded, and your environment is configured to default to the account that you just enabled billing alerts for. If you’re not sure how to do this, check out this post on configuring accounts for PowerShell. In addition to setting the account, we’ll also need to use the US East (Virginia) region for the cmdlets we need to run, since this is where all metric data related to billing is held. We could add a -Region us-east-1 parameter to each cmdlet, but it’s simpler in this case to set a default for the current shell or script:

PS C:> Set-DefaultAWSRegion us-east-1

Now all cmdlets that we run in the current shell or script will operate by default against this region.

Setting Up the Billing Alarm and Notification

Once we’ve enabled billing alerts, we can start to construct alarm notifications. Just as in the Amazon CloudWatch sample, we’ll create an alarm that will trigger an Amazon SNS topic to send an email notification when our total estimated charges for the period exceeds $200.

We’ll first set up the email notification topic, and then use the topic as the alarm action later when we create the alarm.

Creating the Notification Topic

To create a new topic and subscribe an email endpoint to it, we can run this pipeline (indentation used for clarity):

PS C:> ($topicARN = New-SNSTopic -Name BillingAlarmNotifications) | 
                 Connect-SNSNotification -Protocol email `
                                         -Endpoint email@address.com
pending confirmation

The output from the pipeline, pending confirmation, signals that we need to go to our email and confirm the subscription. Once we do this, our topic is all set up to send notifications to the specified email. Notice that we capture the Amazon Resource Name (ARN) of the new topic into the variable $topicARN. We’ll need this when creating the subsequent alarm.

Creating the Alarm

Now that we have the notification topic in place, we can perform the final step to create the alarm.

To do this, we’ll use the Write-CWMetricAlarm cmdlet. For readers who know the underlying Amazon CloudWatch API, this cmdlet maps to the PutMetricAlarm operation and is used to both create and update alarms. Before creating an alarm, we need to know the namespace and the name of the metric it should be associated with. We can get a list of available metrics by using the Get-CWMetrics cmdlet:

PS C:> Get-CWMetrics

Namespace           MetricName                  Dimensions
---------           ----------                  ----------
AWS/Billing         EstimatedCharges            {ServiceName, Currency}
AWS/Billing         EstimatedCharges            {ServiceName, Currency}
AWS/Billing         EstimatedCharges            {ServiceName, Currency}
AWS/Billing         EstimatedCharges            {ServiceName, Currency}
AWS/Billing         EstimatedCharges            {ServiceName, Currency}
AWS/Billing         EstimatedCharges            {ServiceName, Currency}
AWS/Billing         EstimatedCharges            {Currency}

At first glance, this looks like a set of duplicated metrics, but by examining the Dimensions for each object we see the following:

PS C:> (Get-CWMetrics).Dimensions

Name                    Value
----                    -----
ServiceName             AmazonEC2
Currency                USD
ServiceName             AmazonSimpleDB
Currency                USD
ServiceName             AWSQueueService
Currency                USD
ServiceName             AWSDataTransfer
Currency                USD
ServiceName             AmazonSNS
Currency                USD
ServiceName             AmazonS3
Currency                USD
Currency                USD

Now we can see that what initially looked like duplicate metrics are in fact separate metrics for 6 services (in this example) plus one extra that only has a Dimension of Currency—this is the Total Estimated Charge metric we’re interested in for this post. If you wanted to set up billing alerts for, say, Amazon EC2 usage only, then you would simply use that specific dimension when creating the alarm.

Alarms need to have a name that is unique to your account. This, plus the namespace, metric name, and dimension is all we need to create the alarm for the metric, which will be measured periodically. In this example, our alarm threshold (-Threshold parameter) is $200. We want to check every six hours, which we specify using the -Period parameter (the value is in seconds, where 21600 seconds is 6 hours). We want the alarm to fire the first time that the metric breaches, so the value for our -EvaluationPeriods parameter will be 1.

Write-CWMetricAlarm -AlarmName "My Estimated Charges" `
                    -AlarmDescription "Estimated Monthly Charges" `
                    -Namespace "AWS/Billing" `
                    -MetricName EstimatedCharges `
                    -Dimensions @{ Name="Currency"; Value="USD" } `
                    -AlarmActions $topicARN `
                    -ComparisonOperator GreaterThanOrEqualToThreshold `
                    -EvaluationPeriods 1 `
                    -Period 21600 `
                    -Statistic Maximum `
                    -Threshold 200

Note that Amazon CloudWatch returns no response output from the call. If we want to look at the alarm we just created, we can use the Get-CWAlarm cmdlet:

PS C:> Get-CWAlarm "My Estimated Charges"
AlarmName                          : My Estimated Charges
AlarmArn                           : arn:aws:cloudwatch:us-east-1:123412341234:alarm:My Estimated Charges
AlarmDescription                   : Estimated Monthly Charges
AlarmConfigurationUpdatedTimestamp : 3/27/2014 9:41:57 AM
ActionsEnabled                     : True
OKActions                          : {}
AlarmActions                       : {arn:aws:sns:us-east-1:123412341234:BillingNotification}
InsufficientDataActions            : {}
StateValue                         : OK
StateReason                        : Threshold Crossed: 1 datapoint (1.38) was not greater than or equal to the threshold (200.0).
StateReasonData                    : {"version":"1.0","queryDate":"2014-03-27T16:41:58.550+0000","startDate":"2014-03-27T10:41:00.0
                                     00+0000","statistic":"Maximum","period":21600,"recentDatapoints":[1.38],"threshold":20.0}
StateUpdatedTimestamp              : 3/27/2014 9:41:58 AM
MetricName                         : EstimatedCharges
Namespace                          : AWS/Billing
Statistic                          : Maximum
Dimensions                         : {Currency}
Period                             : 21600
Unit                               :
EvaluationPeriods                  : 1
Threshold                          : 200
ComparisonOperator                 : GreaterThanOrEqualToThreshold

All that remains is to wait for the alarm to fire (or, depending on your reasons for wanting to set up the alarm, to not fire!).