1
1
import { randomBytes } from "crypto" ;
2
2
import { logDebug } from "../utils" ;
3
3
import { SampleMode , TraceContext , TraceSource } from "./trace-context-service" ;
4
- import BigNumber from "bignumber.js" ;
5
4
import { Socket , createSocket } from "dgram" ;
6
5
import { SpanContextWrapper } from "./span-context-wrapper" ;
7
6
import { 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" ;
8
13
9
14
const AMZN_TRACE_ID_ENV_VAR = "_X_AMZN_TRACE_ID" ;
10
15
const AWS_XRAY_DAEMON_ADDRESS_ENV_VAR = "AWS_XRAY_DAEMON_ADDRESS" ;
@@ -70,16 +75,8 @@ export class XrayService {
70
75
} ) ;
71
76
}
72
77
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 ( ";" ) ;
83
80
if ( parent === undefined || _sampled === undefined ) return ;
84
81
85
82
const [ , traceId ] = root . split ( "=" ) ;
@@ -94,6 +91,18 @@ export class XrayService {
94
91
} ;
95
92
}
96
93
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
+
97
106
private convertToSampleMode ( xraySampled : number ) : SampleMode {
98
107
return xraySampled === 1 ? SampleMode . USER_KEEP : SampleMode . USER_REJECT ;
99
108
}
@@ -172,11 +181,11 @@ export class XrayService {
172
181
173
182
private convertToParentId ( xrayParentId : string ) : string | undefined {
174
183
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
+ }
180
189
}
181
190
182
191
private convertToTraceId ( xrayTraceId : string ) : string | undefined {
@@ -187,13 +196,29 @@ export class XrayService {
187
196
if ( lastPart . length !== 24 ) return ;
188
197
189
198
// 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 ;
198
221
}
199
222
}
223
+
224
+ const hexStrToDecimalStr = ( hexString : string ) : string => BigInt ( "0x" + hexString ) . toString ( 10 ) ;
0 commit comments