@@ -36,11 +36,19 @@ import { FallbackSampler } from './fallback-sampler';
36
36
import {
37
37
AWSXRayRemoteSamplerConfig ,
38
38
GetSamplingRulesResponse ,
39
+ GetSamplingTargetsBody ,
40
+ GetSamplingTargetsResponse ,
39
41
SamplingRuleRecord ,
42
+ SamplingTargetDocument ,
43
+ TargetMap ,
40
44
} from './types' ;
41
- import { RuleCache } from './rule-cache' ;
45
+ import {
46
+ DEFAULT_TARGET_POLLING_INTERVAL_SECONDS ,
47
+ RuleCache ,
48
+ } from './rule-cache' ;
42
49
43
50
import { SamplingRuleApplier } from './sampling-rule-applier' ;
51
+ import { PACKAGE_NAME } from './version' ;
44
52
45
53
// 5 minute default sampling rules polling interval
46
54
const DEFAULT_RULES_POLLING_INTERVAL_SECONDS : number = 5 * 60 ;
@@ -94,17 +102,22 @@ export class AWSXRayRemoteSampler implements Sampler {
94
102
// Not intended for external use, use Parent-based `AWSXRayRemoteSampler` instead.
95
103
export class _AWSXRayRemoteSampler implements Sampler {
96
104
private rulePollingIntervalMillis : number ;
105
+ private targetPollingInterval : number ;
97
106
private awsProxyEndpoint : string ;
98
107
private ruleCache : RuleCache ;
99
108
private fallbackSampler : FallbackSampler ;
100
109
private samplerDiag : DiagLogger ;
101
110
private rulePoller : NodeJS . Timeout | undefined ;
111
+ private targetPoller : NodeJS . Timeout | undefined ;
102
112
private clientId : string ;
103
113
private rulePollingJitterMillis : number ;
114
+ private targetPollingJitterMillis : number ;
104
115
private samplingClient : AWSXRaySamplingClient ;
105
116
106
117
constructor ( samplerConfig : AWSXRayRemoteSamplerConfig ) {
107
- this . samplerDiag = diag ;
118
+ this . samplerDiag = diag . createComponentLogger ( {
119
+ namespace : PACKAGE_NAME ,
120
+ } ) ;
108
121
109
122
if (
110
123
samplerConfig . pollingInterval == null ||
@@ -120,6 +133,8 @@ export class _AWSXRayRemoteSampler implements Sampler {
120
133
}
121
134
122
135
this . rulePollingJitterMillis = Math . random ( ) * 5 * 1000 ;
136
+ this . targetPollingInterval = this . getDefaultTargetPollingInterval ( ) ;
137
+ this . targetPollingJitterMillis = ( Math . random ( ) / 10 ) * 1000 ;
123
138
124
139
this . awsProxyEndpoint = samplerConfig . endpoint
125
140
? samplerConfig . endpoint
@@ -137,7 +152,12 @@ export class _AWSXRayRemoteSampler implements Sampler {
137
152
// Start the Sampling Rules poller
138
153
this . startSamplingRulesPoller ( ) ;
139
154
140
- // TODO: Start the Sampling Targets poller
155
+ // Start the Sampling Targets poller where the first poll occurs after the default interval
156
+ this . startSamplingTargetsPoller ( ) ;
157
+ }
158
+
159
+ public getDefaultTargetPollingInterval ( ) : number {
160
+ return DEFAULT_TARGET_POLLING_INTERVAL_SECONDS ;
141
161
}
142
162
143
163
public shouldSample (
@@ -203,6 +223,7 @@ export class _AWSXRayRemoteSampler implements Sampler {
203
223
204
224
public stopPollers ( ) {
205
225
clearInterval ( this . rulePoller ) ;
226
+ clearInterval ( this . targetPoller ) ;
206
227
}
207
228
208
229
private startSamplingRulesPoller ( ) : void {
@@ -216,6 +237,27 @@ export class _AWSXRayRemoteSampler implements Sampler {
216
237
this . rulePoller . unref ( ) ;
217
238
}
218
239
240
+ private startSamplingTargetsPoller ( ) : void {
241
+ // Update sampling targets every targetPollingInterval (usually 10 seconds)
242
+ this . targetPoller = setInterval (
243
+ ( ) => this . getAndUpdateSamplingTargets ( ) ,
244
+ this . targetPollingInterval * 1000 + this . targetPollingJitterMillis
245
+ ) ;
246
+ this . targetPoller . unref ( ) ;
247
+ }
248
+
249
+ private getAndUpdateSamplingTargets ( ) : void {
250
+ const requestBody : GetSamplingTargetsBody = {
251
+ SamplingStatisticsDocuments :
252
+ this . ruleCache . createSamplingStatisticsDocuments ( this . clientId ) ,
253
+ } ;
254
+
255
+ this . samplingClient . fetchSamplingTargets (
256
+ requestBody ,
257
+ this . updateSamplingTargets . bind ( this )
258
+ ) ;
259
+ }
260
+
219
261
private getAndUpdateSamplingRules ( ) : void {
220
262
this . samplingClient . fetchSamplingRules ( this . updateSamplingRules . bind ( this ) ) ;
221
263
}
@@ -242,6 +284,41 @@ export class _AWSXRayRemoteSampler implements Sampler {
242
284
}
243
285
}
244
286
287
+ private updateSamplingTargets (
288
+ responseObject : GetSamplingTargetsResponse
289
+ ) : void {
290
+ try {
291
+ const targetDocuments : TargetMap = { } ;
292
+
293
+ // Create Target-Name-to-Target-Map from sampling targets response
294
+ responseObject . SamplingTargetDocuments . forEach (
295
+ ( newTarget : SamplingTargetDocument ) => {
296
+ targetDocuments [ newTarget . RuleName ] = newTarget ;
297
+ }
298
+ ) ;
299
+
300
+ // Update targets in the cache
301
+ const [ refreshSamplingRules , nextPollingInterval ] : [ boolean , number ] =
302
+ this . ruleCache . updateTargets (
303
+ targetDocuments ,
304
+ responseObject . LastRuleModification
305
+ ) ;
306
+ this . targetPollingInterval = nextPollingInterval ;
307
+ clearInterval ( this . targetPoller ) ;
308
+ this . startSamplingTargetsPoller ( ) ;
309
+
310
+ if ( refreshSamplingRules ) {
311
+ this . samplerDiag . debug (
312
+ 'Performing out-of-band sampling rule polling to fetch updated rules.'
313
+ ) ;
314
+ clearInterval ( this . rulePoller ) ;
315
+ this . startSamplingRulesPoller ( ) ;
316
+ }
317
+ } catch ( error : unknown ) {
318
+ this . samplerDiag . debug ( 'Error occurred when updating Sampling Targets' ) ;
319
+ }
320
+ }
321
+
245
322
private static generateClientId ( ) : string {
246
323
const hexChars : string [ ] = [
247
324
'0' ,
0 commit comments