AWS LambdaでJSON文字列を標準出力したときの各コンソール上での出力のされ方を整理してみた

こんにちは、CX事業本部の若槻です。

AWS Lambdaを実行した際の標準出力で、JSONなどの複数行の文字列を改行やインデントを保ったまま出力して結果を確認したい時があります。そこで標準出力の仕方により各コンソール(Lambda、CloudWatch Logs)上でjson文字列の出力がどのように変わるのか確認をして整理してみました。

確認してみる

  • 前提条件
    • ランタイム:Python3.7

パターン1:json.dumpsしてprintfする(indentオプション指定あり)

  • コード

辞書データを json.dumpsindentオプション指定あり)してprintfにより標準出力する場合。

import json

jsn = {
    "data": {
        "a": "abc",
        "b": "あいう",
        "c": 123
    }
}

def lambda_handler(event, context):
    jsn_str_indented = json.dumps(jsn, ensure_ascii=False, indent=2)
    print(jsn_str_indented)
  • Lambdaコンソール(Execution Result)上での出力

json形式(改行、インデント)が保たれたまま出力されました。

Function Logs:
START RequestId: 30f360de-bb86-4409-82a1-91928613f661 Version: $LATEST
{
  "data": {
    "a": "abc",
    "b": "あいう",
    "c": 123
  }
}
END RequestId: 30f360de-bb86-4409-82a1-91928613f661
  • CloudWatch Logsコンソール上での出力

改行ごとにログが分割されて出力されました。

image.png

パターン2:json.dumpsしてprintfする(indentオプション指定なし)

  • コード

辞書データを json.dumpsindentオプション指定なし)してprintfにより標準出力する場合。

import json

jsn = {
    "data": {
        "a": "abc",
        "b": "あいう",
        "c": 123
    }
}

def lambda_handler(event, context):
    jsn_str = json.dumps(jsn, ensure_ascii=False)
    print(jsn_str)
  • Lambdaコンソール(Execution Result)上での出力

json形式(改行、インデント)が保たれずに1行の文字列で出力されました。

Function Logs:
START RequestId: 24f26d42-cfdf-475e-825c-cd5c46a99e58 Version: $LATEST
{"data": {"a": "abc", "b": "あいう", "c": 123}}
END RequestId: 24f26d42-cfdf-475e-825c-cd5c46a99e58
  • CloudWatch Logsコンソール上での出力

単一のログの中でjson形式(改行、インデント)が保れたまま出力されました。

image.png

まとめ

上記の2パターンは、どのコンソール上で出力結果を確認するかによって使い分けることになりそうです。前提としてJSON文字列の標準出力はなるべくJSON形式のままで出力結果を確認したいです。

Lambdaを手動で実行(テストボタンによる実行)した時の出力を確認したい場合は、Lambdaコンソール上で出力結果を確認できるので、パターン1が利用できます。

逆に、別のトリガー(API Gatewayなど)から渡されたイベントデータを元にした処理結果を出力して確認したい場合は、Lambdaコンソール上で出力結果を確認できないので、パターン2を利用することになります。

覚えておくとAWS Lambdaでさっと検証をしたい時に役に立ちそうですね。

補足(loggingを利用した場合)

loggingを利用した場合の各コンソールへの出力のされ方も確認をしてみました。

結論としてはprintfと同様の出力のされ方となりました。

  • コード

辞書データを json.dumpsindentオプション指定あり、なしの両パターン)してlogger.infoにより標準出力するコードの場合。

import json
from logging import getLogger, INFO

logger = getLogger(__name__)
logger.setLevel(INFO)

jsn = {
    "data": {
        "a": "abc",
        "b": "あいう",
        "c": 123
    }
}

def lambda_handler(event, context):
    jsn_str_indented = json.dumps(jsn, ensure_ascii=False, indent=2)
    logger.info(jsn_str_indented)

    jsn_str = json.dumps(jsn, ensure_ascii=False)
    logger.info(jsn_str)
  • Lambdaコンソール(Execution Result)上での出力

printfと同様、indentオプション指定ありの場合は改行やインデントが保たれて出力され、指定なしの場合は保たれずに出力されました。

Function Logs:
START RequestId: e449bdfa-c5c2-4acd-aaf7-bf626405d1bf Version: $LATEST
[INFO]  2020-02-05T13:10:13.339Z    e449bdfa-c5c2-4acd-aaf7-bf626405d1bf    {
  "data": {
    "a": "abc",
    "b": "あいう",
    "c": 123
  }
}

[INFO]  2020-02-05T13:10:13.340Z    e449bdfa-c5c2-4acd-aaf7-bf626405d1bf    {"data": {"a": "abc", "b": "あいう", "c": 123}}

END RequestId: e449bdfa-c5c2-4acd-aaf7-bf626405d1bf
  • CloudWatch Logsコンソール上での出力

こちらもprintfと同様、indentオプション指定ありの出力(3〜8行目)は改行ごとにログが分割されて出力されました。

image.png

indentオプション指定なしの出力(9行目をクリックして開く)は単一のログの中でjson形式(改行、インデント)が保れたまま出力されました。image.png

参考