pythonbotoamazon-sqsamazon-cloudwatchcloudwatch

How to read the AWS Status Check Alarm message with Boto


I use python with boto APIs to:

  1. create sns, sqs, and subscribe sqs queue to the sns.
  2. connect to cloudwatch, and create alarm for the "StatusCheckFailed" metric.
  3. use put_metric_alarm to start the alarm monitoring and notification.

I launched one of my own AMI that will simulate StatusCheckFailed condition. If I go to AWS console>SQS, I can see I got the alarm notifications. I can view the content in JSON format too in AWS console.

When I use python, with SQS api, I can:

  1. look up the queue (q = sqs.lookup(queue_name))
  2. get the message (msg = q.read())
  3. get the body of the message (b = message.get_body_encoded())
  4. or message.get_body()

The result is not readable.

  1. get_body_encoded gets you one string without any divider. e.g.

    TypeNotificationMessageId02a8ce9dc21e55eaaeca83b5258563ffTopicArnarnawssnsuswest21888888879statuscheckalarm17122223479SubjectStatusCheckAlarmbadvmstatusalarminUSWest2MessageAlarmNamebadvmstatusalarmAlarmDescriptionstatuscheckfori50602c5abadvmAWSAccountId11233333333NewStateValueALARMNewStateReasonThresholdCross....`
    
  2. get_body gets you un-readable coding.

How can I get the message body in JSON format, e.g. like the one shown in the SQS section of the AWS console?


Solution

  • The result of get_body() returns a JSON-formatted string.

    I recreated your situation by creating an SQS queue and an SNS notification topic, subscribed the SQS queue to the SNS topic, then created an alarm that pushes notifications to the SNS topic. I then triggered an alarm situation and retrieved the results via Python:

    $ python
    Python 2.6.9 (unknown, Sep 13 2014, 00:25:11) 
    [GCC 4.8.2 20140120 (Red Hat 4.8.2-16)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import boto, boto.sqs
    >>> from boto.sqs.message import Message
    >>> q_conn = boto.sqs.connect_to_region("ap-southeast-2")
    >>> q = q_conn.get_queue('bob')
    >>> m = q.read(visibility_timeout=15)
    >>> m.get_body()
    u'{\n  "Type" : "Notification",\n  "MessageId" : "adcad528-680b-5b4f-88bd-98432f1bf252",\n  "TopicArn" : "arn:aws:sns:ap-southeast-2:123412341234:bob-topic",\n  "Subject" : "ALARM: \\"my-alarm-name\\" in APAC - Sydney",\n  "Message" : "{\\"AlarmName\\":\\"my-alarm-name\\",\\"AlarmDescription\\":\\"my-alarm-description\\",\\"AWSAccountId\\":\\"123412341234\\",\\"NewStateValue\\":\\"ALARM\\",\\"NewStateReason\\":\\"Threshold Crossed: 1 datapoint (1459.0) was greater than or equal to the threshold (0.0).\\",\\"StateChangeTime\\":\\"2015-01-11T00:33:20.013+0000\\",\\"Region\\":\\"APAC - Sydney\\",\\"OldStateValue\\":\\"INSUFFICIENT_DATA\\",\\"Trigger\\":{\\"MetricName\\":\\"NetworkIn\\",\\"Namespace\\":\\"AWS/EC2\\",\\"Statistic\\":\\"SUM\\",\\"Unit\\":null,\\"Dimensions\\":[{\\"name\\":\\"InstanceId\\",\\"value\\":\\"i-af41ec91\\"}],\\"Period\\":60,\\"EvaluationPeriods\\":1,\\"ComparisonOperator\\":\\"GreaterThanOrEqualToThreshold\\",\\"Threshold\\":0.0}}",\n  "Timestamp" : "2015-01-11T00:33:20.072Z",\n  "SignatureVersion" : "1",\n  "Signature" : "(removed)",\n  "SigningCertURL" : "(removed)",\n  "UnsubscribeURL" : "https://sns.ap-southeast-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:ap-southeast-2:123412341234:bob-topic:9bc1234c-1234-4995-927a-72b752866e5e"\n}'
    

    The response to get_body() is a string containing JSON. This can be parsed using the JSON library:

    >>> message_string = json.loads(m.get_body())['Message']
    >>> message_string
    u'{"AlarmName":"my-alarm-name","AlarmDescription":"my-alarm-description","AWSAccountId":"123412341234","NewStateValue":"ALARM","NewStateReason":"Threshold Crossed: 1 datapoint (1459.0) was greater than or equal to the threshold (0.0).","StateChangeTime":"2015-01-11T00:33:20.013+0000","Region":"APAC - Sydney","OldStateValue":"INSUFFICIENT_DATA","Trigger":{"MetricName":"NetworkIn","Namespace":"AWS/EC2","Statistic":"SUM","Unit":null,"Dimensions":[{"name":"InstanceId","value":"i-af41ec91"}],"Period":60,"EvaluationPeriods":1,"ComparisonOperator":"GreaterThanOrEqualToThreshold","Threshold":0.0}}'
    >>> message = json.loads(message_string)
    >>> message['AlarmName']
    u'my-alarm-name'