Skip to content

Commit 7806d72

Browse files
authored
Enhance Synthetic Span Service Representation (#635)
* Update naming and corresponding tracer changes
1 parent 50d893a commit 7806d72

16 files changed

+726
-1023
lines changed

datadog_lambda/tracing.py

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# Copyright 2019 Datadog, Inc.
55
import logging
66
import os
7+
import re
78
import traceback
89
import ujson as json
910
from datetime import datetime, timezone
@@ -856,15 +857,31 @@ def create_service_mapping(val):
856857
return new_service_mapping
857858

858859

859-
def determine_service_name(service_mapping, specific_key, generic_key, default_value):
860-
service_name = service_mapping.get(specific_key)
861-
if service_name is None:
862-
service_name = service_mapping.get(generic_key, default_value)
863-
return service_name
860+
def determine_service_name(
861+
service_mapping, specific_key, generic_key, extracted_key, fallback=None
862+
):
863+
# Check for mapped service (specific key first, then generic key)
864+
mapped_service = service_mapping.get(specific_key) or service_mapping.get(
865+
generic_key
866+
)
867+
if mapped_service:
868+
return mapped_service
869+
870+
# Check if AWS service representation is disabled
871+
aws_service_representation = os.environ.get(
872+
"DD_TRACE_AWS_SERVICE_REPRESENTATION_ENABLED", ""
873+
).lower()
874+
if aws_service_representation in ("false", "0"):
875+
return fallback
876+
877+
# Use extracted_key if it exists and is not empty, otherwise use fallback
878+
return (
879+
extracted_key.strip() if extracted_key and extracted_key.strip() else fallback
880+
)
864881

865882

866883
# Initialization code
867-
service_mapping_str = os.getenv("DD_SERVICE_MAPPING", "")
884+
service_mapping_str = os.environ.get("DD_SERVICE_MAPPING", "")
868885
service_mapping = create_service_mapping(service_mapping_str)
869886

870887
_dd_origin = {"_dd.origin": "lambda"}
@@ -988,6 +1005,7 @@ def create_inferred_span_from_api_gateway_websocket_event(
9881005
"http.url": http_url,
9891006
"endpoint": endpoint,
9901007
"resource_names": endpoint,
1008+
"span.kind": "server",
9911009
"apiid": api_id,
9921010
"apiname": api_id,
9931011
"stage": request_context.get("stage"),
@@ -1046,6 +1064,7 @@ def create_inferred_span_from_api_gateway_event(
10461064
"endpoint": path,
10471065
"http.method": method,
10481066
"resource_names": resource,
1067+
"span.kind": "server",
10491068
"apiid": api_id,
10501069
"apiname": api_id,
10511070
"stage": request_context.get("stage"),
@@ -1150,12 +1169,13 @@ def create_inferred_span_from_sqs_event(event, context):
11501169
event_source_arn = event_record.get("eventSourceARN")
11511170
queue_name = event_source_arn.split(":")[-1]
11521171
service_name = determine_service_name(
1153-
service_mapping, queue_name, "lambda_sqs", "sqs"
1172+
service_mapping, queue_name, "lambda_sqs", queue_name, "sqs"
11541173
)
11551174
attrs = event_record.get("attributes") or {}
11561175
tags = {
11571176
"operation_name": "aws.sqs",
11581177
"resource_names": queue_name,
1178+
"span.kind": "server",
11591179
"queuename": queue_name,
11601180
"event_source_arn": event_source_arn,
11611181
"receipt_handle": event_record.get("receiptHandle"),
@@ -1217,11 +1237,12 @@ def create_inferred_span_from_sns_event(event, context):
12171237
topic_arn = sns_message.get("TopicArn")
12181238
topic_name = topic_arn.split(":")[-1]
12191239
service_name = determine_service_name(
1220-
service_mapping, topic_name, "lambda_sns", "sns"
1240+
service_mapping, topic_name, "lambda_sns", topic_name, "sns"
12211241
)
12221242
tags = {
12231243
"operation_name": "aws.sns",
12241244
"resource_names": topic_name,
1245+
"span.kind": "server",
12251246
"topicname": topic_name,
12261247
"topic_arn": topic_arn,
12271248
"message_id": sns_message.get("MessageId"),
@@ -1252,15 +1273,16 @@ def create_inferred_span_from_kinesis_event(event, context):
12521273
event_record = get_first_record(event)
12531274
event_source_arn = event_record.get("eventSourceARN")
12541275
event_id = event_record.get("eventID")
1255-
stream_name = event_source_arn.split(":")[-1]
1276+
stream_name = re.sub(r"^stream/", "", (event_source_arn or "").split(":")[-1])
12561277
shard_id = event_id.split(":")[0]
12571278
service_name = determine_service_name(
1258-
service_mapping, stream_name, "lambda_kinesis", "kinesis"
1279+
service_mapping, stream_name, "lambda_kinesis", stream_name, "kinesis"
12591280
)
12601281
kinesis = event_record.get("kinesis") or {}
12611282
tags = {
12621283
"operation_name": "aws.kinesis",
12631284
"resource_names": stream_name,
1285+
"span.kind": "server",
12641286
"streamname": stream_name,
12651287
"shardid": shard_id,
12661288
"event_source_arn": event_source_arn,
@@ -1287,12 +1309,13 @@ def create_inferred_span_from_dynamodb_event(event, context):
12871309
event_source_arn = event_record.get("eventSourceARN")
12881310
table_name = event_source_arn.split("/")[1]
12891311
service_name = determine_service_name(
1290-
service_mapping, table_name, "lambda_dynamodb", "dynamodb"
1312+
service_mapping, table_name, "lambda_dynamodb", table_name, "dynamodb"
12911313
)
12921314
dynamodb_message = event_record.get("dynamodb") or {}
12931315
tags = {
12941316
"operation_name": "aws.dynamodb",
12951317
"resource_names": table_name,
1318+
"span.kind": "server",
12961319
"tablename": table_name,
12971320
"event_source_arn": event_source_arn,
12981321
"event_id": event_record.get("eventID"),
@@ -1321,11 +1344,12 @@ def create_inferred_span_from_s3_event(event, context):
13211344
obj = s3.get("object") or {}
13221345
bucket_name = bucket.get("name")
13231346
service_name = determine_service_name(
1324-
service_mapping, bucket_name, "lambda_s3", "s3"
1347+
service_mapping, bucket_name, "lambda_s3", bucket_name, "s3"
13251348
)
13261349
tags = {
13271350
"operation_name": "aws.s3",
13281351
"resource_names": bucket_name,
1352+
"span.kind": "server",
13291353
"event_name": event_record.get("eventName"),
13301354
"bucketname": bucket_name,
13311355
"bucket_arn": bucket.get("arn"),
@@ -1351,11 +1375,12 @@ def create_inferred_span_from_s3_event(event, context):
13511375
def create_inferred_span_from_eventbridge_event(event, context):
13521376
source = event.get("source")
13531377
service_name = determine_service_name(
1354-
service_mapping, source, "lambda_eventbridge", "eventbridge"
1378+
service_mapping, source, "lambda_eventbridge", source, "eventbridge"
13551379
)
13561380
tags = {
13571381
"operation_name": "aws.eventbridge",
13581382
"resource_names": source,
1383+
"span.kind": "server",
13591384
"detail_type": event.get("detail-type"),
13601385
}
13611386
InferredSpanInfo.set_tags(
@@ -1429,9 +1454,21 @@ def create_function_execution_span(
14291454
tags["_dd.parent_source"] = trace_context_source
14301455
tags.update(trigger_tags)
14311456
tracer.set_tags(_dd_origin)
1457+
# Determine service name based on config and env var
1458+
if config.service:
1459+
service_name = config.service
1460+
else:
1461+
aws_service_representation = os.environ.get(
1462+
"DD_TRACE_AWS_SERVICE_REPRESENTATION_ENABLED", ""
1463+
).lower()
1464+
if aws_service_representation in ("false", "0"):
1465+
service_name = "aws.lambda"
1466+
else:
1467+
service_name = function_name if function_name else "aws.lambda"
1468+
14321469
span = tracer.trace(
14331470
"aws.lambda",
1434-
service="aws.lambda",
1471+
service=service_name,
14351472
resource=function_name,
14361473
span_type="serverless",
14371474
)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ classifiers = [
2828
python = ">=3.8.0,<4"
2929
datadog = ">=0.51.0,<1.0.0"
3030
wrapt = "^1.11.2"
31-
ddtrace = ">=3.10.2,<4"
31+
ddtrace = ">=3.11.0,<4"
3232
ujson = ">=5.9.0"
3333
botocore = { version = "^1.34.0", optional = true }
3434
requests = { version ="^2.22.0", optional = true }
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+
"kinesisSchemaVersion": "1.0",
6+
"partitionKey": "partitionkey",
7+
"sequenceNumber": "49624230154685806402418173680709770494154422022871973922",
8+
"data": "eyJmb28iOiAiYmFyIiwgIl9kYXRhZG9nIjogeyJ4LWRhdGFkb2ctdHJhY2UtaWQiOiAiNDk0ODM3NzMxNjM1NzI5MTQyMSIsICJ4LWRhdGFkb2ctcGFyZW50LWlkIjogIjI4NzYyNTMzODAwMTg2ODEwMjYiLCAieC1kYXRhZG9nLXNhbXBsaW5nLXByaW9yaXR5IjogIjEifX0=",
9+
"approximateArrivalTimestamp": 1643638425.163
10+
},
11+
"eventSource": "aws:kinesis",
12+
"eventVersion": "1.0",
13+
"eventID": "shardId-000000000002:49624230154685806402418173680709770494154422022871973922",
14+
"eventName": "aws:kinesis:record",
15+
"invokeIdentityArn": "arn:aws:iam::601427279990:role/inferred-spans-python-dev-eu-west-1-lambdaRole",
16+
"awsRegion": "eu-west-1",
17+
"eventSourceARN": "arn:aws:kinesis:eu-west-1:601427279990:stream/kinesisStream"
18+
}
19+
]
20+
}

0 commit comments

Comments
 (0)