Skip to content

Commit e62c6b6

Browse files
committed
OTEL operation name update
1 parent 7637378 commit e62c6b6

1 file changed

Lines changed: 58 additions & 3 deletions

File tree

bottlecap/src/otlp/transform.rs

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ pub const KEY_DATADOG_STATS_COMPUTED: &str = "_dd.stats_computed";
5959

6060
// const SPAN_TYPE_GENERIC_DB: &str = "db";
6161

62+
// AWS Lambda OTEL instrumentation scope name
63+
const AWS_LAMBDA_INSTRUMENTATION_SCOPE: &str = "opentelemetry.instrumentation.aws_lambda";
64+
6265
lazy_static! {
6366
// TODO: add mappings
6467
static ref DB_SYSTEM_MAP: HashMap<String, String> = HashMap::new();
@@ -247,7 +250,7 @@ fn get_otel_operation_name_v1(
247250
}
248251

249252
#[allow(clippy::too_many_lines)]
250-
fn get_otel_operation_name_v2(otel_span: &OtelSpan) -> String {
253+
fn get_otel_operation_name_v2(otel_span: &OtelSpan, lib: &OtelInstrumentationScope) -> String {
251254
let operation_name =
252255
get_otel_attribute_value_as_string(&otel_span.attributes, "operation.name", false);
253256
if !operation_name.is_empty() {
@@ -257,6 +260,12 @@ fn get_otel_operation_name_v2(otel_span: &OtelSpan) -> String {
257260
let is_client = otel_span.kind() == SpanKind::Client;
258261
let is_server = otel_span.kind() == SpanKind::Server;
259262

263+
// AWS Lambda: Check if this is the root Lambda invocation span
264+
// Only applies to Server spans from the AWS Lambda OTEL instrumentation
265+
if is_server && lib.name == AWS_LAMBDA_INSTRUMENTATION_SCOPE {
266+
return "aws.lambda".to_string();
267+
}
268+
260269
// HTTP
261270
let method =
262271
get_otel_attribute_value_as_string(&otel_span.attributes, "http.request.method", false);
@@ -890,7 +899,7 @@ pub fn otel_span_to_dd_span(
890899
}
891900

892901
if otel_operation_and_resource_v2_enabled(config.clone()) {
893-
dd_span.name = get_otel_operation_name_v2(otel_span);
902+
dd_span.name = get_otel_operation_name_v2(otel_span, lib);
894903
} else {
895904
dd_span.name = get_otel_operation_name_v1(
896905
otel_span,
@@ -1321,6 +1330,52 @@ mod tests {
13211330
get_otel_operation_name_v1(&otel_span, &lib, false, &HashMap::new(), true),
13221331
"opentelemetry_instrumentation_aws_lambda.server"
13231332
);
1324-
assert_eq!(get_otel_operation_name_v2(&otel_span), "server.request");
1333+
// With a non-matching lib name, should return server.request
1334+
assert_eq!(get_otel_operation_name_v2(&otel_span, &lib), "server.request");
1335+
}
1336+
1337+
#[test]
1338+
fn test_otel_operation_name_aws_lambda() {
1339+
// Test that AWS Lambda OTEL instrumentation gets aws.lambda operation name
1340+
let otel_span = OtelSpan {
1341+
name: "handler.handler".to_string(),
1342+
kind: SpanKind::Server as i32,
1343+
..Default::default()
1344+
};
1345+
let aws_lambda_lib = OtelInstrumentationScope {
1346+
name: "opentelemetry.instrumentation.aws_lambda".to_string(),
1347+
version: "0.42b0".to_string(),
1348+
attributes: [].to_vec(),
1349+
dropped_attributes_count: 0,
1350+
};
1351+
1352+
// AWS Lambda Server span should return aws.lambda
1353+
assert_eq!(
1354+
get_otel_operation_name_v2(&otel_span, &aws_lambda_lib),
1355+
"aws.lambda"
1356+
);
1357+
1358+
// Non-server span from AWS Lambda instrumentation should NOT return aws.lambda
1359+
let internal_span = OtelSpan {
1360+
name: "my-function".to_string(),
1361+
kind: SpanKind::Internal as i32,
1362+
..Default::default()
1363+
};
1364+
assert_eq!(
1365+
get_otel_operation_name_v2(&internal_span, &aws_lambda_lib),
1366+
"SPAN_KIND_INTERNAL"
1367+
);
1368+
1369+
// Server span from different instrumentation should return server.request
1370+
let other_lib = OtelInstrumentationScope {
1371+
name: "handler".to_string(),
1372+
version: String::new(),
1373+
attributes: [].to_vec(),
1374+
dropped_attributes_count: 0,
1375+
};
1376+
assert_eq!(
1377+
get_otel_operation_name_v2(&otel_span, &other_lib),
1378+
"server.request"
1379+
);
13251380
}
13261381
}

0 commit comments

Comments
 (0)