Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions iopipe/contrib/eventinfo/event_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class EventType(object):
keys = []
exclude_keys = []
required_keys = []
source = None

def __init__(self, event):
self.event = event
Expand All @@ -21,10 +22,16 @@ def collect(self):
return collect_all_keys(self.event, '@iopipe/event-info.%s' % self.type, self.exclude_keys)
event_info = {}
for key in self.keys:
value = get_value(self.event, key)
if isinstance(key, tuple):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's changing that we need to check that these are tuples?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We map one key to another, so keys can now be a list of strings or a list of tuples. If it's a list of tuples, it's a map from old_key to new_key.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can keys now be of two different types? (List of strings or list of tuples)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we map serveless lambda proxy events into api gateway events. See the equivalent JS implementation here:
iopipe/iopipe-js-event-info@2033c3e

old_key, new_key = key
else:
old_key = new_key = key
value = get_value(self.event, old_key)
if value is not None:
event_info['@iopipe/event-info.%s.%s' % (self.type, key)] = value
event_info['@iopipe/event-info.%s.%s' % (self.type, new_key)] = value
event_info['@iopipe/event-info.eventType'] = self.type
if self.source:
event_info['@iopipe/event-info.eventType.source'] = self.source
return event_info


Expand Down Expand Up @@ -152,6 +159,25 @@ def has_required_keys(self):
return super(Scheduled, self).has_required_keys() and get_value(self.event, 'source') == 'aws.events'


class ServerlessLambda(EventType):
type = 'apiGateway'
source = 'slsIntegrationLambda'
keys = [
('headers.["X-Amz-Cf-Id"]', 'headers.X-Amz-Cf-Id'),
('headers.["X-Amzn-Trace-Id"]', 'headers.X-Amzn-Trace-Id'),
('identity.accountId', 'requestContext.accountId'),
('identity.userAgent', 'requestContext.identity.userAgent'),
('method', 'httpMethod'),
('method', 'requestContext.httpMethod'),
('stage', 'requestContext.stage'),
]
required_keys = [
'identity.userAgent',
'identity.sourceIp',
'identity.accountId',
]


class SNS(EventType):
type = 'sns'
keys = [
Expand All @@ -177,7 +203,7 @@ def has_required_keys(self):
get_value(self.event, 'Records[0].eventSource') == 'aws:sns'


EVENT_TYPES = [AlexaSkill, ApiGateway, CloudFront, Firehose, Kinesis, S3, Scheduled, SNS]
EVENT_TYPES = [AlexaSkill, ApiGateway, CloudFront, Firehose, Kinesis, S3, Scheduled, ServerlessLambda, SNS]


def metrics_for_event_type(event, context):
Expand Down
2 changes: 1 addition & 1 deletion iopipe/contrib/eventinfo/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

class EventInfoPlugin(Plugin):
name = 'event-info'
version = '1.1.0'
version = '1.2.0'
homepage = 'https://github.com/iopipe/iopipe-python#event-info-plugin'
enabled = True

Expand Down
5 changes: 5 additions & 0 deletions tests/contrib/eventinfo/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,8 @@ def event_kinesis():
@pytest.fixture
def event_scheduled():
return _load_event('scheduled')


@pytest.fixture
def event_serverless_lambda():
return _load_event('serverless_lambda')
47 changes: 47 additions & 0 deletions tests/contrib/eventinfo/events/serverless_lambda.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"body": {},
"method": "GET",
"principalId": "1234",
"stage": "dev",
"cognitoPoolClaims": {
"sub": ""
},
"enhancedAuthContext": {},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "en-GB,en-US;q=0.8,en;q=0.6,zh-CN;q=0.4",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "GB",
"Host": "ec5ycylws8.execute-api.us-east-1.amazonaws.com",
"upgrade-insecure-requests": "1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36",
"Via": "2.0 f165ce34daf8c0da182681179e863c24.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "l06CAg2QsrALeQcLAUSxGXbm8lgMoMIhR2AjKa4AiKuaVnnGsOFy5g==",
"X-Amzn-Trace-Id": "Root=1-5970ef3e249c0321b2eef14aa513ae",
"X-Forwarded-For": "94.117.120.169, 116.132.62.73",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
"query": {},
"path": {},
"identity": {
"cognitoIdentityPoolId": "",
"accountId": "1234",
"cognitoIdentityId": "",
"caller": "",
"apiKey": "",
"sourceIp": "94.197.120.169",
"accessKey": "",
"cognitoAuthenticationType": "",
"cognitoAuthenticationProvider": "",
"userArn": "",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36",
"user": ""
},
"stageVariables": {}
}
26 changes: 23 additions & 3 deletions tests/contrib/eventinfo/test_event_types.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from iopipe.contrib.eventinfo import event_types as et
from iopipe.contrib.eventinfo.util import get_value


def test__event_Types__alexa_skill(event_alexa_skill):
def test__event_types__alexa_skill(event_alexa_skill):
event = et.AlexaSkill(event_alexa_skill)
assert event.has_required_keys() is True

Expand All @@ -11,7 +12,7 @@ def test__event_Types__alexa_skill(event_alexa_skill):
assert len(list(event_info.keys())) == 31


def test__event_Types__apigw(event_apigw):
def test__event_types__apigw(event_apigw):
event = et.ApiGateway(event_apigw)
assert event.has_required_keys() is True

Expand All @@ -22,7 +23,7 @@ def test__event_Types__apigw(event_apigw):
assert list(event_info.keys()).sort() == expected_keys.sort()


def test__event_Types__cloudfront(event_cloudfront):
def test__event_types__cloudfront(event_cloudfront):
event = et.CloudFront(event_cloudfront)
assert event.has_required_keys() is True

Expand Down Expand Up @@ -53,3 +54,22 @@ def test__event_types__scheduled(event_scheduled):

expected_keys = ['@iopipe/event-info.eventType'] + ['@iopipe/event-info.scheduled.%s' % key for key in event.keys]
assert list(event_info.keys()).sort() == expected_keys.sort()


def test__event_types__serverless_lambda(event_serverless_lambda):
event = et.ServerlessLambda(event_serverless_lambda)
assert event.has_required_keys() is True

event_info = event.collect()
assert event_info != {}

expected_keys = [
'@iopipe/event-info.eventType',
'@iopipe/event-info.eventType.source',
] + ['@iopipe/event-info.apiGateway.%s' % key[1] for key in event.keys]
assert list(event_info.keys()).sort() == expected_keys.sort()
assert all([
get_value(event_serverless_lambda, old_key) == event_info['@iopipe/event-info.apiGateway.%s' % new_key]
for old_key, new_key in event.keys
])
assert event_info['@iopipe/event-info.eventType.source'] == event.source