11import { randomBytes } from "crypto" ;
22import { logDebug } from "../utils" ;
33import { SampleMode , TraceContext , TraceSource } from "./trace-context-service" ;
4- import BigNumber from "bignumber.js" ;
54import { Socket , createSocket } from "dgram" ;
65import { SpanContextWrapper } from "./span-context-wrapper" ;
76import { StepFunctionContext } from "./step-function-service" ;
7+ import {
8+ DATADOG_TRACE_ID_HEADER ,
9+ DATADOG_PARENT_ID_HEADER ,
10+ DATADOG_SAMPLING_PRIORITY_HEADER ,
11+ DatadogTraceHeaders ,
12+ } from "./context/extractor" ;
813
914const AMZN_TRACE_ID_ENV_VAR = "_X_AMZN_TRACE_ID" ;
1015const AWS_XRAY_DAEMON_ADDRESS_ENV_VAR = "AWS_XRAY_DAEMON_ADDRESS" ;
@@ -70,16 +75,8 @@ export class XrayService {
7075 } ) ;
7176 }
7277
73- private parseTraceContextHeader ( ) : XrayTraceHeader | undefined {
74- const header = process . env [ AMZN_TRACE_ID_ENV_VAR ] ;
75- if ( header === undefined ) {
76- logDebug ( "Couldn't read Xray trace header from env" ) ;
77- return ;
78- }
79-
80- // Example: Root=1-5e272390-8c398be037738dc042009320;Parent=94ae789b969f1cc5;Sampled=1
81- logDebug ( `Reading Xray trace context from env var ${ header } ` ) ;
82- const [ root , parent , _sampled ] = header . split ( ";" ) ;
78+ public static parseAWSTraceHeader ( awsTraceHeader : string ) : XrayTraceHeader | undefined {
79+ const [ root , parent , _sampled ] = awsTraceHeader . split ( ";" ) ;
8380 if ( parent === undefined || _sampled === undefined ) return ;
8481
8582 const [ , traceId ] = root . split ( "=" ) ;
@@ -94,6 +91,18 @@ export class XrayService {
9491 } ;
9592 }
9693
94+ private parseTraceContextHeader ( ) : XrayTraceHeader | undefined {
95+ const header = process . env [ AMZN_TRACE_ID_ENV_VAR ] ;
96+ if ( header === undefined ) {
97+ logDebug ( "Couldn't read Xray trace header from env" ) ;
98+ return ;
99+ }
100+
101+ // Example: Root=1-5e272390-8c398be037738dc042009320;Parent=94ae789b969f1cc5;Sampled=1
102+ logDebug ( `Reading Xray trace context from env var ${ header } ` ) ;
103+ return XrayService . parseAWSTraceHeader ( header ) ;
104+ }
105+
97106 private convertToSampleMode ( xraySampled : number ) : SampleMode {
98107 return xraySampled === 1 ? SampleMode . USER_KEEP : SampleMode . USER_REJECT ;
99108 }
@@ -172,11 +181,11 @@ export class XrayService {
172181
173182 private convertToParentId ( xrayParentId : string ) : string | undefined {
174183 if ( xrayParentId . length !== 16 ) return ;
175-
176- const hex = new BigNumber ( xrayParentId , 16 ) ;
177- if ( hex . isNaN ( ) ) return ;
178-
179- return hex . toString ( 10 ) ;
184+ try {
185+ return BigInt ( "0x" + xrayParentId ) . toString ( 10 ) ;
186+ } catch ( _ ) {
187+ return undefined ;
188+ }
180189 }
181190
182191 private convertToTraceId ( xrayTraceId : string ) : string | undefined {
@@ -187,13 +196,29 @@ export class XrayService {
187196 if ( lastPart . length !== 24 ) return ;
188197
189198 // We want to turn the last 63 bits into a decimal number in a string representation
190- // Unfortunately, all numbers in javascript are represented by float64 bit numbers, which
191- // means we can't parse 64 bit integers accurately.
192- const hex = new BigNumber ( lastPart , 16 ) ;
193- if ( hex . isNaN ( ) ) return ;
194-
195- // Toggle off the 64th bit
196- const last63Bits = hex . mod ( new BigNumber ( "8000000000000000" , 16 ) ) ;
197- return last63Bits . toString ( 10 ) ;
199+ try {
200+ return ( BigInt ( "0x" + lastPart ) % BigInt ( "0x8000000000000000" ) ) . toString ( 10 ) ;
201+ } catch ( _ ) {
202+ return undefined ;
203+ }
204+ }
205+
206+ public static extraceDDContextFromAWSTraceHeader ( amznTraceId : string ) : DatadogTraceHeaders | null {
207+ var aws_context = XrayService . parseAWSTraceHeader ( amznTraceId ) ;
208+ if ( ! aws_context ) {
209+ return null ;
210+ }
211+ const trace_id_parts = aws_context . traceId . split ( "-" ) ;
212+ if ( trace_id_parts && trace_id_parts . length > 2 && trace_id_parts [ 2 ] . startsWith ( "00000000" ) ) {
213+ // This AWSTraceHeader contains Datadog injected trace context
214+ return {
215+ [ DATADOG_TRACE_ID_HEADER ] : hexStrToDecimalStr ( trace_id_parts [ 2 ] . substring ( 8 ) ) ,
216+ [ DATADOG_PARENT_ID_HEADER ] : hexStrToDecimalStr ( aws_context . parentId ) ,
217+ [ DATADOG_SAMPLING_PRIORITY_HEADER ] : aws_context . sampled ,
218+ } ;
219+ }
220+ return null ;
198221 }
199222}
223+
224+ const hexStrToDecimalStr = ( hexString : string ) : string => BigInt ( "0x" + hexString ) . toString ( 10 ) ;
0 commit comments