文字列をCloudWatchLogsにPUTしてみた

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは。
くコ:彡がトレードマークの阿部です。

CloudWatch Logsを使うと、OSやアプリケーションログをAWSに転送する事が出来ます。
Linux、Windowsを問わずに利用可能です。

CloudWatch LogsでAmazonLinux上のApacheエラーログを監視する
AWS CloudWatch LogsでWindows OSのイベントログを収集する

ログファイルを介さずに文字列をPUTする事は出来ないのだろうか?と疑問に思いました。
というわけで、AWS CLIのput-log-eventsコマンドを使って、文字列をPUTしてみました。

ロググループの作成

AWSマネージメントコンソールからCloudWatchにアクセスし、左メニュー[ログ]を選択します。
アクション -> ロググループの作成で、ロググループを作成します。
ここでは、Testというロググループを作成しました。

1

1-2

ログストリームの作成

作成したロググループを選択し、ログストリームの作成を選択します。
ここでは、App1いうログストリームを作成しました。

2

ログイベントのPUT

put-log-eventsコマンドを使って、メッセージ「Hello CloudWatch」をPUTしてみます。
ロググループとログストリームは先ほど作成したものを指定します。タイムスタンプは、long型で記載します。
OutputにnextSequenceTokenが表示されます。

$ aws logs put-log-events --log-group-name "Test" --log-stream-name "App1" --log-events timestamp=1461997171845,message='Hello CloudWatch'
{
    "nextSequenceToken": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX436652582946"
}
$

ログストリームを確認すると、ログイベントが追加されている事がわかります。

3

今度は別のメッセージをPUTしてみます。
トークンが無効であるメッセージが表示され、失敗してしまいました。
ログイベントをPUTする場合、リクエストに1つ前のリクエストで表示されたトークン(nextSequenceToken)を含める必要があります。

$ aws logs put-log-events --log-group-name "Test" --log-stream-name "App1" --log-events timestamp=1461997617646,message='Message 2'

A client error (InvalidSequenceTokenException) occurred when calling the PutLogEvents operation: The given sequenceToken is invalid. The next expected sequenceToken is: 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX436652582946
$ 

初回のPUT時に表示されたトークンを指定して、PUTしてみます。
今度はPUT出来ました。

$ aws logs put-log-events --log-group-name "Test" --log-stream-name "App1" --log-events timestamp=1461997617646,message='Message 2' --sequence-token XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX436652582946
{
    "nextSequenceToken": "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY350958389282"
}
$

4

トークンの表示

2回目以降のPUTでは、put-log-eventsで表示されるトークンの指定が必要でした。
連続してPUTする場合は良いですが、1つ前のトークンを控えておくのは大変です。
describe-log-streamsコマンドを使えば、次のPUTに必要なトークンを表示する事が可能です。
uploadSequenceTokenに注目すると、前回のPUT時に表示されたnextSequenceTokenと同じ値である事がわかります。

$ aws logs describe-log-streams --log-group-name "Test"
{
    "logStreams": [
        {
            "firstEventTimestamp": 1461997171845,
            "lastEventTimestamp": 1461997617646,
            "creationTime": 1461996716218,
            "uploadSequenceToken": "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY350958389282",
            "logStreamName": "App1",
            "lastIngestionTime": 1461998112607,
            "arn": "arn:aws:logs:ap-northeast-1:aws-accountid:log-group:Test:log-stream:App1",
            "storedBytes": 0
        }
    ]
}
$

スクリプト

任意の文字列をPUTするスクリプトを作ってみました。

使い方

コードをput-log-events.shとして、保存して下さい。引数にPUTしたいメッセージを指定し、実行します。

$ ./put-log-events.sh "messages 3"
{
    "nextSequenceToken": "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ667119339554"
}
$

実行結果

5

コード

UploadSequenceTokenコマンドを実行しトークンを取得出来なかった場合、トークンを指定せずにPUTします。
トークンを取得できた場合、そのトークンを指定してPUTします。

#!/bin/bash

# リージョン
export AWS_DEFAULT_REGION=ap-northeast-1

# CloudWatchLogs設定
LogGroupName="Test"
LogStreamName="App1"

# CloudWatchLogsにPUTするメッセージ
Mess=$1

# コーテーションを取り除く
Mess=`echo $Mess | sed -e "s/'//g"`

# put-log-eventに利用するトークン
UploadSequenceToken=$(aws logs describe-log-streams --log-group-name "$LogGroupName" --query 'logStreams[?logStreamName==`'$LogStreamName'`].[uploadSequenceToken]' --output text)

# put-log-eventに利用するタイムスタンプ
TimeStamp=`date "+%s%N" --utc`
TimeStamp=`expr $TimeStamp / 1000000`

# put-log-eventsの実行
if [ "$UploadSequenceToken" != "None" ]
then
  # トークン有りの場合
  aws logs put-log-events --log-group-name "$LogGroupName" --log-stream-name "$LogStreamName" --log-events timestamp=$TimeStamp,message="$Mess" --sequence-token $UploadSequenceToken
else
  # トークン無しの場合(初回のput)
  aws logs put-log-events --log-group-name "$LogGroupName" --log-stream-name "$LogStreamName" --log-events timestamp=$TimeStamp,message="$Mess"
fi

おわりに

CloudWatch Logsに文字列をPUTしてみました。
上手く使えば、ローカルにログを持たずにすみそうですね。
では、またお会いしましょう。