@loadstrike/loadstrike-sdk 0.1.10001 → 1.0.10801
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 +8 -8
- package/dist/cjs/cluster.js +18 -1
- package/dist/cjs/correlation.js +69 -11
- package/dist/cjs/index.js +2 -14
- package/dist/cjs/local.js +88 -18
- package/dist/cjs/reporting.js +19 -5
- package/dist/cjs/runtime.js +526 -264
- package/dist/cjs/sinks.js +200 -106
- package/dist/cjs/transports.js +104 -18
- package/dist/esm/cluster.js +17 -0
- package/dist/esm/correlation.js +68 -10
- package/dist/esm/index.js +2 -4
- package/dist/esm/local.js +86 -16
- package/dist/esm/reporting.js +18 -2
- package/dist/esm/runtime.js +527 -264
- package/dist/esm/sinks.js +199 -105
- package/dist/esm/transports.js +103 -17
- package/dist/types/cluster.d.ts +30 -0
- package/dist/types/contracts.d.ts +15 -15
- package/dist/types/correlation.d.ts +41 -1
- package/dist/types/index.d.ts +4 -8
- package/dist/types/local.d.ts +146 -2
- package/dist/types/reporting.d.ts +33 -0
- package/dist/types/runtime.d.ts +464 -77
- package/dist/types/sinks.d.ts +212 -21
- package/dist/types/transports.d.ts +142 -0
- package/package.json +8 -19
package/dist/cjs/sinks.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OtelCollectorReportingSink = exports.SplunkReportingSink = exports.DatadogReportingSink = exports.TimescaleDbReportingSink = exports.GrafanaLokiReportingSink = exports.InfluxDbReportingSink = exports.CompositeReportingSink = exports.ConsoleReportingSink = exports.MemoryReportingSink = exports.OtelCollectorReportingSinkOptions = exports.SplunkReportingSinkOptions = exports.DatadogReportingSinkOptions = exports.TimescaleDbReportingSinkOptions = exports.GrafanaLokiReportingSinkOptions = exports.InfluxDbReportingSinkOptions = void 0;
|
|
3
|
+
exports.__loadstrikeTestExports = exports.OtelCollectorReportingSink = exports.SplunkReportingSink = exports.DatadogReportingSink = exports.TimescaleDbReportingSink = exports.GrafanaLokiReportingSink = exports.InfluxDbReportingSink = exports.CompositeReportingSink = exports.ConsoleReportingSink = exports.MemoryReportingSink = exports.OtelCollectorReportingSinkOptions = exports.SplunkReportingSinkOptions = exports.DatadogReportingSinkOptions = exports.TimescaleDbReportingSinkOptions = exports.GrafanaLokiReportingSinkOptions = exports.InfluxDbReportingSinkOptions = void 0;
|
|
4
4
|
const runtime_js_1 = require("./runtime.js");
|
|
5
5
|
const pg_1 = require("pg");
|
|
6
6
|
const DEFAULT_INFLUX_CONFIGURATION_SECTION_PATH = "LoadStrike:ReportingSinks:InfluxDb";
|
|
@@ -244,13 +244,8 @@ class MemoryReportingSink {
|
|
|
244
244
|
SaveRealtimeMetrics(metrics) {
|
|
245
245
|
this.saveRealtimeMetrics(metrics);
|
|
246
246
|
}
|
|
247
|
-
saveFinalStats(result) {
|
|
248
|
-
this.finalResults.push(cloneNodeStats(result));
|
|
249
|
-
}
|
|
250
|
-
SaveFinalStats(result) {
|
|
251
|
-
this.saveFinalStats(result);
|
|
252
|
-
}
|
|
253
247
|
saveRunResult(result) {
|
|
248
|
+
this.finalResults.push(cloneRunResult(result));
|
|
254
249
|
this.runResults.push(deepCloneRecord(result));
|
|
255
250
|
}
|
|
256
251
|
SaveRunResult(result) {
|
|
@@ -293,13 +288,9 @@ class ConsoleReportingSink {
|
|
|
293
288
|
SaveRealtimeMetrics(metrics) {
|
|
294
289
|
this.saveRealtimeMetrics(metrics);
|
|
295
290
|
}
|
|
296
|
-
|
|
291
|
+
saveRunResult(result) {
|
|
297
292
|
this.writeLine(`final requests=${result.allRequestCount} ok=${result.allOkCount} fail=${result.allFailCount} failedThresholds=${result.failedThresholds}`);
|
|
298
293
|
}
|
|
299
|
-
SaveFinalStats(result) {
|
|
300
|
-
this.saveFinalStats(result);
|
|
301
|
-
}
|
|
302
|
-
saveRunResult(_result) { }
|
|
303
294
|
SaveRunResult(result) {
|
|
304
295
|
this.saveRunResult(result);
|
|
305
296
|
}
|
|
@@ -369,17 +360,6 @@ class CompositeReportingSink {
|
|
|
369
360
|
async SaveRealtimeMetrics(metrics) {
|
|
370
361
|
await this.saveRealtimeMetrics(metrics);
|
|
371
362
|
}
|
|
372
|
-
async saveFinalStats(result) {
|
|
373
|
-
for (const sink of this.sinks) {
|
|
374
|
-
const saveFinalStats = sink.saveFinalStats ?? sink.SaveFinalStats;
|
|
375
|
-
if (saveFinalStats) {
|
|
376
|
-
await saveFinalStats.call(sink, result);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
async SaveFinalStats(result) {
|
|
381
|
-
await this.saveFinalStats(result);
|
|
382
|
-
}
|
|
383
363
|
async saveRunResult(result) {
|
|
384
364
|
for (const sink of this.sinks) {
|
|
385
365
|
const saveRunResult = sink.saveRunResult ?? sink.SaveRunResult;
|
|
@@ -466,12 +446,6 @@ class InfluxDbReportingSink {
|
|
|
466
446
|
async SaveRealtimeMetrics(metrics) {
|
|
467
447
|
await this.saveRealtimeMetrics(metrics);
|
|
468
448
|
}
|
|
469
|
-
async saveFinalStats(result) {
|
|
470
|
-
await this.persistEvents(createFinalStatsEvents(this.getSession(), result));
|
|
471
|
-
}
|
|
472
|
-
async SaveFinalStats(result) {
|
|
473
|
-
await this.saveFinalStats(result);
|
|
474
|
-
}
|
|
475
449
|
async saveRunResult(result) {
|
|
476
450
|
await this.persistEvents(createRunResultEvents(this.getSession(), result));
|
|
477
451
|
}
|
|
@@ -582,12 +556,6 @@ class GrafanaLokiReportingSink {
|
|
|
582
556
|
async SaveRealtimeMetrics(metrics) {
|
|
583
557
|
await this.saveRealtimeMetrics(metrics);
|
|
584
558
|
}
|
|
585
|
-
async saveFinalStats(result) {
|
|
586
|
-
await this.persistEvents(createFinalStatsEvents(this.getSession(), result));
|
|
587
|
-
}
|
|
588
|
-
async SaveFinalStats(result) {
|
|
589
|
-
await this.saveFinalStats(result);
|
|
590
|
-
}
|
|
591
559
|
async saveRunResult(result) {
|
|
592
560
|
await this.persistEvents(createRunResultEvents(this.getSession(), result));
|
|
593
561
|
}
|
|
@@ -734,12 +702,6 @@ class TimescaleDbReportingSink {
|
|
|
734
702
|
async SaveRealtimeMetrics(metrics) {
|
|
735
703
|
await this.saveRealtimeMetrics(metrics);
|
|
736
704
|
}
|
|
737
|
-
async saveFinalStats(result) {
|
|
738
|
-
await this.persistEvents(createFinalStatsEvents(this.getSession(), result));
|
|
739
|
-
}
|
|
740
|
-
async SaveFinalStats(result) {
|
|
741
|
-
await this.saveFinalStats(result);
|
|
742
|
-
}
|
|
743
705
|
async saveRunResult(result) {
|
|
744
706
|
await this.persistEvents(createRunResultEvents(this.getSession(), result));
|
|
745
707
|
}
|
|
@@ -1016,12 +978,6 @@ class DatadogReportingSink {
|
|
|
1016
978
|
async SaveRealtimeMetrics(metrics) {
|
|
1017
979
|
await this.saveRealtimeMetrics(metrics);
|
|
1018
980
|
}
|
|
1019
|
-
async saveFinalStats(result) {
|
|
1020
|
-
await this.persistEvents(createFinalStatsEvents(this.getSession(), result));
|
|
1021
|
-
}
|
|
1022
|
-
async SaveFinalStats(result) {
|
|
1023
|
-
await this.saveFinalStats(result);
|
|
1024
|
-
}
|
|
1025
981
|
async saveRunResult(result) {
|
|
1026
982
|
await this.persistEvents(createRunResultEvents(this.getSession(), result));
|
|
1027
983
|
}
|
|
@@ -1145,12 +1101,6 @@ class SplunkReportingSink {
|
|
|
1145
1101
|
async SaveRealtimeMetrics(metrics) {
|
|
1146
1102
|
await this.saveRealtimeMetrics(metrics);
|
|
1147
1103
|
}
|
|
1148
|
-
async saveFinalStats(result) {
|
|
1149
|
-
await this.persistEvents(createFinalStatsEvents(this.getSession(), result));
|
|
1150
|
-
}
|
|
1151
|
-
async SaveFinalStats(result) {
|
|
1152
|
-
await this.saveFinalStats(result);
|
|
1153
|
-
}
|
|
1154
1104
|
async saveRunResult(result) {
|
|
1155
1105
|
await this.persistEvents(createRunResultEvents(this.getSession(), result));
|
|
1156
1106
|
}
|
|
@@ -1254,12 +1204,6 @@ class OtelCollectorReportingSink {
|
|
|
1254
1204
|
async SaveRealtimeMetrics(metrics) {
|
|
1255
1205
|
await this.saveRealtimeMetrics(metrics);
|
|
1256
1206
|
}
|
|
1257
|
-
async saveFinalStats(result) {
|
|
1258
|
-
await this.persistEvents(createFinalStatsEvents(this.getSession(), result));
|
|
1259
|
-
}
|
|
1260
|
-
async SaveFinalStats(result) {
|
|
1261
|
-
await this.saveFinalStats(result);
|
|
1262
|
-
}
|
|
1263
1207
|
async saveRunResult(result) {
|
|
1264
1208
|
await this.persistEvents(createRunResultEvents(this.getSession(), result));
|
|
1265
1209
|
}
|
|
@@ -1374,6 +1318,7 @@ function createFinalStatsEvents(session, stats) {
|
|
|
1374
1318
|
function createRunResultEvents(session, result) {
|
|
1375
1319
|
const occurredUtc = new Date();
|
|
1376
1320
|
const events = [
|
|
1321
|
+
...createFinalStatsEvents(session, runResultToNodeStats(result)),
|
|
1377
1322
|
createReportingEvent(session, occurredUtc, "run.result.final", null, null, {
|
|
1378
1323
|
phase: "final",
|
|
1379
1324
|
entity: "run-result"
|
|
@@ -1468,7 +1413,8 @@ function createStepEvents(session, occurredUtc, phase, scenario) {
|
|
|
1468
1413
|
return events;
|
|
1469
1414
|
}
|
|
1470
1415
|
function createStatusCodeEvents(session, occurredUtc, phase, scenarioName, stepName, resultKind, statusCodes) {
|
|
1471
|
-
|
|
1416
|
+
const normalizedStatusCodes = Array.isArray(statusCodes) ? statusCodes : [];
|
|
1417
|
+
return normalizedStatusCodes.map((statusCode) => createReportingEvent(session, occurredUtc, `status-code.${phase}`, scenarioName, stepName, {
|
|
1472
1418
|
phase,
|
|
1473
1419
|
entity: stepName ? "step-status-code" : "scenario-status-code",
|
|
1474
1420
|
result_kind: resultKind,
|
|
@@ -1601,30 +1547,63 @@ function createReportingEvent(session, occurredUtc, eventType, scenarioName, ste
|
|
|
1601
1547
|
};
|
|
1602
1548
|
}
|
|
1603
1549
|
function addMeasurementFields(fields, prefix, measurement) {
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1550
|
+
const request = measurement?.request ?? { count: 0, percent: 0, rps: 0 };
|
|
1551
|
+
const latency = measurement?.latency ?? {
|
|
1552
|
+
minMs: 0,
|
|
1553
|
+
meanMs: 0,
|
|
1554
|
+
maxMs: 0,
|
|
1555
|
+
percent50: 0,
|
|
1556
|
+
percent75: 0,
|
|
1557
|
+
percent95: 0,
|
|
1558
|
+
percent99: 0,
|
|
1559
|
+
stdDev: 0,
|
|
1560
|
+
latencyCount: {
|
|
1561
|
+
lessOrEq800: 0,
|
|
1562
|
+
more800Less1200: 0,
|
|
1563
|
+
moreOrEq1200: 0
|
|
1564
|
+
}
|
|
1565
|
+
};
|
|
1566
|
+
const latencyCount = latency.latencyCount ?? {
|
|
1567
|
+
lessOrEq800: 0,
|
|
1568
|
+
more800Less1200: 0,
|
|
1569
|
+
moreOrEq1200: 0
|
|
1570
|
+
};
|
|
1571
|
+
const dataTransfer = measurement?.dataTransfer ?? {
|
|
1572
|
+
allBytes: 0,
|
|
1573
|
+
minBytes: 0,
|
|
1574
|
+
meanBytes: 0,
|
|
1575
|
+
maxBytes: 0,
|
|
1576
|
+
percent50: 0,
|
|
1577
|
+
percent75: 0,
|
|
1578
|
+
percent95: 0,
|
|
1579
|
+
percent99: 0,
|
|
1580
|
+
stdDev: 0
|
|
1581
|
+
};
|
|
1582
|
+
const statusCodes = Array.isArray(measurement?.statusCodes) ? measurement.statusCodes : [];
|
|
1583
|
+
fields[`${prefix}_request_count`] = request.count ?? 0;
|
|
1584
|
+
fields[`${prefix}_request_percent`] = request.percent ?? 0;
|
|
1585
|
+
fields[`${prefix}_request_rps`] = request.rps ?? 0;
|
|
1586
|
+
fields[`${prefix}_latency_min_ms`] = latency.minMs ?? 0;
|
|
1587
|
+
fields[`${prefix}_latency_mean_ms`] = latency.meanMs ?? 0;
|
|
1588
|
+
fields[`${prefix}_latency_max_ms`] = latency.maxMs ?? 0;
|
|
1589
|
+
fields[`${prefix}_latency_p50_ms`] = latency.percent50 ?? 0;
|
|
1590
|
+
fields[`${prefix}_latency_p75_ms`] = latency.percent75 ?? 0;
|
|
1591
|
+
fields[`${prefix}_latency_p95_ms`] = latency.percent95 ?? 0;
|
|
1592
|
+
fields[`${prefix}_latency_p99_ms`] = latency.percent99 ?? 0;
|
|
1593
|
+
fields[`${prefix}_latency_std_dev`] = latency.stdDev ?? 0;
|
|
1594
|
+
fields[`${prefix}_latency_le_800_count`] = latencyCount.lessOrEq800 ?? 0;
|
|
1595
|
+
fields[`${prefix}_latency_gt_800_lt_1200_count`] = latencyCount.more800Less1200 ?? 0;
|
|
1596
|
+
fields[`${prefix}_latency_ge_1200_count`] = latencyCount.moreOrEq1200 ?? 0;
|
|
1597
|
+
fields[`${prefix}_bytes_all`] = dataTransfer.allBytes ?? 0;
|
|
1598
|
+
fields[`${prefix}_bytes_min`] = dataTransfer.minBytes ?? 0;
|
|
1599
|
+
fields[`${prefix}_bytes_mean`] = dataTransfer.meanBytes ?? 0;
|
|
1600
|
+
fields[`${prefix}_bytes_max`] = dataTransfer.maxBytes ?? 0;
|
|
1601
|
+
fields[`${prefix}_bytes_p50`] = dataTransfer.percent50 ?? 0;
|
|
1602
|
+
fields[`${prefix}_bytes_p75`] = dataTransfer.percent75 ?? 0;
|
|
1603
|
+
fields[`${prefix}_bytes_p95`] = dataTransfer.percent95 ?? 0;
|
|
1604
|
+
fields[`${prefix}_bytes_p99`] = dataTransfer.percent99 ?? 0;
|
|
1605
|
+
fields[`${prefix}_bytes_std_dev`] = dataTransfer.stdDev ?? 0;
|
|
1606
|
+
fields[`${prefix}_status_code_count`] = statusCodes.length;
|
|
1628
1607
|
}
|
|
1629
1608
|
function buildInfluxWriteUri(options) {
|
|
1630
1609
|
const query = new URLSearchParams({
|
|
@@ -2596,28 +2575,28 @@ function cloneSessionStartInfo(session) {
|
|
|
2596
2575
|
};
|
|
2597
2576
|
}
|
|
2598
2577
|
function cloneNodeInfo(nodeInfo) {
|
|
2599
|
-
return { ...nodeInfo };
|
|
2578
|
+
return { ...(nodeInfo ?? {}) };
|
|
2600
2579
|
}
|
|
2601
2580
|
function cloneTestInfo(testInfo) {
|
|
2602
|
-
return { ...testInfo };
|
|
2581
|
+
return { ...(testInfo ?? {}) };
|
|
2603
2582
|
}
|
|
2604
2583
|
function cloneMetricStats(metrics) {
|
|
2605
2584
|
return {
|
|
2606
|
-
counters: metrics
|
|
2607
|
-
gauges: metrics
|
|
2608
|
-
durationMs: metrics
|
|
2585
|
+
counters: (metrics?.counters ?? []).map((value) => ({ ...value })),
|
|
2586
|
+
gauges: (metrics?.gauges ?? []).map((value) => ({ ...value })),
|
|
2587
|
+
durationMs: metrics?.durationMs ?? 0
|
|
2609
2588
|
};
|
|
2610
2589
|
}
|
|
2611
2590
|
function cloneScenarioStats(value) {
|
|
2612
2591
|
return {
|
|
2613
2592
|
...value,
|
|
2614
|
-
ok: deepCloneRecord(value
|
|
2615
|
-
fail: deepCloneRecord(value
|
|
2616
|
-
loadSimulationStats: { ...value
|
|
2617
|
-
stepStats: value
|
|
2593
|
+
ok: deepCloneRecord(value?.ok ?? {}),
|
|
2594
|
+
fail: deepCloneRecord(value?.fail ?? {}),
|
|
2595
|
+
loadSimulationStats: { ...(value?.loadSimulationStats ?? {}) },
|
|
2596
|
+
stepStats: (value?.stepStats ?? []).map((step) => ({
|
|
2618
2597
|
...step,
|
|
2619
|
-
ok: deepCloneRecord(step
|
|
2620
|
-
fail: deepCloneRecord(step
|
|
2598
|
+
ok: deepCloneRecord(step?.ok ?? {}),
|
|
2599
|
+
fail: deepCloneRecord(step?.fail ?? {})
|
|
2621
2600
|
}))
|
|
2622
2601
|
};
|
|
2623
2602
|
}
|
|
@@ -2626,20 +2605,91 @@ function cloneNodeStats(result) {
|
|
|
2626
2605
|
...result,
|
|
2627
2606
|
nodeInfo: cloneNodeInfo(result.nodeInfo),
|
|
2628
2607
|
testInfo: cloneTestInfo(result.testInfo),
|
|
2629
|
-
thresholds: result.thresholds.map((value) => ({ ...value })),
|
|
2630
|
-
thresholdResults: result.thresholdResults.map((value) => ({ ...value })),
|
|
2608
|
+
thresholds: (result.thresholds ?? []).map((value) => ({ ...value })),
|
|
2609
|
+
thresholdResults: (result.thresholdResults ?? []).map((value) => ({ ...value })),
|
|
2631
2610
|
metrics: cloneMetricStats(result.metrics),
|
|
2632
|
-
metricValues: result.metricValues.map((value) => ({ ...value })),
|
|
2633
|
-
scenarioStats: result.scenarioStats.map((value) => cloneScenarioStats(value)),
|
|
2634
|
-
stepStats: result.stepStats.map((step) => ({
|
|
2611
|
+
metricValues: Array.isArray(result.metricValues) ? result.metricValues.map((value) => ({ ...value })) : [],
|
|
2612
|
+
scenarioStats: (result.scenarioStats ?? []).map((value) => cloneScenarioStats(value)),
|
|
2613
|
+
stepStats: (result.stepStats ?? []).map((step) => ({
|
|
2614
|
+
...step,
|
|
2615
|
+
ok: deepCloneRecord(step?.ok ?? {}),
|
|
2616
|
+
fail: deepCloneRecord(step?.fail ?? {})
|
|
2617
|
+
})),
|
|
2618
|
+
pluginsData: (result.pluginsData ?? []).map((plugin) => new runtime_js_1.LoadStrikePluginData(plugin.pluginName, (plugin.tables ?? []).map((table) => new runtime_js_1.LoadStrikePluginDataTable(table.tableName, [...(table.headers ?? [])], (table.rows ?? []).map((row) => deepCloneRecord(row)))), [...(plugin.hints ?? [])])),
|
|
2619
|
+
disabledSinks: [...(result.disabledSinks ?? [])],
|
|
2620
|
+
sinkErrors: (result.sinkErrors ?? []).map((value) => ({ ...value })),
|
|
2621
|
+
reportFiles: [...(result.reportFiles ?? [])],
|
|
2622
|
+
logFiles: [...(result.logFiles ?? [])]
|
|
2623
|
+
};
|
|
2624
|
+
}
|
|
2625
|
+
function cloneRunResult(result) {
|
|
2626
|
+
return {
|
|
2627
|
+
...result,
|
|
2628
|
+
nodeInfo: cloneNodeInfo(result.nodeInfo),
|
|
2629
|
+
testInfo: cloneTestInfo(result.testInfo),
|
|
2630
|
+
thresholds: (result.thresholds ?? []).map((value) => ({ ...value })),
|
|
2631
|
+
thresholdResults: (result.thresholdResults ?? []).map((value) => ({ ...value })),
|
|
2632
|
+
metricStats: cloneMetricStats(result.metricStats),
|
|
2633
|
+
metrics: Array.isArray(result.metrics) ? result.metrics.map((value) => ({ ...value })) : [],
|
|
2634
|
+
scenarioStats: (result.scenarioStats ?? []).map((value) => cloneScenarioStats(value)),
|
|
2635
|
+
stepStats: (result.stepStats ?? []).map((step) => ({
|
|
2635
2636
|
...step,
|
|
2636
|
-
ok: deepCloneRecord(step
|
|
2637
|
-
fail: deepCloneRecord(step
|
|
2637
|
+
ok: deepCloneRecord(step?.ok ?? {}),
|
|
2638
|
+
fail: deepCloneRecord(step?.fail ?? {})
|
|
2638
2639
|
})),
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2640
|
+
scenarioDurationsMs: { ...(result.scenarioDurationsMs ?? {}) },
|
|
2641
|
+
pluginsData: (result.pluginsData ?? []).map((plugin) => new runtime_js_1.LoadStrikePluginData(plugin.pluginName, (plugin.tables ?? []).map((table) => new runtime_js_1.LoadStrikePluginDataTable(table.tableName, [...(table.headers ?? [])], (table.rows ?? []).map((row) => deepCloneRecord(row)))), [...(plugin.hints ?? [])])),
|
|
2642
|
+
disabledSinks: [...(result.disabledSinks ?? [])],
|
|
2643
|
+
sinkErrors: (result.sinkErrors ?? []).map((value) => ({ ...value })),
|
|
2644
|
+
reportFiles: [...(result.reportFiles ?? [])],
|
|
2645
|
+
logFiles: [...(result.logFiles ?? [])],
|
|
2646
|
+
correlationRows: (result.correlationRows ?? []).map((row) => deepCloneRecord(row)),
|
|
2647
|
+
failedCorrelationRows: (result.failedCorrelationRows ?? []).map((row) => deepCloneRecord(row))
|
|
2648
|
+
};
|
|
2649
|
+
}
|
|
2650
|
+
function runResultToNodeStats(result) {
|
|
2651
|
+
return {
|
|
2652
|
+
startedUtc: result.startedUtc,
|
|
2653
|
+
completedUtc: result.completedUtc,
|
|
2654
|
+
allBytes: result.allBytes ?? 0,
|
|
2655
|
+
allRequestCount: result.allRequestCount ?? 0,
|
|
2656
|
+
allOkCount: result.allOkCount ?? 0,
|
|
2657
|
+
allFailCount: result.allFailCount ?? 0,
|
|
2658
|
+
failedThresholds: result.failedThresholds ?? 0,
|
|
2659
|
+
durationMs: result.durationMs ?? 0,
|
|
2660
|
+
nodeInfo: cloneNodeInfo(result.nodeInfo),
|
|
2661
|
+
testInfo: cloneTestInfo(result.testInfo),
|
|
2662
|
+
thresholds: (result.thresholds ?? []).map((value) => ({ ...value })),
|
|
2663
|
+
thresholdResults: (result.thresholdResults ?? []).map((value) => ({ ...value })),
|
|
2664
|
+
metrics: cloneMetricStats(result.metricStats),
|
|
2665
|
+
metricValues: Array.isArray(result.metrics) ? result.metrics.map((value) => ({ ...value })) : [],
|
|
2666
|
+
scenarioStats: (result.scenarioStats ?? []).map((value) => cloneScenarioStats(value)),
|
|
2667
|
+
stepStats: (result.stepStats ?? []).map((step) => ({
|
|
2668
|
+
...step,
|
|
2669
|
+
ok: deepCloneRecord(step?.ok ?? {}),
|
|
2670
|
+
fail: deepCloneRecord(step?.fail ?? {})
|
|
2671
|
+
})),
|
|
2672
|
+
pluginsData: (result.pluginsData ?? []).map((plugin) => new runtime_js_1.LoadStrikePluginData(plugin.pluginName, (plugin.tables ?? []).map((table) => new runtime_js_1.LoadStrikePluginDataTable(table.tableName, [...(table.headers ?? [])], (table.rows ?? []).map((row) => deepCloneRecord(row)))), [...(plugin.hints ?? [])])),
|
|
2673
|
+
disabledSinks: [...(result.disabledSinks ?? [])],
|
|
2674
|
+
sinkErrors: (result.sinkErrors ?? []).map((value) => ({ ...value })),
|
|
2675
|
+
reportFiles: [...(result.reportFiles ?? [])],
|
|
2676
|
+
logFiles: [...(result.logFiles ?? [])],
|
|
2677
|
+
findScenarioStats: (scenarioName) => result.scenarioStats.find((value) => value.scenarioName === scenarioName),
|
|
2678
|
+
getScenarioStats: (scenarioName) => {
|
|
2679
|
+
const scenario = result.scenarioStats.find((value) => value.scenarioName === scenarioName);
|
|
2680
|
+
if (!scenario) {
|
|
2681
|
+
throw new Error(`Scenario stats not found: ${scenarioName}`);
|
|
2682
|
+
}
|
|
2683
|
+
return scenario;
|
|
2684
|
+
},
|
|
2685
|
+
FindScenarioStats: (scenarioName) => result.scenarioStats.find((value) => value.scenarioName === scenarioName),
|
|
2686
|
+
GetScenarioStats: (scenarioName) => {
|
|
2687
|
+
const scenario = result.scenarioStats.find((value) => value.scenarioName === scenarioName);
|
|
2688
|
+
if (!scenario) {
|
|
2689
|
+
throw new Error(`Scenario stats not found: ${scenarioName}`);
|
|
2690
|
+
}
|
|
2691
|
+
return scenario;
|
|
2692
|
+
}
|
|
2643
2693
|
};
|
|
2644
2694
|
}
|
|
2645
2695
|
function deepCloneRecord(value) {
|
|
@@ -2673,3 +2723,47 @@ async function postWithTimeout(fetchImpl, url, init, timeoutMs, sinkName) {
|
|
|
2673
2723
|
clearTimeout(timer);
|
|
2674
2724
|
}
|
|
2675
2725
|
}
|
|
2726
|
+
exports.__loadstrikeTestExports = {
|
|
2727
|
+
GrafanaLokiReportingSink,
|
|
2728
|
+
InfluxDbReportingSink,
|
|
2729
|
+
OtelCollectorReportingSink,
|
|
2730
|
+
SplunkReportingSink,
|
|
2731
|
+
TimescaleDbReportingSink,
|
|
2732
|
+
cleanNullableText,
|
|
2733
|
+
cloneBaseContext,
|
|
2734
|
+
cloneMetricStats,
|
|
2735
|
+
cloneNodeStats,
|
|
2736
|
+
cloneScenarioStats,
|
|
2737
|
+
cloneSessionStartInfo,
|
|
2738
|
+
createFinalStatsEvents,
|
|
2739
|
+
createRealtimeStatsEvents,
|
|
2740
|
+
createRunResultEvents,
|
|
2741
|
+
createReportingEvent,
|
|
2742
|
+
mergeDatadogOptions,
|
|
2743
|
+
mergeInfluxOptions,
|
|
2744
|
+
mergeGrafanaLokiOptions,
|
|
2745
|
+
mergeOtelCollectorOptions,
|
|
2746
|
+
mergeSplunkOptions,
|
|
2747
|
+
mergeTimescaleDbOptions,
|
|
2748
|
+
normalizeConfigKey,
|
|
2749
|
+
normalizePath,
|
|
2750
|
+
normalizePluginFieldName,
|
|
2751
|
+
normalizePluginFieldValue,
|
|
2752
|
+
normalizeStringMap,
|
|
2753
|
+
optionNumber,
|
|
2754
|
+
optionString,
|
|
2755
|
+
pickBooleanValue,
|
|
2756
|
+
pickRecordValue,
|
|
2757
|
+
postWithTimeout,
|
|
2758
|
+
quoteIdentifier,
|
|
2759
|
+
replaceLiteral,
|
|
2760
|
+
resolveConfigSection,
|
|
2761
|
+
resolveTimeoutMs,
|
|
2762
|
+
sanitizeGrafanaLabelKey,
|
|
2763
|
+
sanitizeGrafanaLabelValue,
|
|
2764
|
+
sinkSessionMetadataFromContext,
|
|
2765
|
+
toOtelAnyValue,
|
|
2766
|
+
trimTrailingSlashes,
|
|
2767
|
+
tryReadText,
|
|
2768
|
+
validateIdentifier
|
|
2769
|
+
};
|
package/dist/cjs/transports.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.EndpointAdapterFactory = exports.KafkaSaslOptions = exports.HttpAuthOptions = exports.HttpOAuth2ClientCredentialsOptions = exports.PushDiffusionEndpointDefinition = exports.DelegateStreamEndpointDefinition = exports.AzureEventHubsEndpointDefinition = exports.RedisStreamsEndpointDefinition = exports.NatsEndpointDefinition = exports.RabbitMqEndpointDefinition = exports.KafkaEndpointDefinition = exports.HttpEndpointDefinition = exports.TrafficEndpointDefinition = void 0;
|
|
36
|
+
exports.__loadstrikeTestExports = exports.EndpointAdapterFactory = exports.KafkaSaslOptions = exports.HttpAuthOptions = exports.HttpOAuth2ClientCredentialsOptions = exports.PushDiffusionEndpointDefinition = exports.DelegateStreamEndpointDefinition = exports.AzureEventHubsEndpointDefinition = exports.RedisStreamsEndpointDefinition = exports.NatsEndpointDefinition = exports.RabbitMqEndpointDefinition = exports.KafkaEndpointDefinition = exports.HttpEndpointDefinition = exports.TrafficEndpointDefinition = void 0;
|
|
37
37
|
const node_crypto_1 = require("node:crypto");
|
|
38
38
|
const correlation_js_1 = require("./correlation.js");
|
|
39
39
|
class TrafficEndpointDefinitionModel {
|
|
@@ -247,6 +247,9 @@ class AzureEventHubsEndpointDefinitionModel extends TrafficEndpointDefinitionMod
|
|
|
247
247
|
super.Validate();
|
|
248
248
|
requireNonEmptyString(this.ConnectionString, "ConnectionString must be provided for Azure Event Hubs endpoint.");
|
|
249
249
|
requireNonEmptyString(this.EventHubName, "EventHubName must be provided for Azure Event Hubs endpoint.");
|
|
250
|
+
if (this.PartitionCount != null && this.PartitionCount < 0) {
|
|
251
|
+
throw new RangeError("PartitionCount must be zero or greater when configured.");
|
|
252
|
+
}
|
|
250
253
|
}
|
|
251
254
|
}
|
|
252
255
|
class DelegateStreamEndpointDefinitionModel extends TrafficEndpointDefinitionModel {
|
|
@@ -650,6 +653,12 @@ function initializeAzureEventHubsEndpointDefinitionModel(target, initial) {
|
|
|
650
653
|
if (hasAnyEndpointField(raw, ["PartitionId", "partitionId"])) {
|
|
651
654
|
target.PartitionId = pickOptionalEndpointString(raw, "PartitionId", "partitionId");
|
|
652
655
|
}
|
|
656
|
+
if (hasAnyEndpointField(raw, ["PartitionKey", "partitionKey"])) {
|
|
657
|
+
target.PartitionKey = pickOptionalEndpointString(raw, "PartitionKey", "partitionKey");
|
|
658
|
+
}
|
|
659
|
+
if (hasAnyEndpointField(raw, ["PartitionCount", "partitionCount"])) {
|
|
660
|
+
target.PartitionCount = pickOptionalEndpointNumber(raw, "PartitionCount", "partitionCount");
|
|
661
|
+
}
|
|
653
662
|
}
|
|
654
663
|
function initializeDelegateStreamEndpointDefinitionModel(target, initial) {
|
|
655
664
|
const raw = asRecordOrEmpty(initial);
|
|
@@ -740,10 +749,9 @@ function validateHttpAuthOptionsModel(target) {
|
|
|
740
749
|
}
|
|
741
750
|
return;
|
|
742
751
|
case "oauth2clientcredentials":
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
toHttpOAuth2ClientCredentialsOptionsModel(target.OAuth2ClientCredentials).Validate();
|
|
752
|
+
requireNonEmptyString(target.TokenUrl ?? target.OAuth2ClientCredentials?.TokenEndpoint, "TokenEndpoint must be provided for OAuth2 client credentials flow.");
|
|
753
|
+
requireNonEmptyString(target.ClientId ?? target.OAuth2ClientCredentials?.ClientId, "ClientId must be provided for OAuth2 client credentials flow.");
|
|
754
|
+
requireNonEmptyString(target.ClientSecret ?? target.OAuth2ClientCredentials?.ClientSecret, "ClientSecret must be provided for OAuth2 client credentials flow.");
|
|
747
755
|
return;
|
|
748
756
|
default:
|
|
749
757
|
throw new RangeError("Unsupported HTTP auth type.");
|
|
@@ -933,8 +941,7 @@ const protocolBus = new class InMemoryProtocolBus {
|
|
|
933
941
|
produceEventHub(endpoint, payload) {
|
|
934
942
|
const options = endpoint.azureEventHubs ?? {};
|
|
935
943
|
const hubName = optionString(options, "EventHubName", "eventHubName") || endpoint.name;
|
|
936
|
-
const partitionId =
|
|
937
|
-
|| partitionFromKey(optionString(options, "PartitionKey", "partitionKey"), optionNumber(options, "PartitionCount", "partitionCount") || 4);
|
|
944
|
+
const partitionId = resolveEventHubProducePartitionId(options) || "";
|
|
938
945
|
const rows = this.eventHubs.get(hubName) ?? [];
|
|
939
946
|
rows.push({
|
|
940
947
|
partitionId,
|
|
@@ -1160,10 +1167,10 @@ class HttpEndpointAdapter extends CallbackAdapter {
|
|
|
1160
1167
|
body.set("grant_type", "client_credentials");
|
|
1161
1168
|
body.set("client_id", clientId);
|
|
1162
1169
|
body.set("client_secret", clientSecret);
|
|
1163
|
-
const scopes = Array.isArray(
|
|
1164
|
-
?
|
|
1165
|
-
: Array.isArray(
|
|
1166
|
-
?
|
|
1170
|
+
const scopes = Array.isArray(auth?.scopes)
|
|
1171
|
+
? auth.scopes.map((x) => String(x).trim()).filter((x) => x.length > 0)
|
|
1172
|
+
: Array.isArray(oauthOptions?.scopes)
|
|
1173
|
+
? oauthOptions.scopes.map((x) => String(x).trim()).filter((x) => x.length > 0)
|
|
1167
1174
|
: [];
|
|
1168
1175
|
const scopeText = typeof auth?.scope === "string" && auth.scope.trim()
|
|
1169
1176
|
? auth.scope.trim()
|
|
@@ -1175,8 +1182,8 @@ class HttpEndpointAdapter extends CallbackAdapter {
|
|
|
1175
1182
|
body.set("audience", auth.audience.trim());
|
|
1176
1183
|
}
|
|
1177
1184
|
for (const [key, value] of Object.entries({
|
|
1178
|
-
...(
|
|
1179
|
-
...(
|
|
1185
|
+
...(oauthOptions?.additionalFormFields ?? {}),
|
|
1186
|
+
...(auth?.additionalFormFields ?? {})
|
|
1180
1187
|
})) {
|
|
1181
1188
|
if (key.trim() && typeof value === "string") {
|
|
1182
1189
|
body.set(key.trim(), value);
|
|
@@ -1602,13 +1609,15 @@ class AzureEventHubsEndpointAdapter extends CallbackAdapter {
|
|
|
1602
1609
|
const options = this.endpoint.azureEventHubs ?? {};
|
|
1603
1610
|
const resolved = prepareProducedPayload(this.endpoint, payload);
|
|
1604
1611
|
const wire = toWirePayload(resolved, this.endpoint);
|
|
1605
|
-
const
|
|
1612
|
+
const partitionId = resolveEventHubProducePartitionId(options);
|
|
1613
|
+
const batch = partitionId
|
|
1614
|
+
? await producer.createBatch({ partitionId })
|
|
1615
|
+
: await producer.createBatch();
|
|
1606
1616
|
const eventData = {
|
|
1607
1617
|
body: Buffer.from(wire.body),
|
|
1608
1618
|
contentType: wire.contentType,
|
|
1609
1619
|
properties: { ...wire.headers }
|
|
1610
1620
|
};
|
|
1611
|
-
const partitionId = optionString(options, "PartitionId", "partitionId");
|
|
1612
1621
|
if (partitionId) {
|
|
1613
1622
|
eventData.partitionId = partitionId;
|
|
1614
1623
|
}
|
|
@@ -1835,6 +1844,10 @@ const AZURE_EVENT_HUBS_ENDPOINT_FLAT_KEYS = [
|
|
|
1835
1844
|
"consumerGroup",
|
|
1836
1845
|
"PartitionId",
|
|
1837
1846
|
"partitionId",
|
|
1847
|
+
"PartitionKey",
|
|
1848
|
+
"partitionKey",
|
|
1849
|
+
"PartitionCount",
|
|
1850
|
+
"partitionCount",
|
|
1838
1851
|
"StartFromEarliest",
|
|
1839
1852
|
"startFromEarliest"
|
|
1840
1853
|
];
|
|
@@ -1947,7 +1960,11 @@ function resolveEndpointKind(raw) {
|
|
|
1947
1960
|
"EventHubName",
|
|
1948
1961
|
"eventHubName",
|
|
1949
1962
|
"PartitionId",
|
|
1950
|
-
"partitionId"
|
|
1963
|
+
"partitionId",
|
|
1964
|
+
"PartitionKey",
|
|
1965
|
+
"partitionKey",
|
|
1966
|
+
"PartitionCount",
|
|
1967
|
+
"partitionCount"
|
|
1951
1968
|
])) {
|
|
1952
1969
|
return "AzureEventHubs";
|
|
1953
1970
|
}
|
|
@@ -2448,6 +2465,10 @@ function validateAzureEventHubsEndpoint(endpoint, mode, hasModeDelegate) {
|
|
|
2448
2465
|
}
|
|
2449
2466
|
requireNonEmptyString(optionString(options, "ConnectionString", "connectionString"), "ConnectionString must be provided for Azure Event Hubs endpoint.");
|
|
2450
2467
|
requireNonEmptyString(optionString(options, "EventHubName", "eventHubName"), "EventHubName must be provided for Azure Event Hubs endpoint.");
|
|
2468
|
+
const partitionCount = optionNumber(options, "PartitionCount", "partitionCount");
|
|
2469
|
+
if (partitionCount < 0) {
|
|
2470
|
+
throw new RangeError("PartitionCount must be zero or greater when configured.");
|
|
2471
|
+
}
|
|
2451
2472
|
}
|
|
2452
2473
|
function validatePushDiffusionEndpoint(endpoint, mode) {
|
|
2453
2474
|
const options = endpoint.pushDiffusion;
|
|
@@ -2847,6 +2868,17 @@ function partitionFromKey(value, partitionCount) {
|
|
|
2847
2868
|
const normalized = Math.abs(hash) % count;
|
|
2848
2869
|
return String(normalized);
|
|
2849
2870
|
}
|
|
2871
|
+
function resolveEventHubProducePartitionId(options) {
|
|
2872
|
+
const explicitPartitionId = optionString(options, "PartitionId", "partitionId");
|
|
2873
|
+
if (explicitPartitionId) {
|
|
2874
|
+
return explicitPartitionId;
|
|
2875
|
+
}
|
|
2876
|
+
const partitionKey = optionString(options, "PartitionKey", "partitionKey");
|
|
2877
|
+
if (!partitionKey) {
|
|
2878
|
+
return undefined;
|
|
2879
|
+
}
|
|
2880
|
+
return partitionFromKey(partitionKey, optionNumber(options, "PartitionCount", "partitionCount") || 4);
|
|
2881
|
+
}
|
|
2850
2882
|
function attachPayloadHelpers(payload) {
|
|
2851
2883
|
const target = {
|
|
2852
2884
|
...payload,
|
|
@@ -3029,10 +3061,10 @@ function deserializeBrokerPayloadBody(body, contentType, messagePayloadType) {
|
|
|
3029
3061
|
function extractTrackingValue(payload, selector) {
|
|
3030
3062
|
const normalized = selector.trim().toLowerCase();
|
|
3031
3063
|
if (normalized.startsWith("header:")) {
|
|
3032
|
-
const headerName = selector.slice("header:".length).trim()
|
|
3064
|
+
const headerName = selector.slice("header:".length).trim();
|
|
3033
3065
|
for (const [key, value] of Object.entries(payload.headers ?? {})) {
|
|
3034
3066
|
const resolved = String(value ?? "").trim();
|
|
3035
|
-
if (key
|
|
3067
|
+
if (key === headerName && resolved) {
|
|
3036
3068
|
return resolved;
|
|
3037
3069
|
}
|
|
3038
3070
|
}
|
|
@@ -3693,3 +3725,57 @@ function payloadBodyAsUtf8(body) {
|
|
|
3693
3725
|
return String(body);
|
|
3694
3726
|
}
|
|
3695
3727
|
}
|
|
3728
|
+
exports.__loadstrikeTestExports = {
|
|
3729
|
+
AzureEventHubsEndpointAdapter,
|
|
3730
|
+
AzureEventHubsEndpointDefinition: exports.AzureEventHubsEndpointDefinition,
|
|
3731
|
+
AzureEventHubsEndpointDefinitionModel,
|
|
3732
|
+
CallbackAdapter,
|
|
3733
|
+
DelegateStreamEndpointDefinition: exports.DelegateStreamEndpointDefinition,
|
|
3734
|
+
DelegateStreamEndpointDefinitionModel,
|
|
3735
|
+
HttpEndpointAdapter,
|
|
3736
|
+
NatsEndpointDefinition: exports.NatsEndpointDefinition,
|
|
3737
|
+
NatsEndpointDefinitionModel,
|
|
3738
|
+
PushDiffusionEndpointDefinition: exports.PushDiffusionEndpointDefinition,
|
|
3739
|
+
PushDiffusionEndpointDefinitionModel,
|
|
3740
|
+
RabbitMqEndpointDefinition: exports.RabbitMqEndpointDefinition,
|
|
3741
|
+
RabbitMqEndpointDefinitionModel,
|
|
3742
|
+
RedisStreamsEndpointAdapter,
|
|
3743
|
+
RedisStreamsEndpointDefinition: exports.RedisStreamsEndpointDefinition,
|
|
3744
|
+
RedisStreamsEndpointDefinitionModel,
|
|
3745
|
+
bufferToUint8Array,
|
|
3746
|
+
applyHttpAuthHeaders,
|
|
3747
|
+
buildHttpRequestBody,
|
|
3748
|
+
buildConfluentKafkaClientOptions,
|
|
3749
|
+
buildKafkaClientOptions,
|
|
3750
|
+
canonicalizeHttpResponseSource,
|
|
3751
|
+
createDelegateRequestEndpointView,
|
|
3752
|
+
createNatsHeaders,
|
|
3753
|
+
createRedisStreamPayload,
|
|
3754
|
+
deserializeBrokerPayloadBody,
|
|
3755
|
+
extractTrackingValue,
|
|
3756
|
+
fromKafkaHeaders,
|
|
3757
|
+
headerValue,
|
|
3758
|
+
attachDotNetTrackingPayloadAliases,
|
|
3759
|
+
attachPayloadHelpers,
|
|
3760
|
+
attachStructuredProducedMessageRequestAliases,
|
|
3761
|
+
inferLegacyHttpResponseSource,
|
|
3762
|
+
injectTrackingValue,
|
|
3763
|
+
mapConfluentKafkaSaslMechanism,
|
|
3764
|
+
mapConfluentKafkaSecurityProtocol,
|
|
3765
|
+
mapKafkaSaslMechanism,
|
|
3766
|
+
parseBodyObject,
|
|
3767
|
+
partitionFromKey,
|
|
3768
|
+
payloadBodyAsUtf8,
|
|
3769
|
+
prepareProducedPayload,
|
|
3770
|
+
protocolBus: protocolBus,
|
|
3771
|
+
readFirstRedisStreamEntry,
|
|
3772
|
+
resolveConnectionMetadata,
|
|
3773
|
+
resolveKafkaOAuthBearerToken,
|
|
3774
|
+
serializePayloadBody,
|
|
3775
|
+
setJsonBodyValue,
|
|
3776
|
+
shouldUseConfluentKafkaClient,
|
|
3777
|
+
toHeaderRecord,
|
|
3778
|
+
toKafkaHeadersWithContentType,
|
|
3779
|
+
validateHttpEndpoint,
|
|
3780
|
+
validateTrackingSelectorPath
|
|
3781
|
+
};
|
package/dist/esm/cluster.js
CHANGED
|
@@ -401,3 +401,20 @@ function booleanOrDefault(value, fallback) {
|
|
|
401
401
|
async function sleep(ms) {
|
|
402
402
|
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
403
403
|
}
|
|
404
|
+
export const __loadstrikeTestExports = {
|
|
405
|
+
DistributedClusterAgent,
|
|
406
|
+
DistributedClusterCoordinator,
|
|
407
|
+
LocalClusterCoordinator,
|
|
408
|
+
arrayOrUndefined,
|
|
409
|
+
booleanOrDefault,
|
|
410
|
+
buildWeightedCycle,
|
|
411
|
+
convertRunResult,
|
|
412
|
+
numberOrDefault,
|
|
413
|
+
parseRunCommand,
|
|
414
|
+
parseRunResult,
|
|
415
|
+
planAgentScenarioAssignments,
|
|
416
|
+
recordOrUndefined,
|
|
417
|
+
sanitizeToken,
|
|
418
|
+
sleep,
|
|
419
|
+
stringOrDefault
|
|
420
|
+
};
|