Creating a simple AWS Cost Explorer chatbot with CSML

Case Study Jan 14, 2020

AWS Cost Explorer is a very important tool in the AWS universe to make sure that you stay on budget. It helps you find out what the biggest cost drivers are in your infrastructure, decide about optimization strategies, monitor improvements made over your infrastructure… With Cost Explorer, you can quickly detect variations in your cost structure — for example, you may want to try different autoscaling strategies and monitor their impact on your billing.

However, Cost Explorer is often overlooked by AWS users as it is not directly related to creating value (building your application or service), and even experienced customers often forget to check their costs regularly on the Cost Explorer console.

On the other side, chatbots are an easy and friendly way to retrieve information in a familiar chat interface. Especially, ChatOps are a trend with a lot of monitoring and alerting tools integrated into messaging platforms such as Slack.


In this tutorial, we will go over how to create a simple chatbot that gathers a first level of information from AWS Cost Explorer. This tutorial assumes that you have an AWS account and some basic knowledge of IAM user rights administration, as well as some understanding of some very basic code principles in order to be able to read the CSML flows — don’t worry, it is quite self-explanatory. The CSML documentation is available on https://docs.csml.dev for reference.

You will also need a free account in the CSML Studio and perhaps as well a Slack account to deploy this bot!

The conversation

The first thing I do when thinking about a small chatbot like this is map out the conversation in the concisest form possible. Pen and paper will do at this point!

We would like to be able to do two things in our bot:

  • retrieve past costs for monitoring
  • find out a forecast of future projected costs for anticipating

We will also need to be able to know what is the timeframe (start/end date) for the cost report. As we are looking for something quick/simple, let’s only use prepared dates: last month, today, year to date, next month

Let’s also consider that for this small example, we will not go into splitting costs between services. I leave it to you to adapt the code to your specific use case!

Getting started

First, let’s create a bot and a flow in the CSML studio. Give it a simple name and a default flow with your favorite name — it does not really matter as there will only be one flow in this bot!

bot setup screen in the CSML studio

Greeting the user

It’s usually a good practice to separate the “hello” part from the actual conversation logic. You usually don’t want to say hello to the user everytime you ask them a question, so let’s add this as our start step, which will be automatically triggered whenever a user starts a conversation with the bot:

start:
	say "Hello I'm Costo!"
	say "I'm here to help you with get an overview on your AWS costs."
	goto select

Letting the user select their scenario

Before they can get their costs, we should let the user select whether they want to get past costs, or a forecast on future costs. This can be done very easily in this simple step:

select:
	use Button("Explore my costs", accept=["costs", "cost", "explorer"]) as btnexp
	use Button("Get a forecast", accept=["forecast", "preview"]) as btnfcst
	use Button("Who are you?", accept=["help"]) as btnhelp
	use Button("Nothing, I'm good", accept=["nothing"]) as btnbye

	say Question("What are you looking for?", buttons=[btnexp, btnfcst, btnhelp, btnbye])
	hold

	if (event match btnexp) goto getcost
	else if (event match btnfcst) goto getforecast
	else if (event match btnhelp) goto gethelp
	else if (event match btnbye) goto bye
	say "I'm sorry I did not get that!"
	goto start

Retrieving the current costs

To retrieve the costs we need to know what time period the user wants the costs for, so we need to ask them this information. It’s easier to directly provide a few options than to try and parse all timestamp formats in free text, but of course you are free to accept other formats. Don’t forget to return to select at the end of the step.

getcosts:
	use Button("Today") as tdy
	use Button("Yesterday") as ysdy
	use Button("Month to date") as mtd
	use Button("Year to date") as ytd
	use Button("Last month") as lm
	say Typing(1000)
	say Question(
		"OK, I'm going to retrieve cost and usage data from your account in AWS Cost Explorer. What is the time period?",
		buttons = [tdy, mtd, ytd, lm]
	)
	hold

	say Typing(1000)
	if (event match tdy) remember "TODAY" as cost_period
	else if (event match ysdy) remember "YESTERDAY" as cost_period
	else if (event match mtd) remember "MTD" as cost_period
	else if (event match ytd) remember "YTD" as cost_period
	else if (event match lm) remember "LASTMONTH" as cost_period
	else {
		say "I did not get that."
		goto start
	}
	use Fn("cost_explorer", period=cost_period, action="cost") as costs
	say "Your AWS costs over the selected period are: {{costs.Unit}} {{costs.Total}}"
	goto select

Retrieving future costs

AWS has an option to forecast future costs based on your past usage, with a certain level of confidence. Let’s also use that to our advantage, with about the same setup as above:

getforecast:
	use Button("Today") as tdy
	use Button("Tomorrow") as tmw
	use Button("This month") as mo
	use Button("This year") as yr
	say Typing(1000)
	say Question(
		"OK, I'm going to check your cost forecast from your account in AWS Cost Explorer. What is the time period?",
		buttons = [tdy, tmw, mo, yr]
	)
	hold

	say Typing(1000)
	if (event match tdy) remember "TODAY" as forecast_period
	else if (event match tmw) remember "TOMORROW" as forecast_period
	else if (event match mo) remember "MONTH" as forecast_period
	else if (event match yr) remember "YEAR" as forecast_period
	else {
		say "I did not get that."
		goto start
	}

	use Fn("cost_explorer", period=forecast_period, action="forecast") as costs
	say "Your AWS cost forecast over the selected period is: {{costs.Unit}} {{costs.Mean}}"
	goto select

Saying goodbye

After each action, you can always leave the bot awaiting the user’s choice in the select step, or you can also provide a “goodbye” hook to close the conversation. This can be done in the step bellow, which is accessible as one of the options of the select step.

bye:
	say Typing(1000)
	say "OK! Ping me whenever you need me!"
	goto end

You should also provide a way for the user to get more information about the bot, so a “get help” option would be great:

gethelp:
	say Typing(1000)
	say "I'm a nice bot helping you find out about your costs within your AWS account. Isn't that great?"
	goto select

The cost_explorer function

AWS provides an easy-to-use SDK for interacting with their services, so that part is relatively easy as we can use the provided methods. I have provided the source code to this function here on github.

To setup your functions, you will also need a IAM user with at least the following rights (read only on Cost Explorer):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ce:GetCostAndUsage",
                "ce:GetCostForecast"
            ],
            "Resource": "*"
        }
    ]
}

Retrieve this user’s ACCESS_KEY_ID and SECRET_ACCESS_KEY and you are all set!

Wrapping Up & Next Steps

We are sharing the source code for this bot so that you can install it in one click without any effort by simply pasting this URL into the “import bot” dialog in the CSML studio: https://github.com/CSML-by-Clevy/AWSCostExplorerBot

Here is the result in Slack for example!

An example conversation in Slack

This is really a simple scenario that I coded as a demo for a customer in about 30 minutes, including the function to retrieve the data from Code Explorer, while also explaining how everything works.

One thing that I would usually do if I were to take this bot further would be to split up the various parts into different flows, just to make them easier to access separately or react to trigger commands.

You can also of course add more options to the cost_explorer function to extend your bot or make the conversation a little more fun with emojis and gifs. I leave that part to your imagination!

You can download this flow here and install it on https://studio.csml.dev. Create your free account today and start building fun and simple, or complex and high-value chatbots using the CSML programming language!

Tags