<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Weird rocketry &#187; cloudwatch</title>
	<atom:link href="http://webapp.org.ua/tag/cloudwatch/feed" rel="self" type="application/rss+xml" />
	<link>https://webapp.org.ua</link>
	<description>Flights to outer code</description>
	<lastBuildDate>Sat, 16 Jul 2016 11:12:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>CloudWatch custom metrics</title>
		<link>https://webapp.org.ua/dev/cloudwatch-custom-metrics/</link>
		<comments>https://webapp.org.ua/dev/cloudwatch-custom-metrics/#comments</comments>
		<pubDate>Wed, 16 Dec 2015 15:40:08 +0000</pubDate>
		<dc:creator>bananos</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[cloudwatch]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[time series]]></category>

		<guid isPermaLink="false">http://webapp.org.ua/?p=397</guid>
		<description><![CDATA[In this post we&#8217;re going to investigate how to create custom metrics for the AWS CloudWatch service. In some cases it&#8217;s not enough to have default set of AWS metrics which are already defined for you in dashboard. Let&#8217;s say you want to monitor the number of active customers on your website, or you would [...]]]></description>
			<content:encoded><![CDATA[<div class="markdown-content">
<p><img class="size-full wp-image-417 alignleft" title="cloudwatch_logo" src="http://webapp.org.ua/wp-content/uploads/2015/12/cloudwatch_logo.png" alt="" width="225" height="225" /></p>
<p>In this post we&#8217;re going to investigate how to create custom metrics for the AWS CloudWatch service. In some cases it&#8217;s not enough to have default set of AWS metrics which are already defined for you in dashboard. Let&#8217;s say you want to monitor the number of active customers on your website, or you would like to know the number of failed requests to your API backend.</p>
<p>Whatever it is, CloudWatch will allow you to record any time-based data using AWS APIs.</p>
<p><br style="clear: both;" /></p>
</div>
<p><span id="more-397"></span></p>
<div class="markdown-content">
<h2>Install AWS CLI</h2>
<p>First off, in order to post data to CloudWatch you need to install and setup <a href="https://pypi.python.org/pypi/awscli/">command-line tools to work with AWS APIs</a>:</p>
<pre><code class="bash" title="">$ pip install awscli
</code></pre>
<p>If you don&#8217;t know what <code>pip</code> is, head over <a href="https://pip.pypa.io/en/latest/installing.html">pip installation manual</a>.<br />
Once AWS CLI is installed the <code>aws</code> command should be available via your command shell:</p>
<pre><code class="bash" title="">$ aws
usage: aws [options]   [ ...] [parameters]
To see help text, you can run:

aws help
aws: error: too few arguments
</code></pre>
<p>Before issuing real commands to AWS service you need to configure cli tools:</p>
<pre><code class="bash" title="">$ aws configure
AWS Access Key ID [****************KCEQ]:
AWS Secret Access Key [****************x++s]:
Default region name [us-west-2]:
Default output format [json]:
</code></pre>
<p>After successfull configuration you should be able to use command-line interface for AWS, for example, let&#8217;s list all available EC2 instances:</p>
<pre><code class="" title="">$ aws ec2 describe-instances | grep "PublicDnsName" | awk '{$1=$1};1' | uniq
"PublicDnsName": "ec2-44-148-96-212.us-west-2.compute.amazonaws.com",
"PublicDnsName": "ec2-42-25-174-143.us-west-2.compute.amazonaws.com",
"PublicDnsName": "ec2-44-68-194-93.us-west-2.compute.amazonaws.com",
"PublicDnsName": "ec2-44-69-229-202.us-west-2.compute.amazonaws.com",
</code></pre>
<h2>Choose a metric</h2>
<p>Let&#8217;s say that we want to monitor application API status by periodically requesting specific endpoint and checking HTTP response code. In our example we&#8217;ll use <code>http://httpbin.org/status/200</code> URL to demo.</p>
<p>We will consider HTTP 200 response code as a <code>service alive</code> event and treat it as <code>1</code>, and any other response code(including timeout) as a <code>service failure</code> event or <code>0</code>.</p>
<p>The following bash code(<code>service_mon.sh</code>) will output HTTP response code:</p>
<pre><code class="bash" title="">#!/bin/bash
CODE=`curl -k -s -o /dev/null -w "%{http_code}" http://httpbin.org/status/200`
echo $CODE
</code></pre>
<p>Run it and verify that script outputs <code>200</code>:</p>
<pre><code class="" title="">$ ./service_mon.sh
200
</code></pre>
<h2>Choose metric name</h2>
<p>We&#8217;re going to name our metric <code>ServiceStatus</code> and will report it to CloudWatch using <code>cloudwatch</code> subcommand. Modify above mentioned <code>service_mon.sh</code> script to be the following:</p>
<pre><code class="bash" title="">#!/bin/bash

# get response code
CODE=`curl -k -s -o /dev/null -w "%{http_code}" http://httpbin.org/status/200`
if [ "$CODE" -eq 200 ] ; then
aws cloudwatch put-metric-data --metric-name ServiceStatus --namespace CL_AGENTS --value 1 --unit "Count"
else
aws cloudwatch put-metric-data --metric-name ServiceStatus --namespace CL_AGENTS --value 0 --unit "Count"
fi
</code></pre>
<p>Note <code>CL_AGENTS</code> in cmd parameters, this is a convenient group name for all your metrics, typically you&#8217;d want to put your application name in there. In this example we&#8217;re specifying a type for our data called <code>Count</code>, this is not the only possible option. Here&#8217;s a list of other units:</p>
<pre><code class="" title="">[ Seconds, Microseconds, Milliseconds, Bytes, Kilobytes, Megabytes, Gigabytes, Terabytes, Bits, Kilobits,
Megabits, Gigabits, Terabits, Percent, Count, Bytes/Second, Kilobytes/Second, Megabytes/Second, Gigabytes/Second,
Terabytes/Second, Bits/Second, Kilobits/Second, Megabits/Second, Gigabits/Second, Terabits/Second, Count/Second, None ]
</code></pre>
<p><a href="http://webapp.org.ua/wp-content/uploads/2015/12/aws_metric_namespace.png"><img class="aligncenter size-full wp-image-415" title="aws_metric_namespace" src="http://webapp.org.ua/wp-content/uploads/2015/12/aws_metric_namespace.png" alt="" width="688" height="578" /></a></p>
<p>&nbsp;</p>
<h2>Periodic script execution</h2>
<p>Put the script we&#8217;ve written into crontab:</p>
<pre><code class="" title=""># m h  dom mon dow   command
*/5 * * * * /mnt/service_mon.sh

</code></pre>
<p><span style="text-align: center;">This will post service status to CloudWatch every 5 minutes.  Here&#8217;s how it might look like in web based AWS console:</span></p>
<p style="text-align: center;"><a href="http://webapp.org.ua/wp-content/uploads/2015/12/cloudwatch_metric.png"><img class="aligncenter size-full wp-image-418" title="cloudwatch_metric" src="http://webapp.org.ua/wp-content/uploads/2015/12/cloudwatch_metric.png" alt="" width="824" height="439" /></a></p>
<p>You may also report multiple values at the same time using JSON file:</p>
<pre><code class="json" title="">[
{
"MetricName": "ServiceStatus",
"Timestamp": "Wednesday, June 12, 2013 8:28:20 PM",
"Value": 1,
"Unit": "Count"
},
{
"MetricName": "ServiceStatus",
"Timestamp": "Wednesday, June 12, 2013 8:30:20 PM",
"Value": 0,
"Unit": "Count"
}
]

</code></pre>
<p>To do bulk reporting use this format:</p>
<pre><code class="" title="">$ aws cloudwatch put-metric-data --namespace "CL_AGENTS" --metric-data file://metric.json
</code></pre>
<h2>Setup alarms</h2>
<p>Up until now our metric is almost useless, except that we may see nice graphs in the CloudWatch. To do it more usable, let&#8217;s add alarm if our API is down:</p>
<ul>
<li>Select <code>ServiceName</code> metric in the <code>CL_AGENTS</code> namespace we&#8217;ve just created</li>
<li>Click <code>Create Alarm</code> button on the right side of the graph</li>
<li>In the subsequent popup, select alarm details:</li>
</ul>
<p style="text-align: center;"><a href="http://webapp.org.ua/wp-content/uploads/2015/12/cloudwatch_create_alarm.png"><img class="aligncenter size-full wp-image-416" title="cloudwatch_create_alarm" src="http://webapp.org.ua/wp-content/uploads/2015/12/cloudwatch_create_alarm.png" alt="" width="836" height="587" /></a></p>
<h2>Gotchas</h2>
<ul>
<li>Keep in mind that CloudWatch will store your time-series data only for <strong>2 weeks (14 days)</strong>, therefore if you want more history and insights for your data you&#8217;re probably will be better off using custom database like <a href="https://github.com/influxdb/influxdb">InfluxDB</a> for example</li>
<li>Make sure to setup aws cli under the same user which your crontab is using, otherwise AWS configuration won&#8217;t be accessible for cron and your monitoring script will not work</li>
</ul>
<h2>Links</h2>
<ul>
<li><a href="https://aws.amazon.com/cloudwatch/">Amazon Cloudwatch service</a></li>
<li><a href="http://docs.aws.amazon.com/cli/latest/reference/cloudwatch/put-metric-data.html">Detailed documentation for put-metric-data command</a></li>
<li><a href="https://en.wikipedia.org/wiki/Time_series_database">Time series database</a></li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>https://webapp.org.ua/dev/cloudwatch-custom-metrics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
