@loadstrike/loadstrike-sdk 1.0.20801 → 1.0.21301
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -2
- package/dist/cjs/autopilot-contracts.js +11 -0
- package/dist/cjs/autopilot.js +717 -0
- package/dist/cjs/cluster.js +27 -2
- package/dist/cjs/correlation.js +132 -0
- package/dist/cjs/index.js +7 -2
- package/dist/cjs/local.js +116 -6
- package/dist/cjs/reporting.js +12 -0
- package/dist/cjs/runtime.js +966 -36
- package/dist/esm/autopilot-contracts.js +8 -0
- package/dist/esm/autopilot.js +709 -0
- package/dist/esm/cluster.js +27 -2
- package/dist/esm/correlation.js +132 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/local.js +116 -6
- package/dist/esm/reporting.js +12 -0
- package/dist/esm/runtime.js +966 -36
- package/dist/types/autopilot-contracts.d.ts +113 -0
- package/dist/types/autopilot.d.ts +43 -0
- package/dist/types/cluster.d.ts +21 -1
- package/dist/types/correlation.d.ts +132 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/local.d.ts +6 -0
- package/dist/types/reporting.d.ts +12 -0
- package/dist/types/runtime.d.ts +871 -0
- package/package.json +1 -1
package/dist/esm/runtime.js
CHANGED
|
@@ -42,14 +42,26 @@ export const LoadStrikeOperationType = {
|
|
|
42
42
|
Error: "Error"
|
|
43
43
|
};
|
|
44
44
|
export class LoadStrikePluginDataTable {
|
|
45
|
+
/**
|
|
46
|
+
* Exposes the public constructor operation.
|
|
47
|
+
* Use this when the surrounding wrapper type makes this operation the clearest way to express your intent.
|
|
48
|
+
*/
|
|
45
49
|
constructor(tableName, headers = [], rows = []) {
|
|
46
50
|
this.tableName = requireNonEmpty(tableName, "Table name must be provided.");
|
|
47
51
|
this.headers = [...headers];
|
|
48
52
|
this.rows = rows.map((row) => ({ ...row }));
|
|
49
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Creates a new instance of this public SDK type.
|
|
56
|
+
* Use this when you are starting a run definition from scratch.
|
|
57
|
+
*/
|
|
50
58
|
static create(tableName) {
|
|
51
59
|
return new LoadStrikePluginDataTable(tableName);
|
|
52
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Creates a new instance of this public SDK type.
|
|
63
|
+
* Use this when you are starting a run definition from scratch.
|
|
64
|
+
*/
|
|
53
65
|
static Create(tableName) {
|
|
54
66
|
return LoadStrikePluginDataTable.create(tableName);
|
|
55
67
|
}
|
|
@@ -64,14 +76,26 @@ export class LoadStrikePluginDataTable {
|
|
|
64
76
|
}
|
|
65
77
|
}
|
|
66
78
|
export class LoadStrikePluginData {
|
|
79
|
+
/**
|
|
80
|
+
* Exposes the public constructor operation.
|
|
81
|
+
* Use this when the surrounding wrapper type makes this operation the clearest way to express your intent.
|
|
82
|
+
*/
|
|
67
83
|
constructor(pluginName, tables = [], hints = []) {
|
|
68
84
|
this.pluginName = requireNonEmpty(pluginName, "Plugin name must be provided.");
|
|
69
85
|
this.tables = tables.map((table) => new LoadStrikePluginDataTable(table.tableName, table.headers, table.rows));
|
|
70
86
|
this.hints = [...hints];
|
|
71
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Creates a new instance of this public SDK type.
|
|
90
|
+
* Use this when you are starting a run definition from scratch.
|
|
91
|
+
*/
|
|
72
92
|
static create(pluginName) {
|
|
73
93
|
return new LoadStrikePluginData(pluginName);
|
|
74
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Creates a new instance of this public SDK type.
|
|
97
|
+
* Use this when you are starting a run definition from scratch.
|
|
98
|
+
*/
|
|
75
99
|
static Create(pluginName) {
|
|
76
100
|
return LoadStrikePluginData.create(pluginName);
|
|
77
101
|
}
|
|
@@ -96,6 +120,10 @@ class MeasurementAccumulator {
|
|
|
96
120
|
get Count() {
|
|
97
121
|
return this.count;
|
|
98
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Exposes the public record operation.
|
|
125
|
+
* Use this when the surrounding wrapper type makes this operation the clearest way to express your intent.
|
|
126
|
+
*/
|
|
99
127
|
record(reply, observedLatencyMs) {
|
|
100
128
|
const latencyMs = resolveRecordedLatency(reply.customLatencyMs, observedLatencyMs);
|
|
101
129
|
const sizeBytes = Math.max(toNumber(reply.sizeBytes), 0);
|
|
@@ -118,6 +146,10 @@ class MeasurementAccumulator {
|
|
|
118
146
|
count: 1
|
|
119
147
|
});
|
|
120
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Builds the configured payload or helper object.
|
|
151
|
+
* Use this when all builder inputs are ready to be materialized.
|
|
152
|
+
*/
|
|
121
153
|
build(allRequestCount, durationMs) {
|
|
122
154
|
const count = this.count;
|
|
123
155
|
const totalDurationMs = Math.max(durationMs, 0);
|
|
@@ -176,6 +208,10 @@ class StepStatsAccumulator {
|
|
|
176
208
|
this.ok = new MeasurementAccumulator();
|
|
177
209
|
this.fail = new MeasurementAccumulator();
|
|
178
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Exposes the public record operation.
|
|
213
|
+
* Use this when the surrounding wrapper type makes this operation the clearest way to express your intent.
|
|
214
|
+
*/
|
|
179
215
|
record(reply, observedLatencyMs) {
|
|
180
216
|
if (reply.isSuccess) {
|
|
181
217
|
this.ok.record(reply, observedLatencyMs);
|
|
@@ -183,6 +219,10 @@ class StepStatsAccumulator {
|
|
|
183
219
|
}
|
|
184
220
|
this.fail.record(reply, observedLatencyMs);
|
|
185
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Builds the configured payload or helper object.
|
|
224
|
+
* Use this when all builder inputs are ready to be materialized.
|
|
225
|
+
*/
|
|
186
226
|
build(allScenarioRequestCount, durationMs) {
|
|
187
227
|
const ok = this.ok.build(allScenarioRequestCount, durationMs);
|
|
188
228
|
const fail = this.fail.build(allScenarioRequestCount, durationMs);
|
|
@@ -222,18 +262,34 @@ class ScenarioStatsAccumulator {
|
|
|
222
262
|
this.loadSimulationStats = { simulationName: "", value: 0 };
|
|
223
263
|
this.currentOperation = "None";
|
|
224
264
|
}
|
|
265
|
+
/**
|
|
266
|
+
* Exposes the public setLoadSimulation operation.
|
|
267
|
+
* Use this when the surrounding wrapper type makes this operation the clearest way to express your intent.
|
|
268
|
+
*/
|
|
225
269
|
setLoadSimulation(simulationName, value) {
|
|
226
270
|
this.loadSimulationStats = {
|
|
227
271
|
simulationName,
|
|
228
272
|
value
|
|
229
273
|
};
|
|
230
274
|
}
|
|
275
|
+
/**
|
|
276
|
+
* Exposes the public setCurrentOperation operation.
|
|
277
|
+
* Use this when the surrounding wrapper type makes this operation the clearest way to express your intent.
|
|
278
|
+
*/
|
|
231
279
|
setCurrentOperation(operation) {
|
|
232
280
|
this.currentOperation = operation;
|
|
233
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* Returns current operation.
|
|
284
|
+
* Use this when current operation is required for branching, logging, or assertions.
|
|
285
|
+
*/
|
|
234
286
|
getCurrentOperation() {
|
|
235
287
|
return this.currentOperation;
|
|
236
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* Exposes the public recordScenario operation.
|
|
291
|
+
* Use this when the surrounding wrapper type makes this operation the clearest way to express your intent.
|
|
292
|
+
*/
|
|
237
293
|
recordScenario(reply, observedLatencyMs) {
|
|
238
294
|
if (reply.isSuccess) {
|
|
239
295
|
this.ok.record(reply, observedLatencyMs);
|
|
@@ -241,6 +297,10 @@ class ScenarioStatsAccumulator {
|
|
|
241
297
|
}
|
|
242
298
|
this.fail.record(reply, observedLatencyMs);
|
|
243
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Exposes the public recordStep operation.
|
|
302
|
+
* Use this when the surrounding wrapper type makes this operation the clearest way to express your intent.
|
|
303
|
+
*/
|
|
244
304
|
recordStep(stepName, reply, observedLatencyMs) {
|
|
245
305
|
const existing = this.steps.get(stepName);
|
|
246
306
|
const step = existing ?? new StepStatsAccumulator(this.scenarioName, stepName, this.nextStepSortIndex += 1);
|
|
@@ -249,6 +309,10 @@ class ScenarioStatsAccumulator {
|
|
|
249
309
|
}
|
|
250
310
|
step.record(reply, observedLatencyMs);
|
|
251
311
|
}
|
|
312
|
+
/**
|
|
313
|
+
* Builds the configured payload or helper object.
|
|
314
|
+
* Use this when all builder inputs are ready to be materialized.
|
|
315
|
+
*/
|
|
252
316
|
build(durationMs) {
|
|
253
317
|
const totalRequests = this.ok.Count + this.fail.Count;
|
|
254
318
|
const ok = this.ok.build(totalRequests, durationMs);
|
|
@@ -293,6 +357,10 @@ class ScenarioStatsAccumulator {
|
|
|
293
357
|
}
|
|
294
358
|
}
|
|
295
359
|
export class LoadStrikeResponse {
|
|
360
|
+
/**
|
|
361
|
+
* Creates a successful reply.
|
|
362
|
+
* Use this when a step or scenario completed successfully and should report a success response.
|
|
363
|
+
*/
|
|
296
364
|
static ok(...args) {
|
|
297
365
|
const normalized = normalizeSuccessResponseCall(args);
|
|
298
366
|
const reply = {
|
|
@@ -305,6 +373,10 @@ export class LoadStrikeResponse {
|
|
|
305
373
|
};
|
|
306
374
|
return attachReplyProjection(reply);
|
|
307
375
|
}
|
|
376
|
+
/**
|
|
377
|
+
* Creates a successful reply.
|
|
378
|
+
* Use this when a step or scenario completed successfully and should report a success response.
|
|
379
|
+
*/
|
|
308
380
|
static Ok(...args) {
|
|
309
381
|
return LoadStrikeResponse.ok(...args);
|
|
310
382
|
}
|
|
@@ -314,6 +386,10 @@ export class LoadStrikeResponse {
|
|
|
314
386
|
static OkWithPayload(payload, statusCode = "200", sizeBytesOrMessage = 0, messageOrSizeBytes = "", customLatencyMs) {
|
|
315
387
|
return LoadStrikeResponse.okWithPayload(payload, statusCode, sizeBytesOrMessage, messageOrSizeBytes, customLatencyMs);
|
|
316
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* Creates a failed reply.
|
|
391
|
+
* Use this when a step or scenario should record an explicit failure response.
|
|
392
|
+
*/
|
|
317
393
|
static fail(...args) {
|
|
318
394
|
const normalized = normalizeFailureResponseCall(args);
|
|
319
395
|
const reply = {
|
|
@@ -326,6 +402,10 @@ export class LoadStrikeResponse {
|
|
|
326
402
|
};
|
|
327
403
|
return attachReplyProjection(reply);
|
|
328
404
|
}
|
|
405
|
+
/**
|
|
406
|
+
* Creates a failed reply.
|
|
407
|
+
* Use this when a step or scenario should record an explicit failure response.
|
|
408
|
+
*/
|
|
329
409
|
static Fail(...args) {
|
|
330
410
|
return LoadStrikeResponse.fail(...args);
|
|
331
411
|
}
|
|
@@ -374,6 +454,10 @@ export class LoadStrikeStep {
|
|
|
374
454
|
}
|
|
375
455
|
}
|
|
376
456
|
export class LoadStrikeSimulation {
|
|
457
|
+
/**
|
|
458
|
+
* Builds a constant injection load shape.
|
|
459
|
+
* Use this when requests should be injected at a fixed rate over a duration.
|
|
460
|
+
*/
|
|
377
461
|
static inject(rate, intervalSeconds, duringSeconds) {
|
|
378
462
|
return attachLoadSimulationProjection({
|
|
379
463
|
Kind: "Inject",
|
|
@@ -382,9 +466,17 @@ export class LoadStrikeSimulation {
|
|
|
382
466
|
DuringSeconds: duringSeconds
|
|
383
467
|
});
|
|
384
468
|
}
|
|
469
|
+
/**
|
|
470
|
+
* Builds a constant injection load shape.
|
|
471
|
+
* Use this when requests should be injected at a fixed rate over a duration.
|
|
472
|
+
*/
|
|
385
473
|
static Inject(rate, intervalSeconds, duringSeconds) {
|
|
386
474
|
return LoadStrikeSimulation.inject(rate, intervalSeconds, duringSeconds);
|
|
387
475
|
}
|
|
476
|
+
/**
|
|
477
|
+
* Builds an iteration-limited constant-concurrency load shape.
|
|
478
|
+
* Use this when a fixed number of iterations should be shared across constant workers.
|
|
479
|
+
*/
|
|
388
480
|
static iterationsForConstant(copies, iterations) {
|
|
389
481
|
return attachLoadSimulationProjection({
|
|
390
482
|
Kind: "IterationsForConstant",
|
|
@@ -392,9 +484,17 @@ export class LoadStrikeSimulation {
|
|
|
392
484
|
Iterations: iterations
|
|
393
485
|
});
|
|
394
486
|
}
|
|
487
|
+
/**
|
|
488
|
+
* Builds an iteration-limited constant-concurrency load shape.
|
|
489
|
+
* Use this when a fixed number of iterations should be shared across constant workers.
|
|
490
|
+
*/
|
|
395
491
|
static IterationsForConstant(copies, iterations) {
|
|
396
492
|
return LoadStrikeSimulation.iterationsForConstant(copies, iterations);
|
|
397
493
|
}
|
|
494
|
+
/**
|
|
495
|
+
* Builds an iteration-limited injection load shape.
|
|
496
|
+
* Use this when a fixed number of injected iterations should be executed.
|
|
497
|
+
*/
|
|
398
498
|
static iterationsForInject(rate, intervalSeconds, iterations) {
|
|
399
499
|
return attachLoadSimulationProjection({
|
|
400
500
|
Kind: "IterationsForInject",
|
|
@@ -403,9 +503,17 @@ export class LoadStrikeSimulation {
|
|
|
403
503
|
Iterations: iterations
|
|
404
504
|
});
|
|
405
505
|
}
|
|
506
|
+
/**
|
|
507
|
+
* Builds an iteration-limited injection load shape.
|
|
508
|
+
* Use this when a fixed number of injected iterations should be executed.
|
|
509
|
+
*/
|
|
406
510
|
static IterationsForInject(rate, intervalSeconds, iterations) {
|
|
407
511
|
return LoadStrikeSimulation.iterationsForInject(rate, intervalSeconds, iterations);
|
|
408
512
|
}
|
|
513
|
+
/**
|
|
514
|
+
* Builds a constant-concurrency load shape.
|
|
515
|
+
* Use this when a fixed number of virtual users should stay active.
|
|
516
|
+
*/
|
|
409
517
|
static keepConstant(copies, duringSeconds) {
|
|
410
518
|
return attachLoadSimulationProjection({
|
|
411
519
|
Kind: "KeepConstant",
|
|
@@ -413,9 +521,17 @@ export class LoadStrikeSimulation {
|
|
|
413
521
|
DuringSeconds: duringSeconds
|
|
414
522
|
});
|
|
415
523
|
}
|
|
524
|
+
/**
|
|
525
|
+
* Builds a constant-concurrency load shape.
|
|
526
|
+
* Use this when a fixed number of virtual users should stay active.
|
|
527
|
+
*/
|
|
416
528
|
static KeepConstant(copies, duringSeconds) {
|
|
417
529
|
return LoadStrikeSimulation.keepConstant(copies, duringSeconds);
|
|
418
530
|
}
|
|
531
|
+
/**
|
|
532
|
+
* Builds a randomized injection load shape.
|
|
533
|
+
* Use this when traffic should fluctuate between a minimum and maximum rate.
|
|
534
|
+
*/
|
|
419
535
|
static injectRandom(minRate, maxRate, intervalSeconds, duringSeconds) {
|
|
420
536
|
return attachLoadSimulationProjection({
|
|
421
537
|
Kind: "InjectRandom",
|
|
@@ -425,9 +541,17 @@ export class LoadStrikeSimulation {
|
|
|
425
541
|
DuringSeconds: duringSeconds
|
|
426
542
|
});
|
|
427
543
|
}
|
|
544
|
+
/**
|
|
545
|
+
* Builds a randomized injection load shape.
|
|
546
|
+
* Use this when traffic should fluctuate between a minimum and maximum rate.
|
|
547
|
+
*/
|
|
428
548
|
static InjectRandom(minRate, maxRate, intervalSeconds, duringSeconds) {
|
|
429
549
|
return LoadStrikeSimulation.injectRandom(minRate, maxRate, intervalSeconds, duringSeconds);
|
|
430
550
|
}
|
|
551
|
+
/**
|
|
552
|
+
* Builds a ramping injection load shape.
|
|
553
|
+
* Use this when request rate should increase over time.
|
|
554
|
+
*/
|
|
431
555
|
static rampingInject(rate, intervalSeconds, duringSeconds) {
|
|
432
556
|
return attachLoadSimulationProjection({
|
|
433
557
|
Kind: "RampingInject",
|
|
@@ -436,9 +560,17 @@ export class LoadStrikeSimulation {
|
|
|
436
560
|
DuringSeconds: duringSeconds
|
|
437
561
|
});
|
|
438
562
|
}
|
|
563
|
+
/**
|
|
564
|
+
* Builds a ramping injection load shape.
|
|
565
|
+
* Use this when request rate should increase over time.
|
|
566
|
+
*/
|
|
439
567
|
static RampingInject(rate, intervalSeconds, duringSeconds) {
|
|
440
568
|
return LoadStrikeSimulation.rampingInject(rate, intervalSeconds, duringSeconds);
|
|
441
569
|
}
|
|
570
|
+
/**
|
|
571
|
+
* Builds a ramping-concurrency load shape.
|
|
572
|
+
* Use this when the number of active virtual users should climb over time.
|
|
573
|
+
*/
|
|
442
574
|
static rampingConstant(copies, duringSeconds) {
|
|
443
575
|
return attachLoadSimulationProjection({
|
|
444
576
|
Kind: "RampingConstant",
|
|
@@ -446,20 +578,36 @@ export class LoadStrikeSimulation {
|
|
|
446
578
|
DuringSeconds: duringSeconds
|
|
447
579
|
});
|
|
448
580
|
}
|
|
581
|
+
/**
|
|
582
|
+
* Builds a ramping-concurrency load shape.
|
|
583
|
+
* Use this when the number of active virtual users should climb over time.
|
|
584
|
+
*/
|
|
449
585
|
static RampingConstant(copies, duringSeconds) {
|
|
450
586
|
return LoadStrikeSimulation.rampingConstant(copies, duringSeconds);
|
|
451
587
|
}
|
|
588
|
+
/**
|
|
589
|
+
* Builds a pause segment in a load profile.
|
|
590
|
+
* Use this when a simulation should intentionally idle for a period.
|
|
591
|
+
*/
|
|
452
592
|
static pause(duringSeconds) {
|
|
453
593
|
return attachLoadSimulationProjection({
|
|
454
594
|
Kind: "Pause",
|
|
455
595
|
DuringSeconds: duringSeconds
|
|
456
596
|
});
|
|
457
597
|
}
|
|
598
|
+
/**
|
|
599
|
+
* Builds a pause segment in a load profile.
|
|
600
|
+
* Use this when a simulation should intentionally idle for a period.
|
|
601
|
+
*/
|
|
458
602
|
static Pause(duringSeconds) {
|
|
459
603
|
return LoadStrikeSimulation.pause(duringSeconds);
|
|
460
604
|
}
|
|
461
605
|
}
|
|
462
606
|
export class LoadStrikeCounter {
|
|
607
|
+
/**
|
|
608
|
+
* Exposes the public constructor operation.
|
|
609
|
+
* Use this when the surrounding wrapper type makes this operation the clearest way to express your intent.
|
|
610
|
+
*/
|
|
463
611
|
constructor(name, initialValueOrUnit = 0, unitOfMeasure = "") {
|
|
464
612
|
this.type = "counter";
|
|
465
613
|
this.name = requireNonEmpty(name, "Metric name is required.");
|
|
@@ -470,20 +618,40 @@ export class LoadStrikeCounter {
|
|
|
470
618
|
? 0
|
|
471
619
|
: (Number.isFinite(initialValueOrUnit) ? Number(initialValueOrUnit) : 0);
|
|
472
620
|
}
|
|
621
|
+
/**
|
|
622
|
+
* Adds a value to the current metric.
|
|
623
|
+
* Use this when a counter or gauge should be incremented by an explicit delta.
|
|
624
|
+
*/
|
|
473
625
|
add(value) {
|
|
474
626
|
const next = Number.isFinite(value) ? Number(value) : 0;
|
|
475
627
|
this.current += next;
|
|
476
628
|
return this.current;
|
|
477
629
|
}
|
|
630
|
+
/**
|
|
631
|
+
* Increments the current metric by one.
|
|
632
|
+
* Use this when events should simply be counted.
|
|
633
|
+
*/
|
|
478
634
|
increment(by = 1) {
|
|
479
635
|
return this.add(by);
|
|
480
636
|
}
|
|
637
|
+
/**
|
|
638
|
+
* Returns the current metric value.
|
|
639
|
+
* Use this when custom metric state needs to be inspected inside user code.
|
|
640
|
+
*/
|
|
481
641
|
value() {
|
|
482
642
|
return this.current;
|
|
483
643
|
}
|
|
644
|
+
/**
|
|
645
|
+
* Adds a value to the current metric.
|
|
646
|
+
* Use this when a counter or gauge should be incremented by an explicit delta.
|
|
647
|
+
*/
|
|
484
648
|
Add(value) {
|
|
485
649
|
return this.add(value);
|
|
486
650
|
}
|
|
651
|
+
/**
|
|
652
|
+
* Increments the current metric by one.
|
|
653
|
+
* Use this when events should simply be counted.
|
|
654
|
+
*/
|
|
487
655
|
Increment(by = 1) {
|
|
488
656
|
return this.increment(by);
|
|
489
657
|
}
|
|
@@ -498,6 +666,10 @@ export class LoadStrikeCounter {
|
|
|
498
666
|
}
|
|
499
667
|
}
|
|
500
668
|
export class LoadStrikeGauge {
|
|
669
|
+
/**
|
|
670
|
+
* Exposes the public constructor operation.
|
|
671
|
+
* Use this when the surrounding wrapper type makes this operation the clearest way to express your intent.
|
|
672
|
+
*/
|
|
501
673
|
constructor(name, initialValueOrUnit = 0, unitOfMeasure = "") {
|
|
502
674
|
this.type = "gauge";
|
|
503
675
|
this.name = requireNonEmpty(name, "Metric name is required.");
|
|
@@ -508,33 +680,69 @@ export class LoadStrikeGauge {
|
|
|
508
680
|
? 0
|
|
509
681
|
: (Number.isFinite(initialValueOrUnit) ? Number(initialValueOrUnit) : 0);
|
|
510
682
|
}
|
|
683
|
+
/**
|
|
684
|
+
* Sets the current gauge value.
|
|
685
|
+
* Use this when the latest observed value should replace the previous one.
|
|
686
|
+
*/
|
|
511
687
|
set(value) {
|
|
512
688
|
this.current = Number.isFinite(value) ? Number(value) : 0;
|
|
513
689
|
return this.current;
|
|
514
690
|
}
|
|
691
|
+
/**
|
|
692
|
+
* Adds a value to the current metric.
|
|
693
|
+
* Use this when a counter or gauge should be incremented by an explicit delta.
|
|
694
|
+
*/
|
|
515
695
|
add(value) {
|
|
516
696
|
const next = Number.isFinite(value) ? Number(value) : 0;
|
|
517
697
|
this.current += next;
|
|
518
698
|
return this.current;
|
|
519
699
|
}
|
|
700
|
+
/**
|
|
701
|
+
* Increments the current metric by one.
|
|
702
|
+
* Use this when events should simply be counted.
|
|
703
|
+
*/
|
|
520
704
|
increment(by = 1) {
|
|
521
705
|
return this.add(by);
|
|
522
706
|
}
|
|
707
|
+
/**
|
|
708
|
+
* Decrements the current metric by one.
|
|
709
|
+
* Use this when a gauge should move down by a single unit.
|
|
710
|
+
*/
|
|
523
711
|
decrement(by = 1) {
|
|
524
712
|
return this.add(-by);
|
|
525
713
|
}
|
|
714
|
+
/**
|
|
715
|
+
* Returns the current metric value.
|
|
716
|
+
* Use this when custom metric state needs to be inspected inside user code.
|
|
717
|
+
*/
|
|
526
718
|
value() {
|
|
527
719
|
return this.current;
|
|
528
720
|
}
|
|
721
|
+
/**
|
|
722
|
+
* Sets the current gauge value.
|
|
723
|
+
* Use this when the latest observed value should replace the previous one.
|
|
724
|
+
*/
|
|
529
725
|
Set(value) {
|
|
530
726
|
return this.set(value);
|
|
531
727
|
}
|
|
728
|
+
/**
|
|
729
|
+
* Adds a value to the current metric.
|
|
730
|
+
* Use this when a counter or gauge should be incremented by an explicit delta.
|
|
731
|
+
*/
|
|
532
732
|
Add(value) {
|
|
533
733
|
return this.add(value);
|
|
534
734
|
}
|
|
735
|
+
/**
|
|
736
|
+
* Increments the current metric by one.
|
|
737
|
+
* Use this when events should simply be counted.
|
|
738
|
+
*/
|
|
535
739
|
Increment(by = 1) {
|
|
536
740
|
return this.increment(by);
|
|
537
741
|
}
|
|
742
|
+
/**
|
|
743
|
+
* Decrements the current metric by one.
|
|
744
|
+
* Use this when a gauge should move down by a single unit.
|
|
745
|
+
*/
|
|
538
746
|
Decrement(by = 1) {
|
|
539
747
|
return this.decrement(by);
|
|
540
748
|
}
|
|
@@ -549,21 +757,45 @@ export class LoadStrikeGauge {
|
|
|
549
757
|
}
|
|
550
758
|
}
|
|
551
759
|
export class LoadStrikeMetric {
|
|
760
|
+
/**
|
|
761
|
+
* Creates a counter metric.
|
|
762
|
+
* Use this when a scenario should accumulate a monotonically increasing custom metric.
|
|
763
|
+
*/
|
|
552
764
|
static counter(name, initialValueOrUnit = 0, unitOfMeasure = "") {
|
|
553
765
|
return new LoadStrikeCounter(name, initialValueOrUnit, unitOfMeasure);
|
|
554
766
|
}
|
|
767
|
+
/**
|
|
768
|
+
* Creates a gauge metric.
|
|
769
|
+
* Use this when a scenario should track the latest value of a custom metric.
|
|
770
|
+
*/
|
|
555
771
|
static gauge(name, initialValueOrUnit = 0, unitOfMeasure = "") {
|
|
556
772
|
return new LoadStrikeGauge(name, initialValueOrUnit, unitOfMeasure);
|
|
557
773
|
}
|
|
774
|
+
/**
|
|
775
|
+
* Creates a counter metric.
|
|
776
|
+
* Use this when a scenario should accumulate a monotonically increasing custom metric.
|
|
777
|
+
*/
|
|
558
778
|
static Counter(name, initialValueOrUnit = 0, unitOfMeasure = "") {
|
|
559
779
|
return LoadStrikeMetric.counter(name, initialValueOrUnit, unitOfMeasure);
|
|
560
780
|
}
|
|
781
|
+
/**
|
|
782
|
+
* Creates a gauge metric.
|
|
783
|
+
* Use this when a scenario should track the latest value of a custom metric.
|
|
784
|
+
*/
|
|
561
785
|
static Gauge(name, initialValueOrUnit = 0, unitOfMeasure = "") {
|
|
562
786
|
return LoadStrikeMetric.gauge(name, initialValueOrUnit, unitOfMeasure);
|
|
563
787
|
}
|
|
788
|
+
/**
|
|
789
|
+
* Creates a counter metric.
|
|
790
|
+
* Use this when a scenario should accumulate a monotonically increasing custom metric.
|
|
791
|
+
*/
|
|
564
792
|
static CreateCounter(name, unitOfMeasure = "") {
|
|
565
793
|
return new LoadStrikeCounter(name, 0, unitOfMeasure);
|
|
566
794
|
}
|
|
795
|
+
/**
|
|
796
|
+
* Creates a gauge metric.
|
|
797
|
+
* Use this when a scenario should track the latest value of a custom metric.
|
|
798
|
+
*/
|
|
567
799
|
static CreateGauge(name, unitOfMeasure = "") {
|
|
568
800
|
return new LoadStrikeGauge(name, 0, unitOfMeasure);
|
|
569
801
|
}
|
|
@@ -684,15 +916,31 @@ export class LoadStrikeContext {
|
|
|
684
916
|
this.registeredScenarios = [...registeredScenarios];
|
|
685
917
|
this.runArgs = [...runArgs];
|
|
686
918
|
}
|
|
919
|
+
/**
|
|
920
|
+
* Creates a new instance of this public SDK type.
|
|
921
|
+
* Use this when you are starting a run definition from scratch.
|
|
922
|
+
*/
|
|
687
923
|
static create() {
|
|
688
924
|
return new LoadStrikeContext();
|
|
689
925
|
}
|
|
926
|
+
/**
|
|
927
|
+
* Exposes the public toObject operation.
|
|
928
|
+
* Use this when the surrounding wrapper type makes this operation the clearest way to express your intent.
|
|
929
|
+
*/
|
|
690
930
|
toObject() {
|
|
691
931
|
return { ...this.values };
|
|
692
932
|
}
|
|
933
|
+
/**
|
|
934
|
+
* Builds the current configuration into a runnable context.
|
|
935
|
+
* Use this when you want to inspect or reuse the final run settings before execution.
|
|
936
|
+
*/
|
|
693
937
|
buildContext() {
|
|
694
938
|
return this;
|
|
695
939
|
}
|
|
940
|
+
/**
|
|
941
|
+
* Builds the current configuration into a runnable context.
|
|
942
|
+
* Use this when you want to inspect or reuse the final run settings before execution.
|
|
943
|
+
*/
|
|
696
944
|
BuildContext() {
|
|
697
945
|
return this.buildContext();
|
|
698
946
|
}
|
|
@@ -714,6 +962,10 @@ export class LoadStrikeContext {
|
|
|
714
962
|
const args = normalizeRunArgsInput(argsOrSingleArray);
|
|
715
963
|
return this.run(args);
|
|
716
964
|
}
|
|
965
|
+
/**
|
|
966
|
+
* Exposes the public toRunnerOptions operation.
|
|
967
|
+
* Use this when the surrounding wrapper type makes this operation the clearest way to express your intent.
|
|
968
|
+
*/
|
|
717
969
|
toRunnerOptions() {
|
|
718
970
|
const normalizedValues = normalizeRunContextCollectionShapes(this.values);
|
|
719
971
|
return {
|
|
@@ -786,27 +1038,59 @@ export class LoadStrikeContext {
|
|
|
786
1038
|
Configure(input) {
|
|
787
1039
|
return this.configure(input);
|
|
788
1040
|
}
|
|
1041
|
+
/**
|
|
1042
|
+
* Copies settings from an existing context snapshot.
|
|
1043
|
+
* Use this when a runner should inherit configuration that was already assembled elsewhere.
|
|
1044
|
+
*/
|
|
789
1045
|
configureContext(context) {
|
|
790
1046
|
return this.configure(context);
|
|
791
1047
|
}
|
|
1048
|
+
/**
|
|
1049
|
+
* Copies settings from an existing context snapshot.
|
|
1050
|
+
* Use this when a runner should inherit configuration that was already assembled elsewhere.
|
|
1051
|
+
*/
|
|
792
1052
|
ConfigureContext(context) {
|
|
793
1053
|
return this.configureContext(context);
|
|
794
1054
|
}
|
|
1055
|
+
/**
|
|
1056
|
+
* Toggles realtime console metric output.
|
|
1057
|
+
* Use this when a local run or CI log should stream live throughput and latency updates.
|
|
1058
|
+
*/
|
|
795
1059
|
displayConsoleMetrics(enable) {
|
|
796
1060
|
return this.DisplayConsoleMetrics(enable);
|
|
797
1061
|
}
|
|
1062
|
+
/**
|
|
1063
|
+
* Toggles realtime console metric output.
|
|
1064
|
+
* Use this when a local run or CI log should stream live throughput and latency updates.
|
|
1065
|
+
*/
|
|
798
1066
|
DisplayConsoleMetrics(enable) {
|
|
799
1067
|
return this.mergeValues({ ConsoleMetricsEnabled: Boolean(enable) });
|
|
800
1068
|
}
|
|
1069
|
+
/**
|
|
1070
|
+
* Toggles local development cluster mode.
|
|
1071
|
+
* Use this when you want to simulate coordinator and agent behavior on a single machine.
|
|
1072
|
+
*/
|
|
801
1073
|
enableLocalDevCluster(enable) {
|
|
802
1074
|
return this.EnableLocalDevCluster(enable);
|
|
803
1075
|
}
|
|
1076
|
+
/**
|
|
1077
|
+
* Toggles local development cluster mode.
|
|
1078
|
+
* Use this when you want to simulate coordinator and agent behavior on a single machine.
|
|
1079
|
+
*/
|
|
804
1080
|
EnableLocalDevCluster(enable) {
|
|
805
1081
|
return this.mergeValues({ LocalDevClusterEnabled: Boolean(enable) });
|
|
806
1082
|
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Loads run settings from a JSON config file.
|
|
1085
|
+
* Use this when configuration should come from a checked-in or generated config document.
|
|
1086
|
+
*/
|
|
807
1087
|
loadConfig(path) {
|
|
808
1088
|
return this.LoadConfig(path);
|
|
809
1089
|
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Loads run settings from a JSON config file.
|
|
1092
|
+
* Use this when configuration should come from a checked-in or generated config document.
|
|
1093
|
+
*/
|
|
810
1094
|
LoadConfig(path) {
|
|
811
1095
|
const configPath = requireNonEmpty(path, "Config path must be provided.");
|
|
812
1096
|
const loaded = loadJsonObject(configPath);
|
|
@@ -816,9 +1100,17 @@ export class LoadStrikeContext {
|
|
|
816
1100
|
...extractContextOverridesFromConfig(loaded)
|
|
817
1101
|
});
|
|
818
1102
|
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Loads infrastructure settings for sinks, plugins, or transport dependencies.
|
|
1105
|
+
* Use this when runtime integrations depend on external connection details.
|
|
1106
|
+
*/
|
|
819
1107
|
loadInfraConfig(path) {
|
|
820
1108
|
return this.LoadInfraConfig(path);
|
|
821
1109
|
}
|
|
1110
|
+
/**
|
|
1111
|
+
* Loads infrastructure settings for sinks, plugins, or transport dependencies.
|
|
1112
|
+
* Use this when runtime integrations depend on external connection details.
|
|
1113
|
+
*/
|
|
822
1114
|
LoadInfraConfig(path) {
|
|
823
1115
|
const infraConfigPath = requireNonEmpty(path, "Infra config path must be provided.");
|
|
824
1116
|
return this.mergeValues({
|
|
@@ -826,87 +1118,191 @@ export class LoadStrikeContext {
|
|
|
826
1118
|
InfraConfig: loadJsonObject(infraConfigPath)
|
|
827
1119
|
});
|
|
828
1120
|
}
|
|
1121
|
+
/**
|
|
1122
|
+
* Sets the agent group for this node or run.
|
|
1123
|
+
* Use this when only a subset of agents should pick up a particular workload.
|
|
1124
|
+
*/
|
|
829
1125
|
withAgentGroup(agentGroup) {
|
|
830
1126
|
return this.WithAgentGroup(agentGroup);
|
|
831
1127
|
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Sets the agent group for this node or run.
|
|
1130
|
+
* Use this when only a subset of agents should pick up a particular workload.
|
|
1131
|
+
*/
|
|
832
1132
|
WithAgentGroup(agentGroup) {
|
|
833
1133
|
return this.mergeValues({ AgentGroup: requireNonEmpty(agentGroup, "Agent group must be provided.") });
|
|
834
1134
|
}
|
|
1135
|
+
/**
|
|
1136
|
+
* Sets the requested agent count.
|
|
1137
|
+
* Use this when a coordinator should fan work out across a specific number of agents.
|
|
1138
|
+
*/
|
|
835
1139
|
withAgentsCount(agentsCount) {
|
|
836
1140
|
return this.WithAgentsCount(agentsCount);
|
|
837
1141
|
}
|
|
1142
|
+
/**
|
|
1143
|
+
* Sets the requested agent count.
|
|
1144
|
+
* Use this when a coordinator should fan work out across a specific number of agents.
|
|
1145
|
+
*/
|
|
838
1146
|
WithAgentsCount(agentsCount) {
|
|
839
1147
|
if (!Number.isFinite(agentsCount) || agentsCount <= 0) {
|
|
840
1148
|
throw new RangeError("Agents count should be greater than zero.");
|
|
841
1149
|
}
|
|
842
1150
|
return this.mergeValues({ AgentsCount: Math.trunc(agentsCount) });
|
|
843
1151
|
}
|
|
1152
|
+
/**
|
|
1153
|
+
* Targets a shared set of scenarios.
|
|
1154
|
+
* Use this when only selected scenarios should execute for the current node or run.
|
|
1155
|
+
*/
|
|
844
1156
|
withTargetScenarios(...scenarioNames) {
|
|
845
1157
|
return this.WithTargetScenarios(...scenarioNames);
|
|
846
1158
|
}
|
|
1159
|
+
/**
|
|
1160
|
+
* Targets a shared set of scenarios.
|
|
1161
|
+
* Use this when only selected scenarios should execute for the current node or run.
|
|
1162
|
+
*/
|
|
847
1163
|
WithTargetScenarios(...scenarioNames) {
|
|
848
1164
|
return this.mergeValues({ TargetScenarios: validateScenarioNames(scenarioNames) });
|
|
849
1165
|
}
|
|
1166
|
+
/**
|
|
1167
|
+
* Targets scenarios for agent nodes only.
|
|
1168
|
+
* Use this when agents should execute only a subset of the registered scenarios.
|
|
1169
|
+
*/
|
|
850
1170
|
withAgentTargetScenarios(...scenarioNames) {
|
|
851
1171
|
return this.WithAgentTargetScenarios(...scenarioNames);
|
|
852
1172
|
}
|
|
1173
|
+
/**
|
|
1174
|
+
* Targets scenarios for agent nodes only.
|
|
1175
|
+
* Use this when agents should execute only a subset of the registered scenarios.
|
|
1176
|
+
*/
|
|
853
1177
|
WithAgentTargetScenarios(...scenarioNames) {
|
|
854
1178
|
return this.mergeValues({ AgentTargetScenarios: validateScenarioNames(scenarioNames) });
|
|
855
1179
|
}
|
|
1180
|
+
/**
|
|
1181
|
+
* Targets scenarios for the coordinator only.
|
|
1182
|
+
* Use this when orchestration or control-node work should run on the coordinator itself.
|
|
1183
|
+
*/
|
|
856
1184
|
withCoordinatorTargetScenarios(...scenarioNames) {
|
|
857
1185
|
return this.WithCoordinatorTargetScenarios(...scenarioNames);
|
|
858
1186
|
}
|
|
1187
|
+
/**
|
|
1188
|
+
* Targets scenarios for the coordinator only.
|
|
1189
|
+
* Use this when orchestration or control-node work should run on the coordinator itself.
|
|
1190
|
+
*/
|
|
859
1191
|
WithCoordinatorTargetScenarios(...scenarioNames) {
|
|
860
1192
|
return this.mergeValues({ CoordinatorTargetScenarios: validateScenarioNames(scenarioNames) });
|
|
861
1193
|
}
|
|
1194
|
+
/**
|
|
1195
|
+
* Sets the runner key used for licensing validation.
|
|
1196
|
+
* Use this when the run must authenticate against the licensing API before it starts.
|
|
1197
|
+
*/
|
|
862
1198
|
withRunnerKey(runnerKey) {
|
|
863
1199
|
return this.WithRunnerKey(runnerKey);
|
|
864
1200
|
}
|
|
1201
|
+
/**
|
|
1202
|
+
* Sets the runner key used for licensing validation.
|
|
1203
|
+
* Use this when the run must authenticate against the licensing API before it starts.
|
|
1204
|
+
*/
|
|
865
1205
|
WithRunnerKey(runnerKey) {
|
|
866
1206
|
return this.mergeValues({ RunnerKey: requireNonEmpty(runnerKey, "Runner key must be provided.") });
|
|
867
1207
|
}
|
|
1208
|
+
/**
|
|
1209
|
+
* Sets how long the SDK waits for licensing validation to complete.
|
|
1210
|
+
* Use this when control-plane latency or private networking requires a longer validation window.
|
|
1211
|
+
*/
|
|
868
1212
|
withLicenseValidationTimeout(timeoutSeconds) {
|
|
869
1213
|
return this.WithLicenseValidationTimeout(timeoutSeconds);
|
|
870
1214
|
}
|
|
1215
|
+
/**
|
|
1216
|
+
* Sets how long the SDK waits for licensing validation to complete.
|
|
1217
|
+
* Use this when control-plane latency or private networking requires a longer validation window.
|
|
1218
|
+
*/
|
|
871
1219
|
WithLicenseValidationTimeout(timeoutSeconds) {
|
|
872
1220
|
if (!Number.isFinite(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
873
1221
|
throw new RangeError("License validation timeout should be greater than zero.");
|
|
874
1222
|
}
|
|
875
1223
|
return this.mergeValues({ LicenseValidationTimeoutSeconds: timeoutSeconds });
|
|
876
1224
|
}
|
|
1225
|
+
/**
|
|
1226
|
+
* Sets the runtime node type.
|
|
1227
|
+
* Use this when a process should behave as a single node, coordinator, or agent.
|
|
1228
|
+
*/
|
|
877
1229
|
withNodeType(nodeType) {
|
|
878
1230
|
return this.WithNodeType(nodeType);
|
|
879
1231
|
}
|
|
1232
|
+
/**
|
|
1233
|
+
* Sets the runtime node type.
|
|
1234
|
+
* Use this when a process should behave as a single node, coordinator, or agent.
|
|
1235
|
+
*/
|
|
880
1236
|
WithNodeType(nodeType) {
|
|
881
1237
|
return this.mergeValues({ NodeType: parseNodeTypeToken(nodeType) });
|
|
882
1238
|
}
|
|
1239
|
+
/**
|
|
1240
|
+
* Sets the NATS server URL used for distributed cluster coordination.
|
|
1241
|
+
* Use this when coordinator and agent nodes communicate over NATS.
|
|
1242
|
+
*/
|
|
883
1243
|
withNatsServerUrl(natsUrl) {
|
|
884
1244
|
return this.WithNatsServerUrl(natsUrl);
|
|
885
1245
|
}
|
|
1246
|
+
/**
|
|
1247
|
+
* Sets the NATS server URL used for distributed cluster coordination.
|
|
1248
|
+
* Use this when coordinator and agent nodes communicate over NATS.
|
|
1249
|
+
*/
|
|
886
1250
|
WithNatsServerUrl(natsUrl) {
|
|
887
1251
|
return this.mergeValues({ NatsServerUrl: requireNonEmpty(natsUrl, "NATS server URL must be provided.") });
|
|
888
1252
|
}
|
|
1253
|
+
/**
|
|
1254
|
+
* Disables local report generation.
|
|
1255
|
+
* Use this when reports are unnecessary or should be handled exclusively by sinks.
|
|
1256
|
+
*/
|
|
889
1257
|
withoutReports() {
|
|
890
1258
|
return this.WithoutReports();
|
|
891
1259
|
}
|
|
1260
|
+
/**
|
|
1261
|
+
* Disables local report generation.
|
|
1262
|
+
* Use this when reports are unnecessary or should be handled exclusively by sinks.
|
|
1263
|
+
*/
|
|
892
1264
|
WithoutReports() {
|
|
893
1265
|
return this.mergeValues({ ReportsEnabled: false });
|
|
894
1266
|
}
|
|
1267
|
+
/**
|
|
1268
|
+
* Sets the base file name for generated reports.
|
|
1269
|
+
* Use this when exported reports should use a predictable naming convention.
|
|
1270
|
+
*/
|
|
895
1271
|
withReportFileName(reportFileName) {
|
|
896
1272
|
return this.WithReportFileName(reportFileName);
|
|
897
1273
|
}
|
|
1274
|
+
/**
|
|
1275
|
+
* Sets the base file name for generated reports.
|
|
1276
|
+
* Use this when exported reports should use a predictable naming convention.
|
|
1277
|
+
*/
|
|
898
1278
|
WithReportFileName(reportFileName) {
|
|
899
1279
|
return this.mergeValues({ ReportFileName: requireNonEmpty(reportFileName, "Report file name must be provided.") });
|
|
900
1280
|
}
|
|
1281
|
+
/**
|
|
1282
|
+
* Sets the output folder for generated reports.
|
|
1283
|
+
* Use this when report files should land in a specific directory.
|
|
1284
|
+
*/
|
|
901
1285
|
withReportFolder(reportFolderPath) {
|
|
902
1286
|
return this.WithReportFolder(reportFolderPath);
|
|
903
1287
|
}
|
|
1288
|
+
/**
|
|
1289
|
+
* Sets the output folder for generated reports.
|
|
1290
|
+
* Use this when report files should land in a specific directory.
|
|
1291
|
+
*/
|
|
904
1292
|
WithReportFolder(reportFolderPath) {
|
|
905
1293
|
return this.mergeValues({ ReportFolderPath: requireNonEmpty(reportFolderPath, "Report folder path must be provided.") });
|
|
906
1294
|
}
|
|
1295
|
+
/**
|
|
1296
|
+
* Restricts generated reports to specific formats.
|
|
1297
|
+
* Use this when you want only selected report artifacts such as HTML, CSV, or Markdown.
|
|
1298
|
+
*/
|
|
907
1299
|
withReportFormats(...reportFormats) {
|
|
908
1300
|
return this.WithReportFormats(...reportFormats);
|
|
909
1301
|
}
|
|
1302
|
+
/**
|
|
1303
|
+
* Restricts generated reports to specific formats.
|
|
1304
|
+
* Use this when you want only selected report artifacts such as HTML, CSV, or Markdown.
|
|
1305
|
+
*/
|
|
910
1306
|
WithReportFormats(...reportFormats) {
|
|
911
1307
|
if (!reportFormats.length) {
|
|
912
1308
|
throw new Error("At least one report format should be provided.");
|
|
@@ -917,18 +1313,34 @@ export class LoadStrikeContext {
|
|
|
917
1313
|
}
|
|
918
1314
|
return this.mergeValues({ ReportFormats: normalized });
|
|
919
1315
|
}
|
|
1316
|
+
/**
|
|
1317
|
+
* Sets the realtime reporting cadence.
|
|
1318
|
+
* Use this when sinks or dashboards should receive updates at a controlled interval.
|
|
1319
|
+
*/
|
|
920
1320
|
withReportingInterval(intervalSeconds) {
|
|
921
1321
|
return this.WithReportingInterval(intervalSeconds);
|
|
922
1322
|
}
|
|
1323
|
+
/**
|
|
1324
|
+
* Sets the realtime reporting cadence.
|
|
1325
|
+
* Use this when sinks or dashboards should receive updates at a controlled interval.
|
|
1326
|
+
*/
|
|
923
1327
|
WithReportingInterval(intervalSeconds) {
|
|
924
1328
|
if (!Number.isFinite(intervalSeconds) || intervalSeconds <= 0) {
|
|
925
1329
|
throw new RangeError("Reporting interval should be greater than zero.");
|
|
926
1330
|
}
|
|
927
1331
|
return this.mergeValues({ ReportingIntervalSeconds: intervalSeconds });
|
|
928
1332
|
}
|
|
1333
|
+
/**
|
|
1334
|
+
* Registers one or more reporting sinks.
|
|
1335
|
+
* Use this when run results must be pushed to external observability or storage systems.
|
|
1336
|
+
*/
|
|
929
1337
|
withReportingSinks(...sinks) {
|
|
930
1338
|
return this.WithReportingSinks(...sinks);
|
|
931
1339
|
}
|
|
1340
|
+
/**
|
|
1341
|
+
* Registers one or more reporting sinks.
|
|
1342
|
+
* Use this when run results must be pushed to external observability or storage systems.
|
|
1343
|
+
*/
|
|
932
1344
|
WithReportingSinks(...sinks) {
|
|
933
1345
|
if (!sinks.length) {
|
|
934
1346
|
throw new Error("At least one reporting sink should be provided.");
|
|
@@ -939,9 +1351,17 @@ export class LoadStrikeContext {
|
|
|
939
1351
|
validateNamedReportingSinks(sinks);
|
|
940
1352
|
return this.mergeValues({ ReportingSinks: sinks });
|
|
941
1353
|
}
|
|
1354
|
+
/**
|
|
1355
|
+
* Registers runtime policies for the run.
|
|
1356
|
+
* Use this when scenario selection or step execution should obey policy callbacks.
|
|
1357
|
+
*/
|
|
942
1358
|
withRuntimePolicies(...policies) {
|
|
943
1359
|
return this.WithRuntimePolicies(...policies);
|
|
944
1360
|
}
|
|
1361
|
+
/**
|
|
1362
|
+
* Registers runtime policies for the run.
|
|
1363
|
+
* Use this when scenario selection or step execution should obey policy callbacks.
|
|
1364
|
+
*/
|
|
945
1365
|
WithRuntimePolicies(...policies) {
|
|
946
1366
|
if (!policies.length) {
|
|
947
1367
|
throw new Error("At least one runtime policy should be provided.");
|
|
@@ -951,17 +1371,33 @@ export class LoadStrikeContext {
|
|
|
951
1371
|
}
|
|
952
1372
|
return this.mergeValues({ RuntimePolicies: policies });
|
|
953
1373
|
}
|
|
1374
|
+
/**
|
|
1375
|
+
* Sets how runtime policy failures are handled.
|
|
1376
|
+
* Use this when policy errors should either fail fast or be tolerated.
|
|
1377
|
+
*/
|
|
954
1378
|
withRuntimePolicyErrorMode(mode) {
|
|
955
1379
|
return this.WithRuntimePolicyErrorMode(mode);
|
|
956
1380
|
}
|
|
1381
|
+
/**
|
|
1382
|
+
* Sets how runtime policy failures are handled.
|
|
1383
|
+
* Use this when policy errors should either fail fast or be tolerated.
|
|
1384
|
+
*/
|
|
957
1385
|
WithRuntimePolicyErrorMode(mode) {
|
|
958
1386
|
return this.mergeValues({
|
|
959
1387
|
RuntimePolicyErrorMode: normalizedRuntimePolicyErrorMode(mode)
|
|
960
1388
|
});
|
|
961
1389
|
}
|
|
1390
|
+
/**
|
|
1391
|
+
* Registers worker plugins for the run.
|
|
1392
|
+
* Use this when custom plugin data should be collected alongside run results.
|
|
1393
|
+
*/
|
|
962
1394
|
withWorkerPlugins(...plugins) {
|
|
963
1395
|
return this.WithWorkerPlugins(...plugins);
|
|
964
1396
|
}
|
|
1397
|
+
/**
|
|
1398
|
+
* Registers worker plugins for the run.
|
|
1399
|
+
* Use this when custom plugin data should be collected alongside run results.
|
|
1400
|
+
*/
|
|
965
1401
|
WithWorkerPlugins(...plugins) {
|
|
966
1402
|
if (!plugins.length) {
|
|
967
1403
|
throw new Error("At least one worker plugin should be provided.");
|
|
@@ -972,71 +1408,143 @@ export class LoadStrikeContext {
|
|
|
972
1408
|
validateNamedWorkerPlugins(plugins);
|
|
973
1409
|
return this.mergeValues({ WorkerPlugins: plugins });
|
|
974
1410
|
}
|
|
1411
|
+
/**
|
|
1412
|
+
* Sets the minimum runtime log level.
|
|
1413
|
+
* Use this when the run should emit less or more operational detail.
|
|
1414
|
+
*/
|
|
975
1415
|
withMinimumLogLevel(minimumLogLevel) {
|
|
976
1416
|
return this.WithMinimumLogLevel(minimumLogLevel);
|
|
977
1417
|
}
|
|
1418
|
+
/**
|
|
1419
|
+
* Sets the minimum runtime log level.
|
|
1420
|
+
* Use this when the run should emit less or more operational detail.
|
|
1421
|
+
*/
|
|
978
1422
|
WithMinimumLogLevel(minimumLogLevel) {
|
|
979
1423
|
return this.mergeValues({
|
|
980
1424
|
MinimumLogLevel: parseMinimumLogLevelToken(requireNonEmpty(minimumLogLevel, "Minimum log level must be provided."))
|
|
981
1425
|
});
|
|
982
1426
|
}
|
|
1427
|
+
/**
|
|
1428
|
+
* Supplies a custom logger configuration factory.
|
|
1429
|
+
* Use this when the default runtime logging output is not enough for your environment.
|
|
1430
|
+
*/
|
|
983
1431
|
withLoggerConfig(loggerConfig) {
|
|
984
1432
|
return this.WithLoggerConfig(loggerConfig);
|
|
985
1433
|
}
|
|
1434
|
+
/**
|
|
1435
|
+
* Supplies a custom logger configuration factory.
|
|
1436
|
+
* Use this when the default runtime logging output is not enough for your environment.
|
|
1437
|
+
*/
|
|
986
1438
|
WithLoggerConfig(loggerConfig) {
|
|
987
1439
|
if (typeof loggerConfig !== "function") {
|
|
988
1440
|
throw new TypeError("Logger config must be provided.");
|
|
989
1441
|
}
|
|
990
1442
|
return this.mergeValues({ LoggerConfig: loggerConfig });
|
|
991
1443
|
}
|
|
1444
|
+
/**
|
|
1445
|
+
* Sets the timeout for scenario completion.
|
|
1446
|
+
* Use this when long-running scenarios need an explicit completion window.
|
|
1447
|
+
*/
|
|
992
1448
|
withScenarioCompletionTimeout(timeoutSeconds) {
|
|
993
1449
|
return this.WithScenarioCompletionTimeout(timeoutSeconds);
|
|
994
1450
|
}
|
|
1451
|
+
/**
|
|
1452
|
+
* Sets the timeout for scenario completion.
|
|
1453
|
+
* Use this when long-running scenarios need an explicit completion window.
|
|
1454
|
+
*/
|
|
995
1455
|
WithScenarioCompletionTimeout(timeoutSeconds) {
|
|
996
1456
|
if (!Number.isFinite(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
997
1457
|
throw new RangeError("Scenario completion timeout should be greater than zero.");
|
|
998
1458
|
}
|
|
999
1459
|
return this.mergeValues({ ScenarioCompletionTimeoutSeconds: timeoutSeconds });
|
|
1000
1460
|
}
|
|
1461
|
+
/**
|
|
1462
|
+
* Sets the timeout for cluster command round-trips.
|
|
1463
|
+
* Use this when distributed control messages need a tighter or looser deadline.
|
|
1464
|
+
*/
|
|
1001
1465
|
withClusterCommandTimeout(timeoutSeconds) {
|
|
1002
1466
|
return this.WithClusterCommandTimeout(timeoutSeconds);
|
|
1003
1467
|
}
|
|
1468
|
+
/**
|
|
1469
|
+
* Sets the timeout for cluster command round-trips.
|
|
1470
|
+
* Use this when distributed control messages need a tighter or looser deadline.
|
|
1471
|
+
*/
|
|
1004
1472
|
WithClusterCommandTimeout(timeoutSeconds) {
|
|
1005
1473
|
if (!Number.isFinite(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
1006
1474
|
throw new RangeError("Cluster command timeout should be greater than zero.");
|
|
1007
1475
|
}
|
|
1008
1476
|
return this.mergeValues({ ClusterCommandTimeoutSeconds: timeoutSeconds });
|
|
1009
1477
|
}
|
|
1478
|
+
/**
|
|
1479
|
+
* Sets the retry limit for restartable failed iterations.
|
|
1480
|
+
* Use this when transient failures should be retried a fixed number of times.
|
|
1481
|
+
*/
|
|
1010
1482
|
withRestartIterationMaxAttempts(attempts) {
|
|
1011
1483
|
return this.WithRestartIterationMaxAttempts(attempts);
|
|
1012
1484
|
}
|
|
1485
|
+
/**
|
|
1486
|
+
* Sets the retry limit for restartable failed iterations.
|
|
1487
|
+
* Use this when transient failures should be retried a fixed number of times.
|
|
1488
|
+
*/
|
|
1013
1489
|
WithRestartIterationMaxAttempts(attempts) {
|
|
1014
1490
|
if (!Number.isFinite(attempts) || attempts < 0) {
|
|
1015
1491
|
throw new RangeError("Restart iteration max attempts should be zero or greater.");
|
|
1016
1492
|
}
|
|
1017
1493
|
return this.mergeValues({ RestartIterationMaxAttempts: Math.trunc(attempts) });
|
|
1018
1494
|
}
|
|
1495
|
+
/**
|
|
1496
|
+
* Sets the session identifier for this run.
|
|
1497
|
+
* Use this when downstream logs, reports, or external systems need a stable session id.
|
|
1498
|
+
*/
|
|
1019
1499
|
withSessionId(sessionId) {
|
|
1020
1500
|
return this.WithSessionId(sessionId);
|
|
1021
1501
|
}
|
|
1502
|
+
/**
|
|
1503
|
+
* Sets the session identifier for this run.
|
|
1504
|
+
* Use this when downstream logs, reports, or external systems need a stable session id.
|
|
1505
|
+
*/
|
|
1022
1506
|
WithSessionId(sessionId) {
|
|
1023
1507
|
return this.mergeValues({ SessionId: requireNonEmpty(sessionId, "Session id must be provided.") });
|
|
1024
1508
|
}
|
|
1509
|
+
/**
|
|
1510
|
+
* Sets the test suite label for the run.
|
|
1511
|
+
* Use this when related tests should be grouped under a suite name.
|
|
1512
|
+
*/
|
|
1025
1513
|
withTestSuite(testSuite) {
|
|
1026
1514
|
return this.WithTestSuite(testSuite);
|
|
1027
1515
|
}
|
|
1516
|
+
/**
|
|
1517
|
+
* Sets the test suite label for the run.
|
|
1518
|
+
* Use this when related tests should be grouped under a suite name.
|
|
1519
|
+
*/
|
|
1028
1520
|
WithTestSuite(testSuite) {
|
|
1029
1521
|
return this.mergeValues({ TestSuite: requireNonEmpty(testSuite, "Test suite must be provided.") });
|
|
1030
1522
|
}
|
|
1523
|
+
/**
|
|
1524
|
+
* Sets the test name label for the run.
|
|
1525
|
+
* Use this when reports and logs should expose a human-readable test identifier.
|
|
1526
|
+
*/
|
|
1031
1527
|
withTestName(testName) {
|
|
1032
1528
|
return this.WithTestName(testName);
|
|
1033
1529
|
}
|
|
1530
|
+
/**
|
|
1531
|
+
* Sets the test name label for the run.
|
|
1532
|
+
* Use this when reports and logs should expose a human-readable test identifier.
|
|
1533
|
+
*/
|
|
1034
1534
|
WithTestName(testName) {
|
|
1035
1535
|
return this.mergeValues({ TestName: requireNonEmpty(testName, "Test name must be provided.") });
|
|
1036
1536
|
}
|
|
1537
|
+
/**
|
|
1538
|
+
* Sets the cluster identifier for this run.
|
|
1539
|
+
* Use this when multiple cluster nodes must join the same distributed execution.
|
|
1540
|
+
*/
|
|
1037
1541
|
withClusterId(clusterId) {
|
|
1038
1542
|
return this.WithClusterId(clusterId);
|
|
1039
1543
|
}
|
|
1544
|
+
/**
|
|
1545
|
+
* Sets the cluster identifier for this run.
|
|
1546
|
+
* Use this when multiple cluster nodes must join the same distributed execution.
|
|
1547
|
+
*/
|
|
1040
1548
|
WithClusterId(clusterId) {
|
|
1041
1549
|
return this.mergeValues({ ClusterId: requireNonEmpty(clusterId, "Cluster id must be provided.") });
|
|
1042
1550
|
}
|
|
@@ -1049,12 +1557,16 @@ export class LoadStrikeContext {
|
|
|
1049
1557
|
this.runArgs = [...runArgs];
|
|
1050
1558
|
return this;
|
|
1051
1559
|
}
|
|
1560
|
+
/**
|
|
1561
|
+
* Configures registered scenarios for this SDK object.
|
|
1562
|
+
* Use this when registered scenarios should be set explicitly before the run starts.
|
|
1563
|
+
*/
|
|
1052
1564
|
withRegisteredScenarios(...scenarios) {
|
|
1053
1565
|
return this.assignState(this.values, scenarios, this.runArgs);
|
|
1054
1566
|
}
|
|
1055
1567
|
}
|
|
1056
1568
|
export class LoadStrikeScenario {
|
|
1057
|
-
constructor(name, runHandler, initHandler, cleanHandler, loadSimulations, thresholds, trackingConfiguration, maxFailCount, withoutWarmUpValue, warmUpDurationSeconds, weight, restartIterationOnFail) {
|
|
1569
|
+
constructor(name, runHandler, initHandler, cleanHandler, loadSimulations, thresholds, trackingConfiguration, maxFailCount, withoutWarmUpValue, warmUpDurationSeconds, weight, restartIterationOnFail, internalLicenseFeatures = []) {
|
|
1058
1570
|
this.name = name;
|
|
1059
1571
|
this.runHandler = runHandler;
|
|
1060
1572
|
this.initHandler = initHandler;
|
|
@@ -1067,6 +1579,7 @@ export class LoadStrikeScenario {
|
|
|
1067
1579
|
this.warmUpDurationSeconds = warmUpDurationSeconds;
|
|
1068
1580
|
this.weight = weight;
|
|
1069
1581
|
this.restartIterationOnFail = restartIterationOnFail;
|
|
1582
|
+
this.internalLicenseFeatures = normalizeStringArray(internalLicenseFeatures);
|
|
1070
1583
|
}
|
|
1071
1584
|
static create(name, runHandler) {
|
|
1072
1585
|
const scenarioName = requireNonEmpty(name, "Scenario name must be provided.");
|
|
@@ -1084,57 +1597,105 @@ export class LoadStrikeScenario {
|
|
|
1084
1597
|
static CreateAsync(name, runHandler) {
|
|
1085
1598
|
return LoadStrikeScenario.createAsync(name, runHandler);
|
|
1086
1599
|
}
|
|
1600
|
+
/**
|
|
1601
|
+
* Creates a placeholder scenario that returns the default success reply.
|
|
1602
|
+
* Use this when you want a scenario shell before adding setup, cleanup, or more detailed behavior.
|
|
1603
|
+
*/
|
|
1087
1604
|
static empty(name) {
|
|
1088
1605
|
return LoadStrikeScenario.create(name, () => LoadStrikeResponse.ok());
|
|
1089
1606
|
}
|
|
1607
|
+
/**
|
|
1608
|
+
* Creates a placeholder scenario that returns the default success reply.
|
|
1609
|
+
* Use this when you want a scenario shell before adding setup, cleanup, or more detailed behavior.
|
|
1610
|
+
*/
|
|
1090
1611
|
static Empty(name) {
|
|
1091
1612
|
return LoadStrikeScenario.empty(name);
|
|
1092
1613
|
}
|
|
1093
1614
|
get Name() {
|
|
1094
1615
|
return this.name;
|
|
1095
1616
|
}
|
|
1617
|
+
/**
|
|
1618
|
+
* Configures init for this SDK object.
|
|
1619
|
+
* Use this when init should be set explicitly before the run starts.
|
|
1620
|
+
*/
|
|
1096
1621
|
withInit(handler) {
|
|
1097
1622
|
if (typeof handler !== "function") {
|
|
1098
1623
|
throw new TypeError("Init handler must be provided.");
|
|
1099
1624
|
}
|
|
1100
|
-
return new LoadStrikeScenario(this.name, this.runHandler, handler, this.cleanHandler, this.loadSimulations, this.thresholds, this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail);
|
|
1625
|
+
return new LoadStrikeScenario(this.name, this.runHandler, handler, this.cleanHandler, this.loadSimulations, this.thresholds, this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail, this.internalLicenseFeatures);
|
|
1101
1626
|
}
|
|
1627
|
+
/**
|
|
1628
|
+
* Configures init async for this SDK object.
|
|
1629
|
+
* Use this when init async should be set explicitly before the run starts.
|
|
1630
|
+
*/
|
|
1102
1631
|
withInitAsync(handler) {
|
|
1103
1632
|
return this.withInit(handler);
|
|
1104
1633
|
}
|
|
1634
|
+
/**
|
|
1635
|
+
* Configures clean for this SDK object.
|
|
1636
|
+
* Use this when clean should be set explicitly before the run starts.
|
|
1637
|
+
*/
|
|
1105
1638
|
withClean(handler) {
|
|
1106
1639
|
if (typeof handler !== "function") {
|
|
1107
1640
|
throw new TypeError("Clean handler must be provided.");
|
|
1108
1641
|
}
|
|
1109
|
-
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, handler, this.loadSimulations, this.thresholds, this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail);
|
|
1642
|
+
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, handler, this.loadSimulations, this.thresholds, this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail, this.internalLicenseFeatures);
|
|
1110
1643
|
}
|
|
1644
|
+
/**
|
|
1645
|
+
* Configures clean async for this SDK object.
|
|
1646
|
+
* Use this when clean async should be set explicitly before the run starts.
|
|
1647
|
+
*/
|
|
1111
1648
|
withCleanAsync(handler) {
|
|
1112
1649
|
return this.withClean(handler);
|
|
1113
1650
|
}
|
|
1651
|
+
/**
|
|
1652
|
+
* Configures max fail count for this SDK object.
|
|
1653
|
+
* Use this when max fail count should be set explicitly before the run starts.
|
|
1654
|
+
*/
|
|
1114
1655
|
withMaxFailCount(maxFailCount) {
|
|
1115
1656
|
if (!Number.isFinite(maxFailCount)) {
|
|
1116
1657
|
throw new RangeError("maxFailCount should be a finite number.");
|
|
1117
1658
|
}
|
|
1118
|
-
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, this.thresholds, this.trackingConfiguration, Math.trunc(maxFailCount), this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail);
|
|
1659
|
+
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, this.thresholds, this.trackingConfiguration, Math.trunc(maxFailCount), this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail, this.internalLicenseFeatures);
|
|
1119
1660
|
}
|
|
1661
|
+
/**
|
|
1662
|
+
* Configures out warm up for this SDK object.
|
|
1663
|
+
* Use this when out warm up should be set explicitly before the run starts.
|
|
1664
|
+
*/
|
|
1120
1665
|
withoutWarmUp() {
|
|
1121
|
-
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, this.thresholds, this.trackingConfiguration, this.maxFailCount, true, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail);
|
|
1666
|
+
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, this.thresholds, this.trackingConfiguration, this.maxFailCount, true, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail, this.internalLicenseFeatures);
|
|
1122
1667
|
}
|
|
1668
|
+
/**
|
|
1669
|
+
* Configures warm up duration for this SDK object.
|
|
1670
|
+
* Use this when warm up duration should be set explicitly before the run starts.
|
|
1671
|
+
*/
|
|
1123
1672
|
withWarmUpDuration(durationSeconds) {
|
|
1124
1673
|
if (!Number.isFinite(durationSeconds)) {
|
|
1125
1674
|
throw new RangeError("Warmup duration should be a finite number.");
|
|
1126
1675
|
}
|
|
1127
|
-
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, this.thresholds, this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, durationSeconds, this.weight, this.restartIterationOnFail);
|
|
1676
|
+
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, this.thresholds, this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, durationSeconds, this.weight, this.restartIterationOnFail, this.internalLicenseFeatures);
|
|
1128
1677
|
}
|
|
1678
|
+
/**
|
|
1679
|
+
* Configures weight for this SDK object.
|
|
1680
|
+
* Use this when weight should be set explicitly before the run starts.
|
|
1681
|
+
*/
|
|
1129
1682
|
withWeight(weight) {
|
|
1130
1683
|
if (!Number.isFinite(weight)) {
|
|
1131
1684
|
throw new RangeError("Weight should be a finite number.");
|
|
1132
1685
|
}
|
|
1133
|
-
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, this.thresholds, this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, Math.trunc(weight), this.restartIterationOnFail);
|
|
1686
|
+
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, this.thresholds, this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, Math.trunc(weight), this.restartIterationOnFail, this.internalLicenseFeatures);
|
|
1134
1687
|
}
|
|
1688
|
+
/**
|
|
1689
|
+
* Configures restart iteration on fail for this SDK object.
|
|
1690
|
+
* Use this when restart iteration on fail should be set explicitly before the run starts.
|
|
1691
|
+
*/
|
|
1135
1692
|
withRestartIterationOnFail(shouldRestart) {
|
|
1136
|
-
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, this.thresholds, this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, Boolean(shouldRestart));
|
|
1693
|
+
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, this.thresholds, this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, Boolean(shouldRestart), this.internalLicenseFeatures);
|
|
1137
1694
|
}
|
|
1695
|
+
/**
|
|
1696
|
+
* Configures cross platform tracking for this SDK object.
|
|
1697
|
+
* Use this when cross platform tracking should be set explicitly before the run starts.
|
|
1698
|
+
*/
|
|
1138
1699
|
withCrossPlatformTracking(configuration) {
|
|
1139
1700
|
if (!configuration || typeof configuration !== "object" || Array.isArray(configuration)) {
|
|
1140
1701
|
throw new TypeError("Tracking configuration must be provided.");
|
|
@@ -1150,44 +1711,91 @@ export class LoadStrikeScenario {
|
|
|
1150
1711
|
? mapRuntimeTrackingEndpointSpec(destinationSpec)
|
|
1151
1712
|
: null;
|
|
1152
1713
|
validateRuntimeTrackingConfiguration(copied, sourceEndpoint, destinationEndpoint);
|
|
1153
|
-
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, this.thresholds, copied, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail);
|
|
1714
|
+
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, this.thresholds, copied, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail, this.internalLicenseFeatures);
|
|
1154
1715
|
}
|
|
1716
|
+
/**
|
|
1717
|
+
* Configures load simulations for this SDK object.
|
|
1718
|
+
* Use this when load simulations should be set explicitly before the run starts.
|
|
1719
|
+
*/
|
|
1155
1720
|
withLoadSimulations(...simulations) {
|
|
1156
1721
|
if (!simulations.length) {
|
|
1157
1722
|
throw new Error("At least one load simulation should be provided.");
|
|
1158
1723
|
}
|
|
1159
|
-
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, simulations.map((simulation) => attachLoadSimulationProjection({ ...simulation })), this.thresholds, this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail);
|
|
1724
|
+
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, simulations.map((simulation) => attachLoadSimulationProjection({ ...simulation })), this.thresholds, this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail, this.internalLicenseFeatures);
|
|
1160
1725
|
}
|
|
1726
|
+
/**
|
|
1727
|
+
* Configures thresholds for this SDK object.
|
|
1728
|
+
* Use this when thresholds should be set explicitly before the run starts.
|
|
1729
|
+
*/
|
|
1161
1730
|
withThresholds(...thresholds) {
|
|
1162
1731
|
if (!thresholds.length) {
|
|
1163
1732
|
throw new Error("At least one threshold should be provided.");
|
|
1164
1733
|
}
|
|
1165
|
-
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, thresholds.map((threshold) => ({ ...threshold })), this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail);
|
|
1734
|
+
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, thresholds.map((threshold) => ({ ...threshold })), this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail, this.internalLicenseFeatures);
|
|
1166
1735
|
}
|
|
1736
|
+
/**
|
|
1737
|
+
* Returns simulations.
|
|
1738
|
+
* Use this when simulations is required for branching, logging, or assertions.
|
|
1739
|
+
*/
|
|
1167
1740
|
getSimulations() {
|
|
1168
1741
|
return this.loadSimulations.map((simulation) => attachLoadSimulationProjection({ ...simulation }));
|
|
1169
1742
|
}
|
|
1743
|
+
/**
|
|
1744
|
+
* Returns thresholds.
|
|
1745
|
+
* Use this when thresholds is required for branching, logging, or assertions.
|
|
1746
|
+
*/
|
|
1170
1747
|
getThresholds() {
|
|
1171
1748
|
return this.thresholds;
|
|
1172
1749
|
}
|
|
1750
|
+
/**
|
|
1751
|
+
* Returns tracking configuration.
|
|
1752
|
+
* Use this when tracking configuration is required for branching, logging, or assertions.
|
|
1753
|
+
*/
|
|
1173
1754
|
getTrackingConfiguration() {
|
|
1174
1755
|
return this.trackingConfiguration ? { ...this.trackingConfiguration } : undefined;
|
|
1175
1756
|
}
|
|
1757
|
+
/**
|
|
1758
|
+
* Returns max fail count.
|
|
1759
|
+
* Use this when max fail count is required for branching, logging, or assertions.
|
|
1760
|
+
*/
|
|
1176
1761
|
getMaxFailCount() {
|
|
1177
1762
|
return this.maxFailCount;
|
|
1178
1763
|
}
|
|
1764
|
+
/**
|
|
1765
|
+
* Exposes the public isWithoutWarmUp operation.
|
|
1766
|
+
* Use this when the surrounding wrapper type makes this operation the clearest way to express your intent.
|
|
1767
|
+
*/
|
|
1179
1768
|
isWithoutWarmUp() {
|
|
1180
1769
|
return this.withoutWarmUpValue;
|
|
1181
1770
|
}
|
|
1771
|
+
/**
|
|
1772
|
+
* Returns warm up duration seconds.
|
|
1773
|
+
* Use this when warm up duration seconds is required for branching, logging, or assertions.
|
|
1774
|
+
*/
|
|
1182
1775
|
getWarmUpDurationSeconds() {
|
|
1183
1776
|
return this.warmUpDurationSeconds;
|
|
1184
1777
|
}
|
|
1778
|
+
/**
|
|
1779
|
+
* Returns weight.
|
|
1780
|
+
* Use this when weight is required for branching, logging, or assertions.
|
|
1781
|
+
*/
|
|
1185
1782
|
getWeight() {
|
|
1186
1783
|
return this.weight;
|
|
1187
1784
|
}
|
|
1785
|
+
/**
|
|
1786
|
+
* Exposes the public shouldRestartIterationOnFail operation.
|
|
1787
|
+
* Use this when the surrounding wrapper type makes this operation the clearest way to express your intent.
|
|
1788
|
+
*/
|
|
1188
1789
|
shouldRestartIterationOnFail() {
|
|
1189
1790
|
return this.restartIterationOnFail;
|
|
1190
1791
|
}
|
|
1792
|
+
__loadStrikeInternalLicenseFeatures() {
|
|
1793
|
+
return [...this.internalLicenseFeatures];
|
|
1794
|
+
}
|
|
1795
|
+
__loadStrikeWithInternalLicenseFeatures(...features) {
|
|
1796
|
+
const merged = Array.from(new Set([...this.internalLicenseFeatures, ...normalizeStringArray(features)]));
|
|
1797
|
+
return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, this.thresholds, this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail, merged);
|
|
1798
|
+
}
|
|
1191
1799
|
async invokeInit(context) {
|
|
1192
1800
|
if (this.initHandler) {
|
|
1193
1801
|
await this.initHandler(context);
|
|
@@ -1210,39 +1818,87 @@ export class LoadStrikeScenario {
|
|
|
1210
1818
|
return LoadStrikeResponse.fail("exception", resolveRuntimeErrorMessage(error, "scenario failed"), 0);
|
|
1211
1819
|
}
|
|
1212
1820
|
}
|
|
1821
|
+
/**
|
|
1822
|
+
* Configures cross platform tracking for this SDK object.
|
|
1823
|
+
* Use this when cross platform tracking should be set explicitly before the run starts.
|
|
1824
|
+
*/
|
|
1213
1825
|
WithCrossPlatformTracking(configuration) {
|
|
1214
1826
|
return this.withCrossPlatformTracking(configuration);
|
|
1215
1827
|
}
|
|
1828
|
+
/**
|
|
1829
|
+
* Configures init for this SDK object.
|
|
1830
|
+
* Use this when init should be set explicitly before the run starts.
|
|
1831
|
+
*/
|
|
1216
1832
|
WithInit(handler) {
|
|
1217
1833
|
return this.withInit(handler);
|
|
1218
1834
|
}
|
|
1835
|
+
/**
|
|
1836
|
+
* Configures init async for this SDK object.
|
|
1837
|
+
* Use this when init async should be set explicitly before the run starts.
|
|
1838
|
+
*/
|
|
1219
1839
|
WithInitAsync(handler) {
|
|
1220
1840
|
return this.withInitAsync(handler);
|
|
1221
1841
|
}
|
|
1842
|
+
/**
|
|
1843
|
+
* Configures clean for this SDK object.
|
|
1844
|
+
* Use this when clean should be set explicitly before the run starts.
|
|
1845
|
+
*/
|
|
1222
1846
|
WithClean(handler) {
|
|
1223
1847
|
return this.withClean(handler);
|
|
1224
1848
|
}
|
|
1849
|
+
/**
|
|
1850
|
+
* Configures clean async for this SDK object.
|
|
1851
|
+
* Use this when clean async should be set explicitly before the run starts.
|
|
1852
|
+
*/
|
|
1225
1853
|
WithCleanAsync(handler) {
|
|
1226
1854
|
return this.withCleanAsync(handler);
|
|
1227
1855
|
}
|
|
1856
|
+
/**
|
|
1857
|
+
* Configures load simulations for this SDK object.
|
|
1858
|
+
* Use this when load simulations should be set explicitly before the run starts.
|
|
1859
|
+
*/
|
|
1228
1860
|
WithLoadSimulations(...simulations) {
|
|
1229
1861
|
return this.withLoadSimulations(...simulations);
|
|
1230
1862
|
}
|
|
1863
|
+
/**
|
|
1864
|
+
* Configures max fail count for this SDK object.
|
|
1865
|
+
* Use this when max fail count should be set explicitly before the run starts.
|
|
1866
|
+
*/
|
|
1231
1867
|
WithMaxFailCount(maxFailCount) {
|
|
1232
1868
|
return this.withMaxFailCount(maxFailCount);
|
|
1233
1869
|
}
|
|
1870
|
+
/**
|
|
1871
|
+
* Configures out warm up for this SDK object.
|
|
1872
|
+
* Use this when out warm up should be set explicitly before the run starts.
|
|
1873
|
+
*/
|
|
1234
1874
|
WithoutWarmUp() {
|
|
1235
1875
|
return this.withoutWarmUp();
|
|
1236
1876
|
}
|
|
1877
|
+
/**
|
|
1878
|
+
* Configures restart iteration on fail for this SDK object.
|
|
1879
|
+
* Use this when restart iteration on fail should be set explicitly before the run starts.
|
|
1880
|
+
*/
|
|
1237
1881
|
WithRestartIterationOnFail(shouldRestart) {
|
|
1238
1882
|
return this.withRestartIterationOnFail(shouldRestart);
|
|
1239
1883
|
}
|
|
1884
|
+
/**
|
|
1885
|
+
* Configures thresholds for this SDK object.
|
|
1886
|
+
* Use this when thresholds should be set explicitly before the run starts.
|
|
1887
|
+
*/
|
|
1240
1888
|
WithThresholds(...thresholds) {
|
|
1241
1889
|
return this.withThresholds(...thresholds);
|
|
1242
1890
|
}
|
|
1891
|
+
/**
|
|
1892
|
+
* Configures warm up duration for this SDK object.
|
|
1893
|
+
* Use this when warm up duration should be set explicitly before the run starts.
|
|
1894
|
+
*/
|
|
1243
1895
|
WithWarmUpDuration(durationSeconds) {
|
|
1244
1896
|
return this.withWarmUpDuration(durationSeconds);
|
|
1245
1897
|
}
|
|
1898
|
+
/**
|
|
1899
|
+
* Configures weight for this SDK object.
|
|
1900
|
+
* Use this when weight should be set explicitly before the run starts.
|
|
1901
|
+
*/
|
|
1246
1902
|
WithWeight(weight) {
|
|
1247
1903
|
return this.withWeight(weight);
|
|
1248
1904
|
}
|
|
@@ -1253,115 +1909,251 @@ export class LoadStrikeRunner {
|
|
|
1253
1909
|
this.options = normalizeRunnerOptionCollectionShapes(options);
|
|
1254
1910
|
this.contextConfigurators = [...contextConfigurators];
|
|
1255
1911
|
}
|
|
1912
|
+
/**
|
|
1913
|
+
* Creates a new instance of this public SDK type.
|
|
1914
|
+
* Use this when you are starting a run definition from scratch.
|
|
1915
|
+
*/
|
|
1256
1916
|
static create() {
|
|
1257
1917
|
return new LoadStrikeRunner([], {});
|
|
1258
1918
|
}
|
|
1919
|
+
/**
|
|
1920
|
+
* Creates a new instance of this public SDK type.
|
|
1921
|
+
* Use this when you are starting a run definition from scratch.
|
|
1922
|
+
*/
|
|
1259
1923
|
static Create() {
|
|
1260
1924
|
return LoadStrikeRunner.create();
|
|
1261
1925
|
}
|
|
1926
|
+
/**
|
|
1927
|
+
* Registers one or more scenarios on a fresh runnable context.
|
|
1928
|
+
* Use this when you want a context immediately without composing a runner first.
|
|
1929
|
+
*/
|
|
1262
1930
|
static registerScenarios(...scenarios) {
|
|
1263
1931
|
validateRegisteredScenarios(scenarios);
|
|
1264
1932
|
return new LoadStrikeContext({}, scenarios);
|
|
1265
1933
|
}
|
|
1934
|
+
/**
|
|
1935
|
+
* Registers one or more scenarios on a fresh runnable context.
|
|
1936
|
+
* Use this when you want a context immediately without composing a runner first.
|
|
1937
|
+
*/
|
|
1266
1938
|
static RegisterScenarios(...scenarios) {
|
|
1267
1939
|
return LoadStrikeRunner.registerScenarios(...scenarios);
|
|
1268
1940
|
}
|
|
1941
|
+
/**
|
|
1942
|
+
* Toggles realtime console metric output.
|
|
1943
|
+
* Use this when a local run or CI log should stream live throughput and latency updates.
|
|
1944
|
+
*/
|
|
1269
1945
|
static DisplayConsoleMetrics(context, enable) {
|
|
1270
1946
|
return context.DisplayConsoleMetrics(enable);
|
|
1271
1947
|
}
|
|
1948
|
+
/**
|
|
1949
|
+
* Toggles local development cluster mode.
|
|
1950
|
+
* Use this when you want to simulate coordinator and agent behavior on a single machine.
|
|
1951
|
+
*/
|
|
1272
1952
|
static EnableLocalDevCluster(context, enable) {
|
|
1273
1953
|
return context.EnableLocalDevCluster(enable);
|
|
1274
1954
|
}
|
|
1955
|
+
/**
|
|
1956
|
+
* Loads run settings from a JSON config file.
|
|
1957
|
+
* Use this when configuration should come from a checked-in or generated config document.
|
|
1958
|
+
*/
|
|
1275
1959
|
static LoadConfig(context, path) {
|
|
1276
1960
|
return context.LoadConfig(path);
|
|
1277
1961
|
}
|
|
1962
|
+
/**
|
|
1963
|
+
* Loads infrastructure settings for sinks, plugins, or transport dependencies.
|
|
1964
|
+
* Use this when runtime integrations depend on external connection details.
|
|
1965
|
+
*/
|
|
1278
1966
|
static LoadInfraConfig(context, path) {
|
|
1279
1967
|
return context.LoadInfraConfig(path);
|
|
1280
1968
|
}
|
|
1969
|
+
/**
|
|
1970
|
+
* Executes the configured workload through the SDK runtime.
|
|
1971
|
+
* Use this when configuration is complete and you are ready to start the run.
|
|
1972
|
+
*/
|
|
1281
1973
|
static Run(context, ...args) {
|
|
1282
1974
|
return context.Run(args);
|
|
1283
1975
|
}
|
|
1976
|
+
/**
|
|
1977
|
+
* Sets the agent group for this node or run.
|
|
1978
|
+
* Use this when only a subset of agents should pick up a particular workload.
|
|
1979
|
+
*/
|
|
1284
1980
|
static WithAgentGroup(context, agentGroup) {
|
|
1285
1981
|
return context.WithAgentGroup(agentGroup);
|
|
1286
1982
|
}
|
|
1983
|
+
/**
|
|
1984
|
+
* Sets the requested agent count.
|
|
1985
|
+
* Use this when a coordinator should fan work out across a specific number of agents.
|
|
1986
|
+
*/
|
|
1287
1987
|
static WithAgentsCount(context, agentsCount) {
|
|
1288
1988
|
return context.WithAgentsCount(agentsCount);
|
|
1289
1989
|
}
|
|
1990
|
+
/**
|
|
1991
|
+
* Targets scenarios for agent nodes only.
|
|
1992
|
+
* Use this when agents should execute only a subset of the registered scenarios.
|
|
1993
|
+
*/
|
|
1290
1994
|
static WithAgentTargetScenarios(context, ...scenarioNames) {
|
|
1291
1995
|
return context.WithAgentTargetScenarios(...scenarioNames);
|
|
1292
1996
|
}
|
|
1997
|
+
/**
|
|
1998
|
+
* Sets the cluster identifier for this run.
|
|
1999
|
+
* Use this when multiple cluster nodes must join the same distributed execution.
|
|
2000
|
+
*/
|
|
1293
2001
|
static WithClusterId(context, clusterId) {
|
|
1294
2002
|
return context.WithClusterId(clusterId);
|
|
1295
2003
|
}
|
|
2004
|
+
/**
|
|
2005
|
+
* Targets scenarios for the coordinator only.
|
|
2006
|
+
* Use this when orchestration or control-node work should run on the coordinator itself.
|
|
2007
|
+
*/
|
|
1296
2008
|
static WithCoordinatorTargetScenarios(context, ...scenarioNames) {
|
|
1297
2009
|
return context.WithCoordinatorTargetScenarios(...scenarioNames);
|
|
1298
2010
|
}
|
|
2011
|
+
/**
|
|
2012
|
+
* Sets the runner key used for licensing validation.
|
|
2013
|
+
* Use this when the run must authenticate against the licensing API before it starts.
|
|
2014
|
+
*/
|
|
1299
2015
|
static WithRunnerKey(context, runnerKey) {
|
|
1300
2016
|
return context.WithRunnerKey(runnerKey);
|
|
1301
2017
|
}
|
|
2018
|
+
/**
|
|
2019
|
+
* Sets how long the SDK waits for licensing validation to complete.
|
|
2020
|
+
* Use this when control-plane latency or private networking requires a longer validation window.
|
|
2021
|
+
*/
|
|
1302
2022
|
static WithLicenseValidationTimeout(context, timeoutSeconds) {
|
|
1303
2023
|
return context.WithLicenseValidationTimeout(timeoutSeconds);
|
|
1304
2024
|
}
|
|
2025
|
+
/**
|
|
2026
|
+
* Supplies a custom logger configuration factory.
|
|
2027
|
+
* Use this when the default runtime logging output is not enough for your environment.
|
|
2028
|
+
*/
|
|
1305
2029
|
static WithLoggerConfig(context, loggerConfig) {
|
|
1306
2030
|
return context.WithLoggerConfig(loggerConfig);
|
|
1307
2031
|
}
|
|
2032
|
+
/**
|
|
2033
|
+
* Sets the minimum runtime log level.
|
|
2034
|
+
* Use this when the run should emit less or more operational detail.
|
|
2035
|
+
*/
|
|
1308
2036
|
static WithMinimumLogLevel(context, minimumLogLevel) {
|
|
1309
2037
|
return context.WithMinimumLogLevel(minimumLogLevel);
|
|
1310
2038
|
}
|
|
2039
|
+
/**
|
|
2040
|
+
* Sets the NATS server URL used for distributed cluster coordination.
|
|
2041
|
+
* Use this when coordinator and agent nodes communicate over NATS.
|
|
2042
|
+
*/
|
|
1311
2043
|
static WithNatsServerUrl(context, natsUrl) {
|
|
1312
2044
|
return context.WithNatsServerUrl(natsUrl);
|
|
1313
2045
|
}
|
|
1314
2046
|
static WithNodeType(context, nodeType) {
|
|
1315
2047
|
return context.WithNodeType(nodeType);
|
|
1316
2048
|
}
|
|
2049
|
+
/**
|
|
2050
|
+
* Disables local report generation.
|
|
2051
|
+
* Use this when reports are unnecessary or should be handled exclusively by sinks.
|
|
2052
|
+
*/
|
|
1317
2053
|
static WithoutReports(context) {
|
|
1318
2054
|
return context.WithoutReports();
|
|
1319
2055
|
}
|
|
2056
|
+
/**
|
|
2057
|
+
* Sets the base file name for generated reports.
|
|
2058
|
+
* Use this when exported reports should use a predictable naming convention.
|
|
2059
|
+
*/
|
|
1320
2060
|
static WithReportFileName(context, reportFileName) {
|
|
1321
2061
|
return context.WithReportFileName(reportFileName);
|
|
1322
2062
|
}
|
|
2063
|
+
/**
|
|
2064
|
+
* Sets the output folder for generated reports.
|
|
2065
|
+
* Use this when report files should land in a specific directory.
|
|
2066
|
+
*/
|
|
1323
2067
|
static WithReportFolder(context, reportFolderPath) {
|
|
1324
2068
|
return context.WithReportFolder(reportFolderPath);
|
|
1325
2069
|
}
|
|
1326
2070
|
static WithReportFormats(context, ...reportFormats) {
|
|
1327
2071
|
return context.WithReportFormats(...reportFormats);
|
|
1328
2072
|
}
|
|
2073
|
+
/**
|
|
2074
|
+
* Sets the realtime reporting cadence.
|
|
2075
|
+
* Use this when sinks or dashboards should receive updates at a controlled interval.
|
|
2076
|
+
*/
|
|
1329
2077
|
static WithReportingInterval(context, intervalSeconds) {
|
|
1330
2078
|
return context.WithReportingInterval(intervalSeconds);
|
|
1331
2079
|
}
|
|
2080
|
+
/**
|
|
2081
|
+
* Registers one or more reporting sinks.
|
|
2082
|
+
* Use this when run results must be pushed to external observability or storage systems.
|
|
2083
|
+
*/
|
|
1332
2084
|
static WithReportingSinks(context, ...sinks) {
|
|
1333
2085
|
return context.WithReportingSinks(...sinks);
|
|
1334
2086
|
}
|
|
2087
|
+
/**
|
|
2088
|
+
* Registers runtime policies for the run.
|
|
2089
|
+
* Use this when scenario selection or step execution should obey policy callbacks.
|
|
2090
|
+
*/
|
|
1335
2091
|
static WithRuntimePolicies(context, ...policies) {
|
|
1336
2092
|
return context.WithRuntimePolicies(...policies);
|
|
1337
2093
|
}
|
|
1338
2094
|
static WithRuntimePolicyErrorMode(context, mode) {
|
|
1339
2095
|
return context.WithRuntimePolicyErrorMode(mode);
|
|
1340
2096
|
}
|
|
2097
|
+
/**
|
|
2098
|
+
* Sets the timeout for scenario completion.
|
|
2099
|
+
* Use this when long-running scenarios need an explicit completion window.
|
|
2100
|
+
*/
|
|
1341
2101
|
static WithScenarioCompletionTimeout(context, timeoutSeconds) {
|
|
1342
2102
|
return context.WithScenarioCompletionTimeout(timeoutSeconds);
|
|
1343
2103
|
}
|
|
2104
|
+
/**
|
|
2105
|
+
* Sets the timeout for cluster command round-trips.
|
|
2106
|
+
* Use this when distributed control messages need a tighter or looser deadline.
|
|
2107
|
+
*/
|
|
1344
2108
|
static WithClusterCommandTimeout(context, timeoutSeconds) {
|
|
1345
2109
|
return context.WithClusterCommandTimeout(timeoutSeconds);
|
|
1346
2110
|
}
|
|
2111
|
+
/**
|
|
2112
|
+
* Sets the retry limit for restartable failed iterations.
|
|
2113
|
+
* Use this when transient failures should be retried a fixed number of times.
|
|
2114
|
+
*/
|
|
1347
2115
|
static WithRestartIterationMaxAttempts(context, attempts) {
|
|
1348
2116
|
return context.WithRestartIterationMaxAttempts(attempts);
|
|
1349
2117
|
}
|
|
2118
|
+
/**
|
|
2119
|
+
* Sets the session identifier for this run.
|
|
2120
|
+
* Use this when downstream logs, reports, or external systems need a stable session id.
|
|
2121
|
+
*/
|
|
1350
2122
|
static WithSessionId(context, sessionId) {
|
|
1351
2123
|
return context.WithSessionId(sessionId);
|
|
1352
2124
|
}
|
|
2125
|
+
/**
|
|
2126
|
+
* Targets a shared set of scenarios.
|
|
2127
|
+
* Use this when only selected scenarios should execute for the current node or run.
|
|
2128
|
+
*/
|
|
1353
2129
|
static WithTargetScenarios(context, ...scenarioNames) {
|
|
1354
2130
|
return context.WithTargetScenarios(...scenarioNames);
|
|
1355
2131
|
}
|
|
2132
|
+
/**
|
|
2133
|
+
* Sets the test name label for the run.
|
|
2134
|
+
* Use this when reports and logs should expose a human-readable test identifier.
|
|
2135
|
+
*/
|
|
1356
2136
|
static WithTestName(context, testName) {
|
|
1357
2137
|
return context.WithTestName(testName);
|
|
1358
2138
|
}
|
|
2139
|
+
/**
|
|
2140
|
+
* Sets the test suite label for the run.
|
|
2141
|
+
* Use this when related tests should be grouped under a suite name.
|
|
2142
|
+
*/
|
|
1359
2143
|
static WithTestSuite(context, testSuite) {
|
|
1360
2144
|
return context.WithTestSuite(testSuite);
|
|
1361
2145
|
}
|
|
2146
|
+
/**
|
|
2147
|
+
* Registers worker plugins for the run.
|
|
2148
|
+
* Use this when custom plugin data should be collected alongside run results.
|
|
2149
|
+
*/
|
|
1362
2150
|
static WithWorkerPlugins(context, ...plugins) {
|
|
1363
2151
|
return context.WithWorkerPlugins(...plugins);
|
|
1364
2152
|
}
|
|
2153
|
+
/**
|
|
2154
|
+
* Adds a scenario to the current runner.
|
|
2155
|
+
* Use this when the run should include one more scenario definition.
|
|
2156
|
+
*/
|
|
1365
2157
|
addScenario(scenario) {
|
|
1366
2158
|
if (!(scenario instanceof LoadStrikeScenario)) {
|
|
1367
2159
|
throw new TypeError("Scenario must be provided.");
|
|
@@ -1369,9 +2161,17 @@ export class LoadStrikeRunner {
|
|
|
1369
2161
|
this.scenarios = [...this.scenarios, scenario];
|
|
1370
2162
|
return this;
|
|
1371
2163
|
}
|
|
2164
|
+
/**
|
|
2165
|
+
* Adds a scenario to the current runner.
|
|
2166
|
+
* Use this when the run should include one more scenario definition.
|
|
2167
|
+
*/
|
|
1372
2168
|
AddScenario(scenario) {
|
|
1373
2169
|
return this.addScenario(scenario);
|
|
1374
2170
|
}
|
|
2171
|
+
/**
|
|
2172
|
+
* Adds multiple scenarios to the current runner.
|
|
2173
|
+
* Use this when the run should execute a batch of scenario definitions together.
|
|
2174
|
+
*/
|
|
1375
2175
|
addScenarios(...scenarios) {
|
|
1376
2176
|
if (!scenarios.length) {
|
|
1377
2177
|
throw new Error("At least one scenario must be provided.");
|
|
@@ -1382,9 +2182,17 @@ export class LoadStrikeRunner {
|
|
|
1382
2182
|
this.scenarios = [...this.scenarios, ...scenarios];
|
|
1383
2183
|
return this;
|
|
1384
2184
|
}
|
|
2185
|
+
/**
|
|
2186
|
+
* Adds multiple scenarios to the current runner.
|
|
2187
|
+
* Use this when the run should execute a batch of scenario definitions together.
|
|
2188
|
+
*/
|
|
1385
2189
|
AddScenarios(...scenarios) {
|
|
1386
2190
|
return this.addScenarios(...scenarios);
|
|
1387
2191
|
}
|
|
2192
|
+
/**
|
|
2193
|
+
* Applies a grouped configuration change to the current builder or context.
|
|
2194
|
+
* Use this when several related settings should be supplied in one step.
|
|
2195
|
+
*/
|
|
1388
2196
|
configure(options) {
|
|
1389
2197
|
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
|
1390
2198
|
throw new TypeError("Configure options must be a non-null object.");
|
|
@@ -1411,6 +2219,10 @@ export class LoadStrikeRunner {
|
|
|
1411
2219
|
}
|
|
1412
2220
|
return this.configure(input);
|
|
1413
2221
|
}
|
|
2222
|
+
/**
|
|
2223
|
+
* Copies settings from an existing context snapshot.
|
|
2224
|
+
* Use this when a runner should inherit configuration that was already assembled elsewhere.
|
|
2225
|
+
*/
|
|
1414
2226
|
configureContext(context) {
|
|
1415
2227
|
if (!context || typeof context !== "object" || Array.isArray(context)) {
|
|
1416
2228
|
throw new TypeError("Configure context must be a LoadStrikeContext or run context object.");
|
|
@@ -1420,66 +2232,138 @@ export class LoadStrikeRunner {
|
|
|
1420
2232
|
: new LoadStrikeContext(context);
|
|
1421
2233
|
return this.configure(runtimeContext.toRunnerOptions());
|
|
1422
2234
|
}
|
|
2235
|
+
/**
|
|
2236
|
+
* Copies settings from an existing context snapshot.
|
|
2237
|
+
* Use this when a runner should inherit configuration that was already assembled elsewhere.
|
|
2238
|
+
*/
|
|
1423
2239
|
ConfigureContext(context) {
|
|
1424
2240
|
return this.configureContext(context);
|
|
1425
2241
|
}
|
|
2242
|
+
/**
|
|
2243
|
+
* Sets the test suite label for the run.
|
|
2244
|
+
* Use this when related tests should be grouped under a suite name.
|
|
2245
|
+
*/
|
|
1426
2246
|
withTestSuite(testSuite) {
|
|
1427
2247
|
return this.configure({ testSuite: requireNonEmpty(testSuite, "Test suite must be provided.") });
|
|
1428
2248
|
}
|
|
2249
|
+
/**
|
|
2250
|
+
* Sets the test suite label for the run.
|
|
2251
|
+
* Use this when related tests should be grouped under a suite name.
|
|
2252
|
+
*/
|
|
1429
2253
|
WithTestSuite(testSuite) {
|
|
1430
2254
|
return this.withTestSuite(testSuite);
|
|
1431
2255
|
}
|
|
2256
|
+
/**
|
|
2257
|
+
* Sets the test name label for the run.
|
|
2258
|
+
* Use this when reports and logs should expose a human-readable test identifier.
|
|
2259
|
+
*/
|
|
1432
2260
|
withTestName(testName) {
|
|
1433
2261
|
return this.configure({ testName: requireNonEmpty(testName, "Test name must be provided.") });
|
|
1434
2262
|
}
|
|
2263
|
+
/**
|
|
2264
|
+
* Sets the test name label for the run.
|
|
2265
|
+
* Use this when reports and logs should expose a human-readable test identifier.
|
|
2266
|
+
*/
|
|
1435
2267
|
WithTestName(testName) {
|
|
1436
2268
|
return this.withTestName(testName);
|
|
1437
2269
|
}
|
|
2270
|
+
/**
|
|
2271
|
+
* Sets the session identifier for this run.
|
|
2272
|
+
* Use this when downstream logs, reports, or external systems need a stable session id.
|
|
2273
|
+
*/
|
|
1438
2274
|
withSessionId(sessionId) {
|
|
1439
2275
|
return this.configure({ sessionId: requireNonEmpty(sessionId, "Session id must be provided.") });
|
|
1440
2276
|
}
|
|
2277
|
+
/**
|
|
2278
|
+
* Sets the session identifier for this run.
|
|
2279
|
+
* Use this when downstream logs, reports, or external systems need a stable session id.
|
|
2280
|
+
*/
|
|
1441
2281
|
WithSessionId(sessionId) {
|
|
1442
2282
|
return this.withSessionId(sessionId);
|
|
1443
2283
|
}
|
|
2284
|
+
/**
|
|
2285
|
+
* Sets the output folder for generated reports.
|
|
2286
|
+
* Use this when report files should land in a specific directory.
|
|
2287
|
+
*/
|
|
1444
2288
|
withReportFolder(reportFolderPath) {
|
|
1445
2289
|
return this.configure({ reportFolderPath: requireNonEmpty(reportFolderPath, "Report folder path must be provided.") });
|
|
1446
2290
|
}
|
|
2291
|
+
/**
|
|
2292
|
+
* Sets the output folder for generated reports.
|
|
2293
|
+
* Use this when report files should land in a specific directory.
|
|
2294
|
+
*/
|
|
1447
2295
|
WithReportFolder(reportFolderPath) {
|
|
1448
2296
|
return this.withReportFolder(reportFolderPath);
|
|
1449
2297
|
}
|
|
2298
|
+
/**
|
|
2299
|
+
* Sets the realtime reporting cadence.
|
|
2300
|
+
* Use this when sinks or dashboards should receive updates at a controlled interval.
|
|
2301
|
+
*/
|
|
1450
2302
|
withReportingInterval(intervalSeconds) {
|
|
1451
2303
|
if (!Number.isFinite(intervalSeconds) || intervalSeconds <= 0) {
|
|
1452
2304
|
throw new RangeError("Reporting interval should be greater than zero.");
|
|
1453
2305
|
}
|
|
1454
2306
|
return this.configure({ reportingIntervalSeconds: intervalSeconds });
|
|
1455
2307
|
}
|
|
2308
|
+
/**
|
|
2309
|
+
* Sets the realtime reporting cadence.
|
|
2310
|
+
* Use this when sinks or dashboards should receive updates at a controlled interval.
|
|
2311
|
+
*/
|
|
1456
2312
|
WithReportingInterval(intervalSeconds) {
|
|
1457
2313
|
return this.withReportingInterval(intervalSeconds);
|
|
1458
2314
|
}
|
|
2315
|
+
/**
|
|
2316
|
+
* Sets the timeout for cluster command round-trips.
|
|
2317
|
+
* Use this when distributed control messages need a tighter or looser deadline.
|
|
2318
|
+
*/
|
|
1459
2319
|
withClusterCommandTimeout(timeoutSeconds) {
|
|
1460
2320
|
if (!Number.isFinite(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
1461
2321
|
throw new RangeError("Cluster command timeout should be greater than zero.");
|
|
1462
2322
|
}
|
|
1463
2323
|
return this.configure({ clusterCommandTimeoutSeconds: timeoutSeconds });
|
|
1464
2324
|
}
|
|
2325
|
+
/**
|
|
2326
|
+
* Sets the timeout for cluster command round-trips.
|
|
2327
|
+
* Use this when distributed control messages need a tighter or looser deadline.
|
|
2328
|
+
*/
|
|
1465
2329
|
WithClusterCommandTimeout(timeoutSeconds) {
|
|
1466
2330
|
return this.withClusterCommandTimeout(timeoutSeconds);
|
|
1467
2331
|
}
|
|
2332
|
+
/**
|
|
2333
|
+
* Sets the retry limit for restartable failed iterations.
|
|
2334
|
+
* Use this when transient failures should be retried a fixed number of times.
|
|
2335
|
+
*/
|
|
1468
2336
|
withRestartIterationMaxAttempts(attempts) {
|
|
1469
2337
|
if (!Number.isFinite(attempts) || attempts < 0) {
|
|
1470
2338
|
throw new RangeError("Restart iteration max attempts should be zero or greater.");
|
|
1471
2339
|
}
|
|
1472
2340
|
return this.configure({ restartIterationMaxAttempts: Math.trunc(attempts) });
|
|
1473
2341
|
}
|
|
2342
|
+
/**
|
|
2343
|
+
* Sets the retry limit for restartable failed iterations.
|
|
2344
|
+
* Use this when transient failures should be retried a fixed number of times.
|
|
2345
|
+
*/
|
|
1474
2346
|
WithRestartIterationMaxAttempts(attempts) {
|
|
1475
2347
|
return this.withRestartIterationMaxAttempts(attempts);
|
|
1476
2348
|
}
|
|
2349
|
+
/**
|
|
2350
|
+
* Disables local report generation.
|
|
2351
|
+
* Use this when reports are unnecessary or should be handled exclusively by sinks.
|
|
2352
|
+
*/
|
|
1477
2353
|
withoutReports() {
|
|
1478
2354
|
return this.configure({ reportsEnabled: false });
|
|
1479
2355
|
}
|
|
2356
|
+
/**
|
|
2357
|
+
* Disables local report generation.
|
|
2358
|
+
* Use this when reports are unnecessary or should be handled exclusively by sinks.
|
|
2359
|
+
*/
|
|
1480
2360
|
WithoutReports() {
|
|
1481
2361
|
return this.withoutReports();
|
|
1482
2362
|
}
|
|
2363
|
+
/**
|
|
2364
|
+
* Builds the current configuration into a runnable context.
|
|
2365
|
+
* Use this when you want to inspect or reuse the final run settings before execution.
|
|
2366
|
+
*/
|
|
1483
2367
|
buildContext() {
|
|
1484
2368
|
if (!this.scenarios.length) {
|
|
1485
2369
|
throw new Error("At least one scenario must be added before building the runner context.");
|
|
@@ -1494,6 +2378,10 @@ export class LoadStrikeRunner {
|
|
|
1494
2378
|
}
|
|
1495
2379
|
return context;
|
|
1496
2380
|
}
|
|
2381
|
+
/**
|
|
2382
|
+
* Builds the current configuration into a runnable context.
|
|
2383
|
+
* Use this when you want to inspect or reuse the final run settings before execution.
|
|
2384
|
+
*/
|
|
1497
2385
|
BuildContext() {
|
|
1498
2386
|
return this.buildContext();
|
|
1499
2387
|
}
|
|
@@ -1550,14 +2438,17 @@ export class LoadStrikeRunner {
|
|
|
1550
2438
|
const selectedScenarios = clusterMode === "local-coordinator" || clusterMode === "nats-coordinator"
|
|
1551
2439
|
? await this.filterScenariosWithPolicies(this.scenarios, policies, policyErrors, runtimePolicyErrorMode)
|
|
1552
2440
|
: await this.selectScenarios(policies, policyErrors, runtimePolicyErrorMode);
|
|
1553
|
-
|
|
2441
|
+
if (clusterMode === "nats-agent") {
|
|
2442
|
+
return this.runAgentWithNats(createdUtc, testInfo, nodeInfo);
|
|
2443
|
+
}
|
|
2444
|
+
licensePayload = buildLicenseValidationPayload({
|
|
2445
|
+
...this.options,
|
|
2446
|
+
sessionId: testInfo.sessionId
|
|
2447
|
+
}, this.scenarios);
|
|
1554
2448
|
licenseClient = new LoadStrikeLocalClient({
|
|
1555
2449
|
licenseValidationTimeoutMs: Math.max((this.options.licenseValidationTimeoutSeconds ?? 10) * 1000, 1)
|
|
1556
2450
|
});
|
|
1557
2451
|
licenseSession = await licenseClient.acquireLicenseLease(licensePayload);
|
|
1558
|
-
if (clusterMode === "nats-agent") {
|
|
1559
|
-
return this.runAgentWithNats(createdUtc, testInfo, nodeInfo);
|
|
1560
|
-
}
|
|
1561
2452
|
const loggerSetup = createLoggerSetup(this.options.loggerConfig, this.options.minimumLogLevel, this.options, testInfo, nodeInfo);
|
|
1562
2453
|
const runLogger = loggerSetup.logger;
|
|
1563
2454
|
const scenarioStartInfos = selectedScenarios.map((scenario, index) => {
|
|
@@ -1647,12 +2538,12 @@ export class LoadStrikeRunner {
|
|
|
1647
2538
|
let result;
|
|
1648
2539
|
let metricStats;
|
|
1649
2540
|
if (clusterMode === "local-coordinator") {
|
|
1650
|
-
const aggregated = await this.runCoordinatorWithLocalAgents(selectedScenarios, testInfo, nodeInfo);
|
|
2541
|
+
const aggregated = await this.runCoordinatorWithLocalAgents(selectedScenarios, testInfo, nodeInfo, licenseClient, licenseSession);
|
|
1651
2542
|
metricStats = aggregated.metrics;
|
|
1652
2543
|
result = toDetailedRunResultFromNodeStats(aggregated, started.toISOString(), sinkErrors, policyErrors);
|
|
1653
2544
|
}
|
|
1654
2545
|
else if (clusterMode === "nats-coordinator") {
|
|
1655
|
-
const aggregated = await this.runCoordinatorWithNats(selectedScenarios, testInfo, nodeInfo);
|
|
2546
|
+
const aggregated = await this.runCoordinatorWithNats(selectedScenarios, testInfo, nodeInfo, licenseClient, licenseSession);
|
|
1656
2547
|
metricStats = aggregated.metrics;
|
|
1657
2548
|
result = toDetailedRunResultFromNodeStats(aggregated, started.toISOString(), sinkErrors, policyErrors);
|
|
1658
2549
|
}
|
|
@@ -1799,8 +2690,8 @@ export class LoadStrikeRunner {
|
|
|
1799
2690
|
natsServerUrl: undefined,
|
|
1800
2691
|
reportFolderPath: resolve(this.options.reportFolderPath ?? "./reports", sanitizeReportFileName(machineName)),
|
|
1801
2692
|
targetScenarios,
|
|
1802
|
-
agentTargetScenarios:
|
|
1803
|
-
coordinatorTargetScenarios:
|
|
2693
|
+
agentTargetScenarios: undefined,
|
|
2694
|
+
coordinatorTargetScenarios: undefined,
|
|
1804
2695
|
reportsEnabled: false,
|
|
1805
2696
|
displayConsoleMetrics: false,
|
|
1806
2697
|
reportingSinks: includeWorkerExtensions ? this.options.reportingSinks : [],
|
|
@@ -1818,16 +2709,40 @@ export class LoadStrikeRunner {
|
|
|
1818
2709
|
logFiles: [...(childResult.logFiles ?? [])]
|
|
1819
2710
|
};
|
|
1820
2711
|
}
|
|
1821
|
-
async runCoordinatorWithLocalAgents(scenarios, testInfo, nodeInfo) {
|
|
2712
|
+
async runCoordinatorWithLocalAgents(scenarios, testInfo, nodeInfo, licenseClient, licenseSession) {
|
|
2713
|
+
if (!licenseClient) {
|
|
2714
|
+
throw new Error("Coordinator agent execution authorization requires an initialized licensing client.");
|
|
2715
|
+
}
|
|
2716
|
+
const controllerRunToken = stringValueOrDefault(licenseSession?.runToken, "").trim();
|
|
2717
|
+
if (!controllerRunToken) {
|
|
2718
|
+
throw new Error("Coordinator agent execution authorization requires an active controller run token.");
|
|
2719
|
+
}
|
|
1822
2720
|
const assignments = planRuntimeClusterAssignments(scenarios, Math.max(this.options.agentsCount ?? 1, 1), this.options.targetScenarios ?? [], this.options.agentTargetScenarios ?? []);
|
|
1823
|
-
const nodeResults = await Promise.all(assignments.map((targetScenarios, index) =>
|
|
2721
|
+
const nodeResults = await Promise.all(assignments.map(async (targetScenarios, index) => {
|
|
2722
|
+
const commandId = randomBytes(16).toString("hex");
|
|
2723
|
+
const agentExecutionToken = await licenseClient.createAgentExecutionToken(controllerRunToken, testInfo.sessionId, commandId, index, assignments.length, targetScenarios);
|
|
2724
|
+
return this.runClusterChildNode(targetScenarios, "Agent", `local-agent-${index + 1}`, false, {
|
|
2725
|
+
sessionId: testInfo.sessionId,
|
|
2726
|
+
testSuite: testInfo.testSuite,
|
|
2727
|
+
testName: testInfo.testName,
|
|
2728
|
+
agentCommandId: commandId,
|
|
2729
|
+
agentExecutionToken
|
|
2730
|
+
});
|
|
2731
|
+
}));
|
|
1824
2732
|
const coordinatorTargets = [...(this.options.coordinatorTargetScenarios ?? [])];
|
|
1825
2733
|
if (coordinatorTargets.length) {
|
|
1826
2734
|
nodeResults.push(await this.runClusterChildNode(coordinatorTargets, "Coordinator", nodeInfo.machineName, false));
|
|
1827
2735
|
}
|
|
1828
2736
|
return aggregateNodeStats(testInfo, { ...nodeInfo, nodeType: "Coordinator" }, nodeResults);
|
|
1829
2737
|
}
|
|
1830
|
-
async runCoordinatorWithNats(scenarios, testInfo, nodeInfo) {
|
|
2738
|
+
async runCoordinatorWithNats(scenarios, testInfo, nodeInfo, licenseClient, licenseSession) {
|
|
2739
|
+
if (!licenseClient) {
|
|
2740
|
+
throw new Error("Coordinator agent execution authorization requires an initialized licensing client.");
|
|
2741
|
+
}
|
|
2742
|
+
const controllerRunToken = stringValueOrDefault(licenseSession?.runToken, "").trim();
|
|
2743
|
+
if (!controllerRunToken) {
|
|
2744
|
+
throw new Error("Coordinator agent execution authorization requires an active controller run token.");
|
|
2745
|
+
}
|
|
1831
2746
|
const assignments = planRuntimeClusterAssignments(scenarios, Math.max(this.options.agentsCount ?? 1, 1), this.options.targetScenarios ?? [], this.options.agentTargetScenarios ?? []);
|
|
1832
2747
|
const coordinator = new DistributedClusterCoordinator({
|
|
1833
2748
|
clusterId: this.options.clusterId ?? "local",
|
|
@@ -1841,7 +2756,7 @@ export class LoadStrikeRunner {
|
|
|
1841
2756
|
? { ServerUrl: this.options.natsServerUrl }
|
|
1842
2757
|
: undefined
|
|
1843
2758
|
});
|
|
1844
|
-
const dispatch = await coordinator.dispatch(assignments);
|
|
2759
|
+
const dispatch = await coordinator.dispatch(assignments, (command) => licenseClient.createAgentExecutionToken(controllerRunToken, testInfo.sessionId, command.commandId, command.agentIndex, command.agentCount, command.targetScenarios));
|
|
1845
2760
|
const nodes = dispatch.nodeResults.map((value) => clusterNodeResultToNodeStats(value, testInfo, { ...nodeInfo, nodeType: "Agent" }));
|
|
1846
2761
|
const coordinatorTargets = [...(this.options.coordinatorTargetScenarios ?? [])];
|
|
1847
2762
|
if (coordinatorTargets.length) {
|
|
@@ -1871,7 +2786,9 @@ export class LoadStrikeRunner {
|
|
|
1871
2786
|
handledStats = await this.runClusterChildNode(dispatch.scenarioNames, "Agent", nodeInfo.machineName, true, {
|
|
1872
2787
|
sessionId: testInfo.sessionId,
|
|
1873
2788
|
testSuite: testInfo.testSuite,
|
|
1874
|
-
testName: testInfo.testName
|
|
2789
|
+
testName: testInfo.testName,
|
|
2790
|
+
agentCommandId: dispatch.commandId,
|
|
2791
|
+
agentExecutionToken: dispatch.agentRunToken
|
|
1875
2792
|
});
|
|
1876
2793
|
return {
|
|
1877
2794
|
nodeId: handledStats.nodeInfo.machineName,
|
|
@@ -6513,10 +7430,16 @@ function toRunContext(options) {
|
|
|
6513
7430
|
RestartIterationMaxAttempts: normalized.restartIterationMaxAttempts,
|
|
6514
7431
|
WorkerPlugins: normalized.workerPlugins,
|
|
6515
7432
|
CustomSettings: normalized.customSettings,
|
|
6516
|
-
GlobalCustomSettings: normalized.globalCustomSettings
|
|
7433
|
+
GlobalCustomSettings: normalized.globalCustomSettings,
|
|
7434
|
+
AgentExecutionToken: normalized.agentExecutionToken,
|
|
7435
|
+
AgentCommandId: normalized.agentCommandId
|
|
6517
7436
|
};
|
|
6518
7437
|
}
|
|
6519
7438
|
class RuntimePolicyCallbackError extends Error {
|
|
7439
|
+
/**
|
|
7440
|
+
* Exposes the public constructor operation.
|
|
7441
|
+
* Use this when the surrounding wrapper type makes this operation the clearest way to express your intent.
|
|
7442
|
+
*/
|
|
6520
7443
|
constructor(message) {
|
|
6521
7444
|
super(message);
|
|
6522
7445
|
this.name = "RuntimePolicyCallbackError";
|
|
@@ -6540,17 +7463,24 @@ function buildLicenseValidationPayload(options, scenarios) {
|
|
|
6540
7463
|
const context = {
|
|
6541
7464
|
...toRunContext(options)
|
|
6542
7465
|
};
|
|
6543
|
-
const scenarioSpecs = scenarios.map((scenario) =>
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
7466
|
+
const scenarioSpecs = scenarios.map((scenario) => {
|
|
7467
|
+
const row = {
|
|
7468
|
+
Name: scenario.name,
|
|
7469
|
+
MaxFailCount: scenario.getMaxFailCount(),
|
|
7470
|
+
RestartIterationOnFail: scenario.shouldRestartIterationOnFail(),
|
|
7471
|
+
WithoutWarmUp: scenario.isWithoutWarmUp(),
|
|
7472
|
+
WarmUpDurationSeconds: scenario.getWarmUpDurationSeconds(),
|
|
7473
|
+
Weight: scenario.getWeight(),
|
|
7474
|
+
LoadSimulations: [...scenario.getSimulations()],
|
|
7475
|
+
Thresholds: [...scenario.getThresholds()],
|
|
7476
|
+
Tracking: scenario.getTrackingConfiguration() ?? {}
|
|
7477
|
+
};
|
|
7478
|
+
const internalLicenseFeatures = scenario.__loadStrikeInternalLicenseFeatures();
|
|
7479
|
+
if (internalLicenseFeatures.length > 0) {
|
|
7480
|
+
row.InternalLicenseFeatures = internalLicenseFeatures;
|
|
7481
|
+
}
|
|
7482
|
+
return row;
|
|
7483
|
+
});
|
|
6554
7484
|
return {
|
|
6555
7485
|
Context: context,
|
|
6556
7486
|
Scenarios: scenarioSpecs,
|