Help us understand the problem. What is going on with this article?

AWS IoTの利用状況を可視化するCloudwatchカスタムメトリクスを作る

More than 3 years have passed since last update.

AWS IoTのカスタムメトリクス

AWS IoTのコンソール画面が変更され、dashボードが表示されるようになりました。が、thing単位での通信状況はわからないので、rule engineからLambdaへ送り、通信状況をcloudwatchのカスタムメトリクスで表示できるようにしてみました。
マルチテナント型で使う、や、想定外にメッセージが多いときにどのthingがどの位使っているかがわかれば解析が楽になるかなと思います。

現状のdashbordで見れる情報は、アカウント全体の利用状況で以下のように見えます。
スクリーンショット 2017-01-09 9.02.10.png

では、カスタムメトリクス対応を作ってみましょう。

AWS操作

IAM

Lambdaから、cloudwatch からput_metric_dataを使うので、以下2つの権限を持った role を作成してください
AWSLambdaBasicExecutionRole
CloudWatchFullAccess

AWS Lambda

イベントトリガはAWS IoTから作成するので関数だけ作っておいてください。
Lambda から "create a lambda function" -> "configure function"

Name:任意 (ここでは IoT-payload-cal)
Description:任意
Runtime: Python2.7
として以下のコードを利用してください。

前提として dataは jsonで thingNameとしてthingの情報が上がってくるものとします。
例えば以下のようなjsonを想定しています。

example_event.json
{
    "thingName": "xxxx",
    <任意>
}

Lambdaの説明
AWS IoTの課金は、512byteを1-messageとしているのでmessage部分を 512byteで割って小数点を繰り上げしています。これで大まかには詳細利用状況が可視化できるかと思います。floatでcastしているのは、intのままだと小数点が切り捨てられるためです。

コードにはつけてないですが、通信量を見たい場合は、取得したbyte数を同様にカスタムメトリクスにputしてもらえれば、byte数で見ることができると思います。こちらは例えばSIMなどを使ってSIMのコストの概算をみるのによいかと思います。

import json
import math
import datetime
import boto3

CLW = boto3.client('cloudwatch')

def put_cloudwatch(thingName, value):
    try:
        now = datetime.datetime.now()
        CLW.put_metric_data(
            Namespace  = "IoT_count",
            MetricData = [{
                "MetricName" : thingName,
                "Timestamp" : now,
                "Value" : value,
                "Unit" : "Count"
            }]
        )
    except Exception as e:
        print e.message
        raise


def lambda_handler(event, context):

    thingName = event['thingName']
    #JSON to String, and count string bytes
    str_event = json.dumps(event)
    byte_len = len(str_event)
    #count message, AWS IoT 1-message = 512byte
    msg_cnt = float(byte_len)/512

    try:
        put_cloudwatch(thingName, math.ceil(msg_cnt))
    except Exception as e:
        raise

    return 

roleはここで作った role を選択してください。

AWS IoT

AWS IoTから Rules => create

Name:任意 (ここでは、aws_iot_cal)
Description:任意
Using SQL version:beta

すべてのメッセージを通すので、
Attribute:*
Topic filter:#
とします。

Add Actionから、Invoke a Lambda function passing the message data
を選択configure actionから、先ほど作成したLambdaを指定します。

テスト

Lambdaからtest用jsonを作成して実行、もしくはAWS IoTへデータを送ります。
Lambdaのプログラムでも説明したましたが、jsonの中に thingName の情報を必ず入れてください。
lambdaのみで実行確認するには、例えば以下のようなjsonで確認出来ます。

test.json
{
  "thingName": "testThing-1",
  "key3": "value3",
  "key2": "value2",
  "key1": "value1"
}

testThing-1でメトリクスが作成されます。時間単位の積算データはcloudwatchのsumで見てください。
スクリーンショット 2017-01-09 9.40.26.png

1つのNamespaceに複数のthingからputすると以下のようになります。
スクリーンショット 2017-01-09 9.53.16.png

最後に

マルチテナント型や工場/設置場所別で分けたい場合はAWS IoTでtopicとrule enginによる打ち分けで、lambdaを分けて、namespaceを分けるなどすると、良いかもしれません。
大規模なthing登録の場合、全イベントでlambdaが発火されるので、lambdaの同時起動数などは注意が必要です。
lambdaの同時起動数が気になる場合にはlambdaの前段にkinesisを挟むつまり、AWS IoT -> kinesis streams -> Lambda とするとよいかと思います。
同じくcloudwatchのlimitも意識しておいたほうが良いでしょう。
また、カスタムメトリクスもメトリクス単位で少額ですが、課金が発生します。

免責

本投稿は、個人の意見で、所属する企業や団体は関係ありません。
また掲載しているsampleプログラムの動作に関しても保障いたしませんので、参考程度にしてください。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away