Can I determine which AWS service triggered my Lambda function?
Asked Answered
Z

4

11

I have a Python Lambda function that can respond to both an IoT Button and Alexa skill.

Is there a way to read the event or context handed to the handler function to identify which service triggered the function (Alexa or IoT)?

Zugzwang answered 2/3, 2017 at 17:40 Comment(8)
I haven't worked with either Alexa or IoT, but I believe that the schemes of their event objects should be so different, that it would be hard to confuse one for the other (unless the event structure of one or both of them is completely under user's control and you deliberately make them indistinguishable, but in that case you just have to make them distinguishable by adding, for example, a eventSource field)Brewhouse
@Leon: I don't understand. How is this relevant?Zugzwang
See this question, which has an accepted answer that relies on the format of the event template.Fourfold
@KhalidT.: Wow, interesting. So I really need to basically see what fields are there and guess based on that: no field that simply identifies the service?Zugzwang
@KhalidT.: Unforutnaley, non of the event templates listed are for IoT or ASK.Zugzwang
Sadly, AWS still does not provide the event source as part of the event object itself. That's why I referenced that answer, which relies on guessing basically (yes, I know it's not pretty). Also, AWS documentation does not list a sample IoT or ASK event until now but you can print one to either; Console or CloudWatch using your lambda function.Fourfold
@KhalidT.: OK — I think that will work as an answer.Zugzwang
For example, if a s3 bucket changes triggered lambda, then the name of the bucket is available in event object as "event.Records[0].s3.bucket.name". Even the s3 key for object which triggered the event can be found under "event.Records[0].s3.object.key". Hence, there should be similar entries event object which points to service and its details that invoked the lambda. You can stringify the entire event object and log it so that you can watch it in cloudwatch and see what you have there.Trenna
Z
3

There is no way to reliably accomplish this. The closest you can get is to familiarize yourself with the contents of the various events generated by different services, and (hope to) identify a reliably unique key present in each of the series you are interested in that you can then check for in your code, e.g. with

if 'distinctKey' in event.keys():
    # ...

However this is hardly a reliable approach, since it requires that you

  1. examine every possible event structure generated by every potential service and
  2. successfully and confidently identify for each service of interest a key or set of keys that is always reliably present in the service's events and unique to them.
Zugzwang answered 4/3, 2017 at 17:36 Comment(0)
B
8

Was hoping this has been streamline by AWS by now, but sadly it isn't. There is no one single parameter you can check for to determine the type of event across all AWS services.

However, found this nice articulation online here

function getLambdaEventSource(event) {
if (event.Records && event.Records[0].cf) return 'isCloudfront';

if (event.configRuleId && event.configRuleName && event.configRuleArn) return 'isAwsConfig';

if (event.Records && (event.Records[0].eventSource === 'aws:codecommit')) return 'isCodeCommit';

if (event.authorizationToken === "incoming-client-token") return 'isApiGatewayAuthorizer';

if (event.StackId && event.RequestType && event.ResourceType) return 'isCloudFormation';

if (event.Records && (event.Records[0].eventSource === 'aws:ses')) return 'isSes';

if (event.pathParameters && event.pathParameters.proxy) return 'isApiGatewayAwsProxy';

if (event.source === 'aws.events') return 'isScheduledEvent';

if (event.awslogs && event.awslogs.data) return 'isCloudWatchLogs';

if (event.Records && (event.Records[0].EventSource === 'aws:sns')) return 'isSns';

if (event.Records && (event.Records[0].eventSource === 'aws:dynamodb')) return 'isDynamoDb';

if (event.records && event.records[0].approximateArrivalTimestamp) return 'isKinesisFirehose';

if (event.records && event.deliveryStreamArn && event.deliveryStreamArn.startsWith('arn:aws:kinesis:')) return 'isKinesisFirehose';

if (event.eventType === 'SyncTrigger' && event.identityId && event.identityPoolId) return 'isCognitoSyncTrigger';

if (event.Records && event.Records[0].eventSource === 'aws:kinesis') return 'isKinesis';

if (event.Records && event.Records[0].eventSource === 'aws:s3') return 'isS3';

if (event.operation && event.message) return 'isMobileBackend';

}
Brainchild answered 7/8, 2018 at 14:29 Comment(0)
Z
3

