Skip to content

Commit deb86ca

Browse files
authored
feat: use DD_SERVICE for inferred spans when integration service names are removed (#814)
When DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED=true and DD_SERVICE is set, inferred (synthetic) event-source spans use the base service name instead of the AWS resource/instance representation. This gives users a single setting to consolidate every trigger span onto the function's service, rather than one DD_SERVICE_MAPPING entry per trigger type per function. An explicit DD_SERVICE_MAPPING entry still takes precedence, and default behavior is unchanged, so existing integration snapshots are unaffected. Mirrors the resolution order in datadog-lambda-python.
1 parent dabb8e7 commit deb86ca

2 files changed

Lines changed: 96 additions & 0 deletions

File tree

‎src/trace/span-inferrer.spec.ts‎

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,89 @@ describe("SpanInferrer", () => {
325325
});
326326
});
327327

328+
describe("when DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED is set to 'true'", () => {
329+
beforeEach(() => {
330+
process.env.DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED = "true";
331+
});
332+
333+
it("uses DD_SERVICE for SNS events", () => {
334+
const inferrer = new SpanInferrer(mockWrapper as unknown as TracerWrapper);
335+
inferrer.createInferredSpan(snsEvent, {} as any, {} as SpanContext);
336+
expect(getStartSpanServiceTag(1)).toBe("mock-lambda-service");
337+
});
338+
339+
it("uses DD_SERVICE for SQS events", () => {
340+
const inferrer = new SpanInferrer(mockWrapper as unknown as TracerWrapper);
341+
inferrer.createInferredSpan(sqsEvent, {} as any, {} as SpanContext);
342+
expect(getStartSpanServiceTag(1)).toBe("mock-lambda-service");
343+
});
344+
345+
it("uses DD_SERVICE for DDB events", () => {
346+
const inferrer = new SpanInferrer(mockWrapper as unknown as TracerWrapper);
347+
inferrer.createInferredSpan(ddbEvent, {} as any, {} as SpanContext);
348+
expect(getStartSpanServiceTag(1)).toBe("mock-lambda-service");
349+
});
350+
351+
it("uses DD_SERVICE for Kinesis events", () => {
352+
const inferrer = new SpanInferrer(mockWrapper as unknown as TracerWrapper);
353+
inferrer.createInferredSpan(kinesisEvent, {} as any, {} as SpanContext);
354+
expect(getStartSpanServiceTag(1)).toBe("mock-lambda-service");
355+
});
356+
357+
it("uses DD_SERVICE for EventBridge events", () => {
358+
const inferrer = new SpanInferrer(mockWrapper as unknown as TracerWrapper);
359+
inferrer.createInferredSpan(eventBridgeEvent, {} as any, {} as SpanContext);
360+
expect(getStartSpanServiceTag(1)).toBe("mock-lambda-service");
361+
});
362+
363+
it("uses DD_SERVICE for API Gateway events", () => {
364+
const inferrer = new SpanInferrer(mockWrapper as unknown as TracerWrapper);
365+
inferrer.createInferredSpan(apiGatewayV1, {} as any, {} as SpanContext);
366+
expect(getStartSpanServiceTag(1)).toBe("mock-lambda-service");
367+
});
368+
369+
it("uses DD_SERVICE for Lambda Function URL events", () => {
370+
const inferrer = new SpanInferrer(mockWrapper as unknown as TracerWrapper);
371+
inferrer.createInferredSpan(functionUrlEvent, {} as any, {} as SpanContext);
372+
expect(getStartSpanServiceTag(1)).toBe("mock-lambda-service");
373+
});
374+
375+
it("uses DD_SERVICE for S3 events", () => {
376+
const inferrer = new SpanInferrer(mockWrapper as unknown as TracerWrapper);
377+
inferrer.createInferredSpan(s3Event, {} as any, {} as SpanContext);
378+
expect(getStartSpanServiceTag(1)).toBe("mock-lambda-service");
379+
});
380+
381+
it("lets an explicit DD_SERVICE_MAPPING entry win over DD_SERVICE", () => {
382+
process.env.DD_SERVICE_MAPPING = "lambda_sqs:remapped-queue-service";
383+
const inferrer = new SpanInferrer(mockWrapper as unknown as TracerWrapper);
384+
inferrer.createInferredSpan(sqsEvent, {} as any, {} as SpanContext);
385+
expect(getStartSpanServiceTag(1)).toBe("remapped-queue-service");
386+
});
387+
388+
it("falls back to the AWS resource name when DD_SERVICE is unset", () => {
389+
delete process.env[DD_SERVICE_ENV_VAR];
390+
const inferrer = new SpanInferrer(mockWrapper as unknown as TracerWrapper);
391+
inferrer.createInferredSpan(sqsEvent, {} as any, {} as SpanContext);
392+
expect(getStartSpanServiceTag(1)).toBe("MyQueue");
393+
});
394+
395+
it("takes precedence over DD_TRACE_AWS_SERVICE_REPRESENTATION_ENABLED=false", () => {
396+
process.env.DD_TRACE_AWS_SERVICE_REPRESENTATION_ENABLED = "false";
397+
const inferrer = new SpanInferrer(mockWrapper as unknown as TracerWrapper);
398+
inferrer.createInferredSpan(sqsEvent, {} as any, {} as SpanContext);
399+
expect(getStartSpanServiceTag(1)).toBe("mock-lambda-service");
400+
});
401+
});
402+
403+
describe("when DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED is not set", () => {
404+
it("leaves the AWS resource name in place", () => {
405+
const inferrer = new SpanInferrer(mockWrapper as unknown as TracerWrapper);
406+
inferrer.createInferredSpan(sqsEvent, {} as any, {} as SpanContext);
407+
expect(getStartSpanServiceTag(1)).toBe("MyQueue");
408+
});
409+
});
410+
328411
it("extracts service name from event when service mapping has incorrect delimiters", () => {
329412
process.env.DD_SERVICE_MAPPING = "key1-value1,key2=value2";
330413
const inferrer = new SpanInferrer(mockWrapper as unknown as TracerWrapper);

‎src/trace/span-inferrer.ts‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ export class SpanInferrer {
8888
return mappedService;
8989
}
9090

91+
// When integration service names are removed, inferred (synthetic) spans use
92+
// the base service name (DD_SERVICE) instead of the AWS resource/instance
93+
// representation.
94+
const ddService = process.env[DD_SERVICE_ENV_VAR]?.trim();
95+
if (SpanInferrer.removeIntegrationServiceNamesEnabled() && ddService) {
96+
return ddService;
97+
}
98+
9199
if (
92100
process.env.DD_TRACE_AWS_SERVICE_REPRESENTATION_ENABLED === "false" ||
93101
process.env.DD_TRACE_AWS_SERVICE_REPRESENTATION_ENABLED === "0"
@@ -98,6 +106,11 @@ export class SpanInferrer {
98106
return extractedKey?.trim() ? extractedKey : fallback;
99107
}
100108

109+
private static removeIntegrationServiceNamesEnabled(): boolean {
110+
const value = process.env.DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED;
111+
return value === "true" || value === "1";
112+
}
113+
101114
createInferredSpanForApiGateway(
102115
event: any,
103116
context: Context | undefined,

0 commit comments

Comments
 (0)