@@ -33,6 +33,15 @@ jest.mock("./tracer-wrapper", () => {
3333 return mockExtract ( event ) ;
3434 }
3535
36+ startSpan ( name : any , options : any ) : any {
37+ return {
38+ toSpanId : ( ) => "mockSpanId" ,
39+ toTraceId : ( ) => "mockTraceId" ,
40+ finish : jest . fn ( ) ,
41+ setTag : jest . fn ( ) ,
42+ } ;
43+ }
44+
3645 injectSpan ( span : any ) : any {
3746 return {
3847 [ DATADOG_PARENT_ID_HEADER ] : span . toSpanId ( ) ,
@@ -304,6 +313,88 @@ describe("TraceListener", () => {
304313 ) ;
305314 } ) ;
306315
316+ it ( "wraps dd-trace span around invocation with Step Function context" , async ( ) => {
317+ const listener = new TraceListener ( defaultConfig ) ;
318+ mockTraceSource = TraceSource . Event ;
319+
320+ // Mock Step Function context with deterministic trace IDs
321+ mockSpanContext = {
322+ toTraceId : ( ) => "512d06a10e5e34cb" , // Hex converted to decimal would be different
323+ toSpanId : ( ) => "7069a031ef9ad2cc" ,
324+ _sampling : {
325+ priority : "1" ,
326+ } ,
327+ } ;
328+ mockSpanContextWrapper = {
329+ spanContext : mockSpanContext ,
330+ } ;
331+
332+ const stepFunctionSQSEvent = {
333+ Records : [
334+ {
335+ messageId : "4ead33f3-51c8-4094-87bd-5325dc143cbd" ,
336+ receiptHandle :
337+ "AQEBrGtLZCUS1POUEZtdZRoB0zXgT14OQC48A4Xk4Qbnv/v4d0ib5rFI1wEah823t2hE9haPm6nNN1aGsJmYkqa9Y8qaBQscp9f7HKJyybT5hpdKEn07fY0VRv/Of63u1RN1YdFdY5uhI8XGWRc4w7t62lQwMMFY5Ahy7XLVwnav81KRjGFdgxzITrtx3YKxmISNvXzPiiHNKb7jT+ClfXi91bEYHi3Od3ji5xGajAofgYrj2VBDULyohsfMkwlvAanD2wfj2x++wL5LSpFEtMFnvThzt7Dh5FEZChVMzWV+fRFpljivHX58ZeuGv4yIIjLVuuDGn5uAY5ES4CsdINrBAru6K5gDSPUajRzE3TktNgAq5Niqfky1x0srLRAJjTDdmZK8/CXU0sRT/MCT99vkCHa0bC17S/9au5bCbrB4k/T9J8W39AA6kIYhebkq3IQr" ,
338+ body : '{"testData":"Hello from Step Functions to SQS"}' ,
339+ attributes : {
340+ ApproximateReceiveCount : "1" ,
341+ SentTimestamp : "1752594520503" ,
342+ SenderId : "AROAWGCM4HXU73A4V34AJ:EcGTcmgJbwwOwXPbloVwgSaDOmwhYBLH" ,
343+ ApproximateFirstReceiveTimestamp : "1752594520516" ,
344+ } ,
345+ messageAttributes : {
346+ _datadog : {
347+ stringValue :
348+ '{"Execution":{"Id":"arn:aws:states:sa-east-1:123456123456:execution:rstrat-sfn-sqs-demo-dev-state-machine:a4912895-93a3-4803-a712-69fecb55c025","StartTime":"2025-07-15T15:48:40.302Z","Name":"a4912895-93a3-4803-a712-69fecb55c025","RoleArn":"arn:aws:iam::123456123456:role/rstrat-sfn-sqs-demo-dev-StepFunctionsExecutionRole-s6ozc2dVrvLH","RedriveCount":0},"StateMachine":{"Id":"arn:aws:states:sa-east-1:123456123456:stateMachine:rstrat-sfn-sqs-demo-dev-state-machine","Name":"rstrat-sfn-sqs-demo-dev-state-machine"},"State":{"Name":"SendToSQS","EnteredTime":"2025-07-15T15:48:40.333Z","RetryCount":0},"RootExecutionId":"arn:aws:states:sa-east-1:123456123456:execution:rstrat-sfn-sqs-demo-dev-state-machine:a4912895-93a3-4803-a712-69fecb55c025","serverless-version":"v1"}' ,
349+ stringListValues : [ ] ,
350+ binaryListValues : [ ] ,
351+ dataType : "String" ,
352+ } ,
353+ } ,
354+ md5OfMessageAttributes : "5469b8f90bb6ab27e95816c1fa178680" ,
355+ md5OfBody : "f0c0ddb2ed09a09e8791013f142e8d7e" ,
356+ eventSource : "aws:sqs" ,
357+ eventSourceARN : "arn:aws:sqs:sa-east-1:123456123456:rstrat-sfn-sqs-demo-dev-process-event-queue" ,
358+ awsRegion : "sa-east-1" ,
359+ } ,
360+ ] ,
361+ } ;
362+
363+ await listener . onStartInvocation ( stepFunctionSQSEvent , context as any ) ;
364+ const unwrappedFunc = ( ) => { } ;
365+ const wrappedFunc = listener . onWrap ( unwrappedFunc ) ;
366+ wrappedFunc ( ) ;
367+ await listener . onCompleteInvocation ( ) ;
368+
369+ expect ( mockWrap ) . toHaveBeenCalledWith (
370+ "aws.lambda" ,
371+ {
372+ resource : "my-Lambda" ,
373+ service : "my-Lambda" ,
374+ tags : {
375+ cold_start : true ,
376+ function_arn : "arn:aws:lambda:us-east-1:123456789101:function:my-lambda" ,
377+ function_version : "$LATEST" ,
378+ request_id : "1234" ,
379+ resource_names : "my-Lambda" ,
380+ functionname : "my-lambda" ,
381+ "_dd.parent_source" : "event" ,
382+ "function_trigger.event_source" : "sqs" ,
383+ "function_trigger.event_source_arn" :
384+ "arn:aws:sqs:sa-east-1:123456123456:rstrat-sfn-sqs-demo-dev-process-event-queue" ,
385+ datadog_lambda : datadogLambdaVersion ,
386+ dd_trace : ddtraceVersion ,
387+ } ,
388+ type : "serverless" ,
389+ childOf : expect . objectContaining ( {
390+ toSpanId : expect . any ( Function ) ,
391+ toTraceId : expect . any ( Function ) ,
392+ } ) ,
393+ } ,
394+ unwrappedFunc ,
395+ ) ;
396+ } ) ;
397+
307398 it ( "injects authorizer context if it exists" , async ( ) => {
308399 const listener = new TraceListener ( defaultConfig ) ;
309400 mockTraceSource = TraceSource . Event ;
0 commit comments