There is no way to reliably accomplish this. The closest you can get is to familiarize yourself with the contents of the various events generated by different services, and (hope to) identify a reliably unique key present in each of the series you are interested in that you can then check for in your code, e.g. with

if 'distinctKey' in event.keys():
    # ...

However this is hardly a reliable approach, since it requires that you

  1. examine every possible event structure generated by every potential service and
  2. successfully and confidently identify for each service of interest a key or set of keys that is always reliably present in the service's events and unique to them.
Zugzwang answered 4/3, 2017 at 17:36 Comment(0)
A
1

For Python Dev: You can check this out https://gist.github.com/Necromancerx/abed07138690d37d170a6cf15b40d749.

def get_lambda_event_source(self, event: dict):
    if 'pathParameters' in event and 'proxy' in event['pathParameters']:
        return 'api_gateway_aws_proxy'
    elif 'Records' in event and len(event['Records']) > 0 and 'eventSource' in event['Records'][0] and event['Records'][0]['eventSource'] == 'aws:s3':
        return 's3'
    elif 'Records' in event and len(event['Records']) > 0 and 'EventSource' in event['Records'][0] and event['Records'][0]['EventSource'] == 'aws:sns':
        return 'sns'
    elif 'Records' in event and len(event['Records']) > 0 and 'eventSource' in event['Records'][0] and event['Records'][0]['eventSource'] == 'aws:dynamodb':
        return 'dynamo_db'
    elif 'Records' in event and len(event['Records']) > 0 and 'cf' in event['Records'][0]:
        return 'cloudfront'
    elif 'source' in event and event['source'] == 'aws.events':
        return 'scheduled_event'
    elif 'awslogs' in event and 'data' in event['awslogs']:
        return 'cloud_watch_logs'
    elif 'authorizationToken' in event and event['authorizationToken'] == "incoming-client-token":
        return 'api_gateway_authorizer'
    elif 'configRuleId' in event and 'configRuleName' in event and 'configRuleArn' in event:
        return 'aws_config'
    elif 'StackId' in event and 'RequestType' in event and 'ResourceType' in event:
        return 'cloud_formation'
    elif 'Records' in event and len(event['Records']) > 0 and 'eventSource' in event['Records'][0] and event['Records'][0]['eventSource'] == 'aws:codecommit':
        return 'code_commit'
    elif 'Records' in event and len(event['Records']) > 0 and 'eventSource' in event['Records'][0] and event['Records'][0]['eventSource'] == 'aws:ses':
        return 'ses'
    elif 'Records' in event and len(event['Records']) > 0 and 'eventSource' in event['Records'][0] and event['Records'][0]['eventSource'] == 'aws:kinesis':
        return 'kinesis'
    elif 'records' in event and len(event['Records']) > 0 and 'approximateArrivalTimestamp' in event['records'][0]:
        return 'kinesis_firehose'
    elif 'records' in event and len(event['Records']) > 0 and 'deliveryStreamArn' in event and event['deliveryStreamArn'] is str and event['deliveryStreamArn'].startswith('arn:aws:kinesis:'):
        return 'kinesis_firehose'
    elif 'eventType' in event and event['eventType'] == 'SyncTrigger' and 'identityId' in event and 'identityPoolId' in event:
        return 'cognito_sync_trigger'
    elif 'operation' in event and 'message' in event:
        return 'is_mobile_backend'

Based on this javascript gist https://gist.github.com/jeshan/52cb021fd20d871c56ad5ce6d2654d7b

Acephalous answered 7/5, 2020 at 21:11 Comment(0)
N
-1

You can read and Log the event in the Cloudwatch like below

import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def my_logging_handler(event, context):
logger.info('got event{}'.format(event))

This will log the event data in cloud watch you see and determine which event which triggered the lambda

Nigh answered 2/3, 2017 at 19:14 Comment(2)
The question is what part of event or context, which I have access to, I can use to determine what derive (IoT or ASK) invoked the function. Or, if (and only if) that's not possible, how I examine some other source (like the logs, perhaps) to do so.Zugzwang
This doesn't really provide an answer to the question, but it does show you how to debug this to discover an answer yourself.Hussey

© 2022 - 2024 — McMap. All rights reserved.