Skip to content

Instantly share code, notes, and snippets.

@adamstauffer
Created April 17, 2018 15:51
Show Gist options
  • Save adamstauffer/fb911274401cf5c59e648583b47ba0f9 to your computer and use it in GitHub Desktop.
Save adamstauffer/fb911274401cf5c59e648583b47ba0f9 to your computer and use it in GitHub Desktop.
Convert AWS Cloudwatch metric alarms into Grafana graph panels with alerts
"""Generate Grafana graph panels from Cloudwatch Metric Alarms.
Meant for alarms that send SNS notifications. Only supports single
dimension Cloudwatch alarms.
"""
import json
import boto3
# enter the partial name of an SNS notification to filter alarm actions
NOTIFICATION_NAME = ''
# name of your cloudwatch datasource in grafana
GRAFANA_CLOUDWATCH_DATASOURCE = 'Cloudwatch'
# region like 'us-east-1'
METRICS_REGION = 'us-east-1'
# grafana notification internal ID
NOTIFICATION_ID = 1
client = boto3.client('cloudwatch')
paginator = client.get_paginator('describe_alarms')
page_iterator = paginator.paginate()
for page in page_iterator:
for metric_alarm in page['MetricAlarms']:
# naive way to filter a cloudwatch alarm with an applicable action
for alarm_action in metric_alarm['AlarmActions']:
if NOTIFICATION_NAME in alarm_action:
alarm_name = metric_alarm.get('AlarmName')
metric_name = metric_alarm.get('MetricName')
namespace = metric_alarm.get('Namespace')
statistic = metric_alarm.get('Statistic')
threshold = metric_alarm.get('Threshold')
# convert cloudwatch comparison to grafana comparison
comparison_operator = metric_alarm.get('ComparisonOperator')
if 'GreaterThan' in comparison_operator:
comparison = 'gt'
if 'LessThan' in comparison_operator:
comparison = 'lt'
# convert evaluation periods & period to evaluation time
evaluation_periods = metric_alarm.get('EvaluationPeriods')
period = metric_alarm.get('Period')
evaluation_time = '{}s'.format(evaluation_periods * period)
# only support a single dimension
dimensions = metric_alarm['Dimensions']
if len(dimensions) == 0:
print(
'Could not convert alarm "{}", '
'no dimensions found!'.format(alarm_name))
break
dimension = dimensions[0]
dimension_name = dimension.get('Name')
dimension_value = dimension.get('Value')
panel_json = {
"alert": {
"conditions": [
{
"evaluator": {
"params": [
threshold,
],
"type": comparison,
},
"operator": {
"type": "and",
},
"query": {
"params": [
"A",
evaluation_time,
"now",
],
},
"reducer": {
"params": [],
"type": "avg",
},
"type": "query",
},
],
"frequency": "60s",
"handler": 1,
"message": "",
"name": alarm_name,
"noDataState": "ok",
"notifications": [
{
"id": NOTIFICATION_ID,
},
],
},
"aliasColors": {},
"bars": False,
"dashes": False,
"datasource": GRAFANA_CLOUDWATCH_DATASOURCE,
"fill": 1,
"id": 10,
"legend": {
"alignAsTable": True,
"avg": False,
"current": True,
"max": False,
"min": False,
"rightSide": True,
"show": True,
"total": False,
"values": True,
},
"lines": True,
"linewidth": 1,
"links": [],
"nullPointMode": "connected",
"percentage": False,
"pointradius": 5,
"points": False,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": False,
"steppedLine": False,
"targets": [
{
"alias": "",
"dimensions": {
dimension_name: dimension_value,
},
"metricName": metric_name,
"namespace": namespace,
"period": "",
"refId": "A",
"region": METRICS_REGION,
"statistics": [
statistic,
],
},
],
"thresholds": [],
"timeFrom": None,
"timeShift": None,
"title": alarm_name,
"tooltip": {
"shared": True,
"sort": 0,
"value_type": "individual",
},
"type": "graph",
"xaxis": {
"buckets": None,
"mode": "time",
"name": None,
"show": True,
"values": [],
},
"yaxes": [
{
"format": "none",
"label": None,
"logBase": 1,
"max": None,
"min": None,
"show": True,
},
{
"format": "short",
"label": None,
"logBase": 1,
"max": None,
"min": None,
"show": True,
},
],
}
print(json.dumps(panel_json))
break
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment