LoginSignup
0
2

More than 1 year has passed since last update.

AWS Lambdaで独自にログを出力したい(標準のログを出したくない)

Posted at

問題

Lambda標準のログを抑止してCloudWatchLogsのコストを節約したい。けど、特定の場合にはログを出力したいといった問題を解決します。

Lambdaコード

早速ですが、このような関数を用意してlambda_handler内で使用します。
必要な権限(IAMポリシー)は後で解説します。標準のログを出さないようにするのも、IAMポリシーの定義で行います。

import boto3
import time
import datetime

logs_client = boto3.client('logs')
lgn = '/aws/lambda/PutLog'

def lambda_handler(event, context):
    put_log('test')
    put_log('テスト')

def put_log(message):

    # ロググループがない場合作成
    res = logs_client.describe_log_groups(
        logGroupNamePrefix=lgn
    )
    if not res['logGroups']:
        res = logs_client.create_log_group(
            logGroupName=lgn
        )

    # putするログストリームを取得
    lsn = datetime.datetime.now().strftime("%Y/%m/%d") + '[PutLog]'
    res = logs_client.describe_log_streams(
        logGroupName=lgn,
        logStreamNamePrefix=lsn,
    )

    # ログストリームがない場合作成し、取得
    if not res['logStreams']:
        res = logs_client.create_log_stream(
            logGroupName=lgn,
            logStreamName=lsn
        )
        res = logs_client.describe_log_streams(
            logGroupName=lgn,
            logStreamNamePrefix=lsn,
        )

    # シーケンストークンがある場合指定する
    if 'uploadSequenceToken' in res['logStreams'][0]:
        seq_token = res['logStreams'][0]['uploadSequenceToken']

        res = logs_client.put_log_events(
            logGroupName=lgn,
            logStreamName=lsn,
            logEvents=[
                {
                    'timestamp': int(time.time()) * 1000,
                    'message': message
                },
            ],
            sequenceToken=seq_token
        )
    # ない場合指定しない
    else:
        res = logs_client.put_log_events(
            logGroupName=lgn,
            logStreamName=lsn,
            logEvents=[
                {
                    'timestamp': int(time.time()) * 1000,
                    'message': message
                },
            ]
        )

コード解説

コードはこちらの記事を参考にしました。

Lambda標準のログと同じような感覚で使いたかったので、ロググループ作成とログストリーム作成を追加しました。これにより、あらかじめそれらを作成する必要がなくなります。
Lambda内の変数lgnでロググループ名の指定と、変数lsnでログストリーム名の指定をします。ここでは、ロググループ名は標準のログと同じ、ログストリーム名は日付+[PutLog]にしています。ログストリーム名を調整すれば、任意の単位でまとめることができると思います。

そして、少し理解が難しいのがシーケンストークンの指定です。参考記事でも触れられていますが、2回目以降同じログストリームに書き込むためには、シーケンストークンの指定が必要です。

IAMポリシー

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:DescribeLogGroups",
                "logs:DescribeLogStreams"
            ],
            "Resource": "arn:aws:logs:リージョン名:アカウントID:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:リージョン名:アカウントID:log-group:/aws/lambda/PutLog:log-stream:*[PutLog]"
            ]
        }
    ]
}

ポリシー解説

ポリシーの内容も前述の記事を参考にしています。リージョン名とアカウントIDは置き換えてください。

CreateLogStreamおよびPutLogEventsを独自に指定することで、標準のログが出力されるのを回避しています。
ここでは、関数内で指定している日付+[PutLog]に対応させるために*[PutLog]で、ワイルドカードの指定をしています。

実行結果

通常であればこのような文字列が付与されたログストリームが作成され、開始終了のログやprint等で指定した文字列が出力されます。前述のポリシーを定義することで、このような標準のログ出力を抑止します。
SnapCrab_NoName_2021-9-10_6-22-15_No-00.png

こちらがテスト結果です。print等の代わりに、作成したput_log関数で任意の文字列を指定します。
SnapCrab_NoName_2021-9-10_6-22-24_No-00.png

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2