LoginSignup
0
0

More than 1 year has passed since last update.

Amazon EventBridge Pipes の Enrichment(強化) の AWS Lambda 関数の仕様

Posted at

結論

  • 入力
    • Lambda 関数の第一引数 event は、各サービスからのpayloadが "配列" で引き渡される。
  • 出力
    • return ... で返した内容が、EventBridge Pipes のターゲットに引き渡される。

解説

何もしない = ソースもしくはフィルタから event を受け取って、何もせずにターゲットへ event を引き渡す Lambda 関数を基に解説します。

lambda_function.py
def lambda_handler(event, context):
    print(event)
    return event
index.mjs
export const handler = async (event, context) => {
    console.log(event);
    return event;
};

入力

Lambda 関数の第一引数 event には、ソースもしくはフィルタからのpayloadが引き渡されます。第二引数 context も使用可能です。

例えば Amazon SQS をソースに設定し、MessageBody を {"v":1} としたデータをSQSキューに入れると print(event) の結果は以下のようになります。

[
    {
        'messageId': '8c8b72a2-85f0-47be-bf9f-81edff5197e9',
        'receiptHandle': '.....',
        'body': '{"v":1}',
        'attributes': {
            'ApproximateReceiveCount': '1',
            'SentTimestamp': '1672477371472',
            'SenderId': 'AID................KM',
            'ApproximateFirstReceiveTimestamp': '1672477371473'
        },
        'messageAttributes': {},
        'md5OfMessageAttributes': None,
        'md5OfBody': '455c0c10d425837001a72a84239ac362',
        'eventSource': 'aws:sqs',
        'eventSourceARN': 'arn:aws:sqs:REGION:............:SQS_NAME',
        'awsRegion': 'REGION'
    }
]

payloadはソースのサービスで異なりますが、EventBridge Pipes のターゲットにおける「サンプルイベント/イベントペイロード」で確認できるものとほぼ同じです。

"ほぼ" と表現した理由は event には配列として渡されるからです。よって Lambda 関数内での参照は、例えば messageId であれば event[0]['messageId'] として参照することになります。

lambda_function.py
def lambda_handler(event, context):
    print(event)
    print(event[0]['messageId'])
    return event

event は配列であるため、複数のpayloadが引き渡されそうな気もしますが、今のところ複数payloadが入ってくる様子はありませんでした。例えばSQSに send-message-batch で3つのデータを一度にキューへ入れても、3回個別にEnrichmentに指定された Lambda 関数が実行されました。

出力

return ... で返した内容が、EventBridge Pipes のターゲットに引き渡されます。
そして "空" を return すると、ターゲットは実行されません。空とは {} [] "" になります。

以下のコードは、ターゲットを一切実行しない Lambda 関数です。

lambda_function.py
def lambda_handler(event, context):
    return {}

以下のコードは、どのような入力があったとしても、ターゲットに {"foo": "bar"} を引き渡す Lambda 関数です。

lambda_function.py
def lambda_handler(event, context):
    return {'foo': 'bar'}

Implicit body data parsing の適用有無

Enrichment によるデータ処理をする場合、1点注意があるとすれば、Implicit body data parsing(暗黙のbody変換)です。
Enrichment を使わない場合はImplicit body data parsingが適用され、ターゲット側での入力トランスフォーマーで <$.body.foo> といった形で参照できるようになりますが、Enrichment を使った場合はImplicit body data parsingは適用されません。
そのため Enrichment を使う場合は、入力トランスフォーマーがシンプルになるように、Enrichment の Lambda 関数内でフォーマットしきってからターゲットに引き渡す設計が良いでしょう。

私が考える Enrichment に指定する Lambda 関数の実装

ターゲットの入力トランスフォーマーを使わない、もしくはシンプルな指定にするためには、Enrichment に指定する Lambda 関数で出力フォーマットを確定させることになります。
アプローチとしては2つ考えられますが、私としては後者の「eventに付加する」実装が、デバックや今後のアップデートに追従できるのではないかと考えています。
※ "enrichment" という単語の趣旨にもあってそうですし。

例えば、Slack の chat.postMessage への送信フォーマットは channeltext の二つを送ることになりますが、以下のような形です。

アプローチ1「完全に書き換える」

lambda_function.py
def lambda_handler(event, context):
    payload = {
        'channel': 'XXX',
        'text': event[0]['body']
    }
    return payload
# => {
#  'channel': 'XXX',
#  'text': "STRING...."
#}

ターゲットの入力トランスフォーマーには、何も指定しない。 (出力自体が Slack に合っている)

アプローチ2「eventに付加する」

lambda_function.py
def lambda_handler(event, context):
    event[0]['_enrichment'] = {
        'slack': {
            'channel': 'XXX',
            'text': event[0]['body']
        }
    }
    return event[0]
# => {
#  (元々のevent),
#  '_enrichment': {
#    'slack': {
#      'channel': 'XXX',
#      'text': 'text'
#     }
#  }
#}
ターゲットの入力トランスフォーマー
{
  "channel": <$._enrichment.slack.channel>,
  "text": <$._enrichment.slack.text>
}

まとめ

Amazon EventBridge Pipes は、ターゲットにも AWS Lambda を指定できるため、わざわざ Enrichment で Lambda 関数で処理する理由が見当たらないという意見もありそうです。

私の好きな本「UNIX という考え方」には "一つのプログラムには一つの事をうまくやらせる" という定理が紹介されています。
ターゲットには AWS サービスだけでなく外部 API をコールする機能が備わっています。その実装を Lambda 関数内から追い出し「payload変換に集中する」という意味では、Enrichment に指定する Lambda 関数はシンプルにできるメリットがあるでしょう。

EoT

0
0
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
0