Skip to content

Commit 74b3fcb

Browse files
authored
[SLS-1671] Inferred Spans for Kineses, EventBridge, S3, DynamoDB (#191)
* Add kinesis inferred span * Add dynamodb inferred span * Add s3 inferred span * Add eventbridge custom event inferred span * Comment out flaky units tests (TODO) * Add integration tests * Remove log line
1 parent 21f3e33 commit 74b3fcb

File tree

48 files changed

+946
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+946
-0
lines changed

datadog_lambda/tracing.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,18 @@ def create_inferred_span(event, context):
412412
elif event_source.equals(EventTypes.SNS):
413413
logger.debug("SNS event detected. Inferring a span")
414414
return create_inferred_span_from_sns_event(event, context)
415+
elif event_source.equals(EventTypes.KINESIS):
416+
logger.debug("Kinesis event detected. Inferring a span")
417+
return create_inferred_span_from_kinesis_event(event, context)
418+
elif event_source.equals(EventTypes.DYNAMODB):
419+
logger.debug("Dynamodb event detected. Inferring a span")
420+
return create_inferred_span_from_dynamodb_event(event, context)
421+
elif event_source.equals(EventTypes.S3):
422+
logger.debug("S3 event detected. Inferring a span")
423+
return create_inferred_span_from_s3_event(event, context)
424+
elif event_source.equals(EventTypes.EVENTBRIDGE):
425+
logger.debug("Eventbridge event detected. Inferring a span")
426+
return create_inferred_span_from_eventbridge_event(event, context)
415427

416428
except Exception as e:
417429
logger.debug(
@@ -549,6 +561,101 @@ def create_inferred_span_from_sns_event(event, context):
549561
return span
550562

551563

564+
def create_inferred_span_from_kinesis_event(event, context):
565+
event_record = get_first_record(event)
566+
stream_name = event_record["eventSourceARN"].split(":")[-1]
567+
tags = {
568+
"operation_name": "aws.kinesis",
569+
"service.name": "kinesis",
570+
"resource_names": stream_name,
571+
SPAN_TYPE_TAG: SPAN_TYPE_INFERRED,
572+
}
573+
request_time_epoch = event_record["kinesis"]["approximateArrivalTimestamp"]
574+
575+
args = {
576+
"resource": stream_name,
577+
"span_type": "web",
578+
}
579+
tracer.set_tags({"_dd.origin": "lambda"})
580+
span = tracer.trace("aws.kinesis", **args)
581+
if span:
582+
span.set_tags(tags)
583+
span.start = int(request_time_epoch)
584+
return span
585+
586+
587+
def create_inferred_span_from_dynamodb_event(event, context):
588+
event_record = get_first_record(event)
589+
table_name = event_record["eventSourceARN"].split("/")[1]
590+
tags = {
591+
"operation_name": "aws.dynamodb",
592+
"service.name": "dynamodb",
593+
"resource_names": table_name,
594+
SPAN_TYPE_TAG: SPAN_TYPE_INFERRED,
595+
}
596+
request_time_epoch = event_record["dynamodb"]["ApproximateCreationDateTime"]
597+
598+
args = {
599+
"resource": table_name,
600+
"span_type": "web",
601+
}
602+
tracer.set_tags({"_dd.origin": "lambda"})
603+
span = tracer.trace("aws.dynamodb", **args)
604+
if span:
605+
span.set_tags(tags)
606+
span.start = int(request_time_epoch)
607+
return span
608+
609+
610+
def create_inferred_span_from_s3_event(event, context):
611+
event_record = get_first_record(event)
612+
bucket_name = event_record["s3"]["bucket"]["name"]
613+
tags = {
614+
"operation_name": "aws.s3",
615+
"service.name": "s3",
616+
"resource_names": bucket_name,
617+
SPAN_TYPE_TAG: SPAN_TYPE_INFERRED,
618+
}
619+
dt_format = "%Y-%m-%dT%H:%M:%S.%fZ"
620+
timestamp = event_record["eventTime"]
621+
request_time_epoch = datetime.strptime(timestamp, dt_format)
622+
623+
args = {
624+
"resource": bucket_name,
625+
"span_type": "web",
626+
}
627+
tracer.set_tags({"_dd.origin": "lambda"})
628+
span = tracer.trace("aws.s3", **args)
629+
if span:
630+
span.set_tags(tags)
631+
span.start = int(request_time_epoch.strftime("%s"))
632+
return span
633+
634+
635+
def create_inferred_span_from_eventbridge_event(event, context):
636+
source = event["source"]
637+
tags = {
638+
"operation_name": "aws.eventbridge",
639+
"service.name": "eventbridge",
640+
"resource_names": source,
641+
SPAN_TYPE_TAG: SPAN_TYPE_INFERRED,
642+
}
643+
dt_format = "%Y-%m-%dT%H:%M:%SZ"
644+
timestamp = event["time"]
645+
request_time_epoch = datetime.strptime(timestamp, dt_format)
646+
647+
args = {
648+
"resource": source,
649+
"span_type": "web",
650+
}
651+
tracer.set_tags({"_dd.origin": "lambda"})
652+
span = tracer.trace("aws.eventbridge", **args)
653+
if span:
654+
span.set_tags(tags)
655+
span.start = int(request_time_epoch.strftime("%s"))
656+
return span
657+
658+
552659
def create_function_execution_span(
553660
context,
554661
function_name,

datadog_lambda/trigger.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class EventTypes(_stringTypedEnum):
3838
S3 = "s3"
3939
SNS = "sns"
4040
SQS = "sqs"
41+
EVENTBRIDGE = "eventbridge"
4142

4243

4344
class EventSubtypes(_stringTypedEnum):
@@ -128,6 +129,9 @@ def parse_event_source(event: dict) -> _EventSource:
128129
if event.get("awslogs"):
129130
event_source = _EventSource(EventTypes.CLOUDWATCH_LOGS)
130131

132+
if event.get("detail-type"):
133+
event_source = _EventSource(EventTypes.EVENTBRIDGE)
134+
131135
event_detail = event.get("detail")
132136
cw_event_categories = event_detail and event_detail.get("EventCategories")
133137
if event.get("source") == "aws.events" or cw_event_categories:
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"version": "0",
3+
"id": "fd03f394-e769-eff5-08a8-53c228933591",
4+
"detail-type": "testdetail",
5+
"source": "eventbridge.custom.event.sender",
6+
"account": "601427279990",
7+
"time": "2021-11-04T01:37:45Z",
8+
"region": "sa-east-1",
9+
"resources": [],
10+
"detail": {
11+
"foo": "bar"
12+
}
13+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
{
2+
"Records": [
3+
{
4+
"eventID": "c4ca4238a0b923820dcc509a6f75849b",
5+
"eventName": "INSERT",
6+
"eventVersion": "1.1",
7+
"eventSource": "aws:dynamodb",
8+
"awsRegion": "us-east-1",
9+
"dynamodb": {
10+
"Keys": {
11+
"Id": {
12+
"N": "101"
13+
}
14+
},
15+
"NewImage": {
16+
"Message": {
17+
"S": "New item!"
18+
},
19+
"Id": {
20+
"N": "101"
21+
}
22+
},
23+
"ApproximateCreationDateTime": 1428537600,
24+
"SequenceNumber": "4421584500000000017450439091",
25+
"SizeBytes": 26,
26+
"StreamViewType": "NEW_AND_OLD_IMAGES"
27+
},
28+
"eventSourceARN": "arn:aws:dynamodb:us-east-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899"
29+
},
30+
{
31+
"eventID": "c81e728d9d4c2f636f067f89cc14862c",
32+
"eventName": "MODIFY",
33+
"eventVersion": "1.1",
34+
"eventSource": "aws:dynamodb",
35+
"awsRegion": "us-east-1",
36+
"dynamodb": {
37+
"Keys": {
38+
"Id": {
39+
"N": "101"
40+
}
41+
},
42+
"NewImage": {
43+
"Message": {
44+
"S": "This item has changed"
45+
},
46+
"Id": {
47+
"N": "101"
48+
}
49+
},
50+
"OldImage": {
51+
"Message": {
52+
"S": "New item!"
53+
},
54+
"Id": {
55+
"N": "101"
56+
}
57+
},
58+
"ApproximateCreationDateTime": 1428537600,
59+
"SequenceNumber": "4421584500000000017450439092",
60+
"SizeBytes": 59,
61+
"StreamViewType": "NEW_AND_OLD_IMAGES"
62+
},
63+
"eventSourceARN": "arn:aws:dynamodb:us-east-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899"
64+
},
65+
{
66+
"eventID": "eccbc87e4b5ce2fe28308fd9f2a7baf3",
67+
"eventName": "REMOVE",
68+
"eventVersion": "1.1",
69+
"eventSource": "aws:dynamodb",
70+
"awsRegion": "us-east-1",
71+
"dynamodb": {
72+
"Keys": {
73+
"Id": {
74+
"N": "101"
75+
}
76+
},
77+
"OldImage": {
78+
"Message": {
79+
"S": "This item has changed"
80+
},
81+
"Id": {
82+
"N": "101"
83+
}
84+
},
85+
"ApproximateCreationDateTime": 1428537600,
86+
"SequenceNumber": "4421584500000000017450439093",
87+
"SizeBytes": 38,
88+
"StreamViewType": "NEW_AND_OLD_IMAGES"
89+
},
90+
"eventSourceARN": "arn:aws:dynamodb:us-east-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899"
91+
}
92+
]
93+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"version": "0",
3+
"id": "fd03f394-e769-eff5-08a8-53c228933591",
4+
"detail-type": "testdetail",
5+
"source": "eventbridge.custom.event.sender",
6+
"account": "601427279990",
7+
"time": "2021-11-04T01:37:45Z",
8+
"region": "sa-east-1",
9+
"resources": [],
10+
"detail": {
11+
"foo": "bar"
12+
}
13+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"Records": [
3+
{
4+
"kinesis": {
5+
"partitionKey": "partitionKey-03",
6+
"kinesisSchemaVersion": "1.0",
7+
"data": "SGVsbG8sIHRoaXMgaXMgYSB0ZXN0IDEyMy4=",
8+
"sequenceNumber": "49545115243490985018280067714973144582180062593244200961",
9+
"approximateArrivalTimestamp": 1428537600
10+
},
11+
"eventSource": "aws:kinesis",
12+
"eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200961",
13+
"invokeIdentityArn": "arn:aws:iam::EXAMPLE",
14+
"eventVersion": "1.0",
15+
"eventName": "aws:kinesis:record",
16+
"eventSourceARN": "arn:aws:kinesis:EXAMPLE",
17+
"awsRegion": "us-east-1"
18+
}
19+
]
20+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"Records": [
3+
{
4+
"eventVersion": "2.0",
5+
"eventSource": "aws:s3",
6+
"awsRegion": "us-east-1",
7+
"eventTime": "1970-01-01T00:00:00.000Z",
8+
"eventName": "ObjectCreated:Put",
9+
"userIdentity": {
10+
"principalId": "EXAMPLE"
11+
},
12+
"requestParameters": {
13+
"sourceIPAddress": "127.0.0.1"
14+
},
15+
"responseElements": {
16+
"x-amz-request-id": "EXAMPLE123456789",
17+
"x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
18+
},
19+
"s3": {
20+
"s3SchemaVersion": "1.0",
21+
"configurationId": "testConfigRule",
22+
"bucket": {
23+
"name": "example-bucket",
24+
"ownerIdentity": {
25+
"principalId": "EXAMPLE"
26+
},
27+
"arn": "arn:aws:s3:::example-bucket"
28+
},
29+
"object": {
30+
"key": "test/key",
31+
"size": 1024,
32+
"eTag": "0123456789abcdef0123456789abcdef",
33+
"sequencer": "0A1B2C3D4E5F678901"
34+
}
35+
}
36+
}
37+
]
38+
}

0 commit comments

Comments
 (0)