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)?

orome
  • 45,163
  • 57
  • 202
  • 418
  • 1
    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) – Leon Mar 02 '17 at 18:17
  • @Leon: I don't understand. How is this relevant? – orome Mar 02 '17 at 18:50
  • 2
    See [this](http://stackoverflow.com/questions/41814750/how-to-know-event-souce-of-lambda-function-in-itself) question, which has an accepted answer that relies on the format of the [event template](http://docs.aws.amazon.com/lambda/latest/dg/eventsources.html#eventsources-ses-email-receiving). – Khalid T. Mar 02 '17 at 21:06
  • @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? – orome Mar 02 '17 at 21:10
  • @KhalidT.: Unforutnaley, non of the event templates listed are for IoT or ASK. – orome Mar 02 '17 at 21:12
  • 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. – Khalid T. Mar 02 '17 at 21:41
  • @KhalidT.: OK — I think that will work as an answer. – orome Mar 02 '17 at 21:44
  • 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. – bibek shrestha Mar 18 '17 at 17:29

4 Answers4

7

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';

}
Kdroid
  • 135
  • 1
  • 10
2

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.
orome
  • 45,163
  • 57
  • 202
  • 418
0

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

John Paulo Rodriguez
  • 1,280
  • 18
  • 21
-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

Mark B
  • 183,023
  • 24
  • 297
  • 295
Dhanesh H S
  • 186
  • 2
  • 13
  • 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. – orome Mar 02 '17 at 19:22
  • This doesn't really provide an answer to the question, but it does show you how to debug this to discover an answer yourself. – Mark B Mar 03 '17 at 02:27