Lambda (Python) から指定のログストリームにログを書こうとして苦戦したのでメモ。

今日使い始めたばかりなので間違ってる点があるかもしれません。もし間違っていたら教えてくださいm(_ _)m

苦戦ポイント1 -put_log_events()の使い方-

結論から言って次のようにする必要があります。


      logs_client = boto3.client('logs')

      res = logs_client.describe_log_streams(
          logGroupName='(ロググループ名)',
          logStreamNamePrefix='(ログストリーム名)',
      )
      seq_token = res['logStreams'][0]['uploadSequenceToken']

      res = logs_client.put_log_events(
          logGroupName='(ロググループ名)',
          logStreamName='(ログストリーム名)',
          logEvents=[
              {
                  'timestamp': int(time.time()) * 1000,
                  'message': '%s backed up successfully' % (message)
              },
          ],
          sequenceToken=seq_token
      )

注意する点が2点ほどあります。

timestampの指定

まず1点目、timestampはUNIX時間に1000を掛けたものを整数で指定しましょう。つまり単位がミリ秒です。

sequenceToken

2点目、ログを書き出すput_log_events()にはsequenceTokenというパラメータが必要になります。 ログストリームへの初回の書き込みなら(多分)いらないのですが、2回目以降は必要になります。

上記コードではsequenceTokenをdescribe_log_streams()から取得していますが、put_log_events()のレスポンスの中にもありますのでそれを使ってもいいです。

苦戦ポイント2 -IAM ポリシー-

結論から言って次のようにする必要があります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
            ],
            "Resource": [
                "arn:aws:logs:*:*:/aws/lambda/(Lambda関数名☆ワイルドカード可☆)",
                "arn:aws:logs:*:*:log-group:(ロググループ名):log-stream:(ログストリーム名)"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "logs:DescribeLogStreams"
            ],
            "Resource": [
                "arn:aws:logs:*:*:*"
            ],
            "Effect": "Allow"
        }
    ]
}

ポリシーについて先に説明させていただきますと、最初のCreateLogGroup, CreateLogStream, PutLogEventsはCloudWatch Logsにログを書き出す(ログストリームの作成も)時に必要です。

最初のResource内の1つ目 ("arn:aws:logs:*:*:/aws/lambda/(Lambda関数名☆ワイルドカード可☆)")は、Lambdaからprint()やloggerを使った時、自動でCloudWatch Logsに送られるのでその時用です。

その上での注意する点はResourceの指定です。

Resource指定

最初のResource内の2つ目(arn:aws:logs:*:*:log-group:(ロググループ名):log-stream:(ログストリーム名))は今回の問題である特定のログストリームに書くときのArn指定です。 自分は最初間違えてarn:aws:logs:*:*:(ロググループ名)/(ログストリーム名)とかやってました。

前述のdescribe_log_streamsのためにlogs:DescribeLogStreamsをarn:aws:logs:::*に対して設定するのも忘れないでください。