41
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Lambda (Python) からのログ出力Tips

Last updated at Posted at 2018-05-19

標準の出力

AWS Lambda で logging モジュールを使用してログを使用する際、普通に以下のように出力すると、

import logging

logger = logging.getLogger()

def lambda_handler(event, context):
    logger.warn('MESSAGE')

以下のようなタブ区切りフォーマットで出力されます。

[WARNING]	2018-05-19T09:25:42.272Z	xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx	MESSAGE

WARNING はログレベル、その後は出力時刻(UTC)、リクエストID、メッセージ本文となっています。

ロガーのログレベルは、デフォルトでは標準通り WARNING に設定されています。

フォーマットを変更する

出力フォーマットを変更したい場合は、以下を元にします。

import logging

logger = logging.getLogger()

formatter = logging.Formatter(
  '[%(levelname)s]\t%(asctime)s.%(msecs)dZ\t%(aws_request_id)s\t%(message)s\n',
  '%Y-%m-%dT%H:%M:%S'
)
for handler in logger.handlers:
    handler.setFormatter(formatter)

上の Formatter のパラメータが標準のフォーマットに対応しているので、これを変更します。例えばファイル名・関数名・行番号も記録したい場合は

formatter = logging.Formatter(
  '[%(levelname)s]\t%(asctime)s.%(msecs)dZ\t%(aws_request_id)s\t%(filename)s\t%(funcName)s\t%(lineno)d\t%(message)s\n',
  '%Y-%m-%dT%H:%M:%S'
)

などとすれば良いでしょう。

なお、ハンドラ自体を自分で作成して入れ替えることは避けた方が無難です。はじめから設定されているハンドラには aws_request_id というLogRecord属性名でリクエストIDを出力するためのフィルタが追加されていますが、自分で作成したハンドラーにはこの機能が無いためです。

ログレベルを動的に変更する

コードの変更なしにログレベルを変更するには、以下のように、環境変数等の外部からレベル名を取得してロガーに設定するようにします。

import logging
import os

logger = logging.getLogger()

level_name = os.environ.get('LOG_LEVEL')
level = logging.getLevelName(level_name)
if not isinstance(level, int):
    level = logging.INFO # 未設定/設定ミス時のデフォルト
logger.setLevel(level)

上記の例の場合は、環境変数 LOG_LEVELDEBUG などの文字列を設定すれば、そのレベルでロギングが行われることになります。

文字列のレベル名から logger.DEBUG のような数値のログレベルを取得するには logging.getLevelName() が使用できます。

これは通常はログレベルの数値から文字列表現を取得するものですが、逆に文字列を指定すると数値に変換してくれる機能もあります。None や未対応の文字列を与えると 'Level None' のような文字列を返すため、戻り値が数値かどうかで、正しいログレベル文字列だったかどうかが判定できます。

ドキュメントに注意があるように、この機能は 3.4 から 3.4.2 未満のバージョンでのみ動作しませんが、バージョンが固定されているLambda環境では問題にならないでしょう。

また、Python 3.2 以上であれば logger.setLevel() のように直接 'INFO' のような文字列を渡すこともできますが、None や未対応の文字列を渡すと例外が発生するため、getLevelName() の方が安全と思われます。

41
36
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
41
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?