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

More than 1 year has 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プログラムの動作に関しても保障いたしませんので、参考程度にしてください。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.