@loadstrike/loadstrike-sdk 1.0.10101 → 1.0.15201
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 +107 -22
- 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 +105 -20
- 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 +9 -20
package/dist/esm/correlation.js
CHANGED
|
@@ -551,11 +551,10 @@ export class TrackingFieldSelector {
|
|
|
551
551
|
}
|
|
552
552
|
extract(payload) {
|
|
553
553
|
if (this.kind === "header") {
|
|
554
|
-
const headerName = this.path.toLowerCase();
|
|
555
554
|
const headers = payload.headers ?? {};
|
|
556
555
|
for (const [key, value] of Object.entries(headers)) {
|
|
557
556
|
const parsed = String(value ?? "").trim();
|
|
558
|
-
if (key
|
|
557
|
+
if (key === this.path && parsed) {
|
|
559
558
|
return parsed;
|
|
560
559
|
}
|
|
561
560
|
}
|
|
@@ -595,6 +594,8 @@ function normalizeTrackingFieldLocation(location) {
|
|
|
595
594
|
}
|
|
596
595
|
export class CrossPlatformTrackingRuntime {
|
|
597
596
|
constructor(options) {
|
|
597
|
+
this.trackingIdDisplayByEventId = new Map();
|
|
598
|
+
this.gatherByDisplayByComparisonKey = new Map();
|
|
598
599
|
this.producedCount = 0;
|
|
599
600
|
this.consumedCount = 0;
|
|
600
601
|
this.matchedCount = 0;
|
|
@@ -608,6 +609,8 @@ export class CrossPlatformTrackingRuntime {
|
|
|
608
609
|
this.gatherSelector = options.destinationGatherByField
|
|
609
610
|
? TrackingFieldSelector.parse(options.destinationGatherByField)
|
|
610
611
|
: null;
|
|
612
|
+
this.trackingFieldValueCaseSensitive = options.trackingFieldValueCaseSensitive ?? true;
|
|
613
|
+
this.gatherByFieldValueCaseSensitive = options.gatherByFieldValueCaseSensitive ?? true;
|
|
611
614
|
this.timeoutMs = Math.max(options.correlationTimeoutMs ?? 30000, 1);
|
|
612
615
|
this.timeoutCountsAsFailure = options.timeoutCountsAsFailure ?? true;
|
|
613
616
|
this.store = options.store ?? new InMemoryCorrelationStore();
|
|
@@ -630,13 +633,17 @@ export class CrossPlatformTrackingRuntime {
|
|
|
630
633
|
return result;
|
|
631
634
|
}
|
|
632
635
|
result.trackingId = trackingId;
|
|
633
|
-
const
|
|
636
|
+
const comparisonTrackingId = normalizeComparisonValue(trackingId, this.trackingFieldValueCaseSensitive);
|
|
637
|
+
const sourceOccurrences = await this.store.incrementSourceOccurrences(comparisonTrackingId);
|
|
634
638
|
if (sourceOccurrences > 1) {
|
|
635
639
|
this.duplicateSourceCount += 1;
|
|
636
640
|
result.duplicateSource = true;
|
|
637
641
|
}
|
|
638
|
-
const registration = await this.store.registerSource(
|
|
642
|
+
const registration = await this.store.registerSource(comparisonTrackingId, nowMs);
|
|
639
643
|
result.eventId = registration.eventId ?? "";
|
|
644
|
+
if (registration.eventId) {
|
|
645
|
+
this.trackingIdDisplayByEventId.set(registration.eventId, trackingId);
|
|
646
|
+
}
|
|
640
647
|
if (registration.eventId) {
|
|
641
648
|
await this.store.tryExpire(registration.eventId);
|
|
642
649
|
}
|
|
@@ -677,12 +684,13 @@ export class CrossPlatformTrackingRuntime {
|
|
|
677
684
|
return result;
|
|
678
685
|
}
|
|
679
686
|
result.trackingId = trackingId;
|
|
680
|
-
const
|
|
687
|
+
const comparisonTrackingId = normalizeComparisonValue(trackingId, this.trackingFieldValueCaseSensitive);
|
|
688
|
+
const destinationOccurrences = await this.store.incrementDestinationOccurrences(comparisonTrackingId);
|
|
681
689
|
if (destinationOccurrences > 1) {
|
|
682
690
|
this.duplicateDestinationCount += 1;
|
|
683
691
|
result.duplicateDestination = true;
|
|
684
692
|
}
|
|
685
|
-
const source = await this.store.tryMatchDestination(
|
|
693
|
+
const source = await this.store.tryMatchDestination(comparisonTrackingId, nowMs);
|
|
686
694
|
if (!source) {
|
|
687
695
|
result.message = "Destination tracking id had no source match.";
|
|
688
696
|
return result;
|
|
@@ -690,10 +698,12 @@ export class CrossPlatformTrackingRuntime {
|
|
|
690
698
|
this.matchedCount += 1;
|
|
691
699
|
const latencyMs = Math.max(nowMs - (source.producedUtc ?? source.sourceTimestampUtc ?? nowMs), 0);
|
|
692
700
|
this.totalLatencyMs += latencyMs;
|
|
701
|
+
const displayTrackingId = this.resolveTrackingIdDisplay(source.eventId, source.trackingId, true);
|
|
693
702
|
const gatherKey = this.resolveGatherKey(payload);
|
|
694
703
|
result.eventId = source.eventId ?? "";
|
|
695
704
|
result.sourceTimestampUtc = source.sourceTimestampUtc ?? source.producedUtc ?? 0;
|
|
696
705
|
result.destinationTimestampUtc = nowMs;
|
|
706
|
+
result.trackingId = displayTrackingId;
|
|
697
707
|
result.gatherKey = gatherKey;
|
|
698
708
|
result.matched = true;
|
|
699
709
|
result.latencyMs = latencyMs;
|
|
@@ -703,7 +713,7 @@ export class CrossPlatformTrackingRuntime {
|
|
|
703
713
|
this.gathered.set(gatherKey, row);
|
|
704
714
|
for (const plugin of this.plugins) {
|
|
705
715
|
if (plugin.onMatched) {
|
|
706
|
-
await plugin.onMatched(
|
|
716
|
+
await plugin.onMatched(displayTrackingId, source.payload, payload, latencyMs, gatherKey);
|
|
707
717
|
}
|
|
708
718
|
}
|
|
709
719
|
return result;
|
|
@@ -751,7 +761,9 @@ export class CrossPlatformTrackingRuntime {
|
|
|
751
761
|
expiredEntries.push(entry);
|
|
752
762
|
}
|
|
753
763
|
for (const entry of expiredEntries) {
|
|
764
|
+
const displayTrackingId = this.resolveTrackingIdDisplay(entry.eventId, entry.trackingId, true);
|
|
754
765
|
this.timeoutCount += 1;
|
|
766
|
+
entry.trackingId = displayTrackingId;
|
|
755
767
|
const gatherKey = this.resolveGatherKey(entry.payload);
|
|
756
768
|
const row = this.gathered.get(gatherKey) ?? { total: 0, matched: 0, timedOut: 0 };
|
|
757
769
|
row.total += 1;
|
|
@@ -759,7 +771,7 @@ export class CrossPlatformTrackingRuntime {
|
|
|
759
771
|
this.gathered.set(gatherKey, row);
|
|
760
772
|
for (const plugin of this.plugins) {
|
|
761
773
|
if (plugin.onTimeout) {
|
|
762
|
-
await plugin.onTimeout(
|
|
774
|
+
await plugin.onTimeout(displayTrackingId, entry.payload);
|
|
763
775
|
}
|
|
764
776
|
}
|
|
765
777
|
}
|
|
@@ -783,11 +795,40 @@ export class CrossPlatformTrackingRuntime {
|
|
|
783
795
|
if (!this.gatherSelector) {
|
|
784
796
|
return "__ungrouped__";
|
|
785
797
|
}
|
|
786
|
-
|
|
798
|
+
const gatherKey = this.gatherSelector.extract(payload);
|
|
799
|
+
if (!gatherKey) {
|
|
800
|
+
return "__unknown__";
|
|
801
|
+
}
|
|
802
|
+
if (this.gatherByFieldValueCaseSensitive) {
|
|
803
|
+
return gatherKey;
|
|
804
|
+
}
|
|
805
|
+
const comparisonKey = normalizeComparisonValue(gatherKey, false);
|
|
806
|
+
const existing = this.gatherByDisplayByComparisonKey.get(comparisonKey);
|
|
807
|
+
if (existing) {
|
|
808
|
+
return existing;
|
|
809
|
+
}
|
|
810
|
+
this.gatherByDisplayByComparisonKey.set(comparisonKey, gatherKey);
|
|
811
|
+
return gatherKey;
|
|
787
812
|
}
|
|
788
813
|
isTimeoutCountedAsFailure() {
|
|
789
814
|
return this.timeoutCountsAsFailure;
|
|
790
815
|
}
|
|
816
|
+
resolveTrackingIdDisplay(eventId, fallbackTrackingId, remove) {
|
|
817
|
+
if (!eventId?.trim()) {
|
|
818
|
+
return fallbackTrackingId;
|
|
819
|
+
}
|
|
820
|
+
if (remove) {
|
|
821
|
+
const displayTrackingId = this.trackingIdDisplayByEventId.get(eventId);
|
|
822
|
+
this.trackingIdDisplayByEventId.delete(eventId);
|
|
823
|
+
return displayTrackingId ?? fallbackTrackingId;
|
|
824
|
+
}
|
|
825
|
+
return this.trackingIdDisplayByEventId.get(eventId) ?? fallbackTrackingId;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
function normalizeComparisonValue(value, caseSensitive) {
|
|
829
|
+
return caseSensitive
|
|
830
|
+
? value
|
|
831
|
+
: value.toUpperCase();
|
|
791
832
|
}
|
|
792
833
|
function normalizeJsonBody(body) {
|
|
793
834
|
if (body instanceof Uint8Array) {
|
|
@@ -907,7 +948,9 @@ function uniqueStringList(values) {
|
|
|
907
948
|
return [...new Set(values.filter((value) => value.trim().length > 0))];
|
|
908
949
|
}
|
|
909
950
|
function createRedisStoreClient(connectionString, database) {
|
|
910
|
-
const
|
|
951
|
+
const createClientOverride = globalThis
|
|
952
|
+
.__wave15CreateRedisClient;
|
|
953
|
+
const client = (typeof createClientOverride === "function" ? createClientOverride : createClient)({
|
|
911
954
|
url: connectionString,
|
|
912
955
|
database: database >= 0 ? database : undefined
|
|
913
956
|
});
|
|
@@ -997,3 +1040,18 @@ function readJsonPathSegment(current, segment) {
|
|
|
997
1040
|
}
|
|
998
1041
|
return undefined;
|
|
999
1042
|
}
|
|
1043
|
+
export const __loadstrikeTestExports = {
|
|
1044
|
+
CorrelationStoreConfiguration,
|
|
1045
|
+
InMemoryCorrelationStore,
|
|
1046
|
+
RedisCorrelationStore,
|
|
1047
|
+
RedisCorrelationStoreOptions,
|
|
1048
|
+
TrackingFieldSelector,
|
|
1049
|
+
createRedisStoreClient,
|
|
1050
|
+
hydrateCorrelationEntry,
|
|
1051
|
+
normalizeCorrelationEntry,
|
|
1052
|
+
parseStringList,
|
|
1053
|
+
readJsonPathSegment,
|
|
1054
|
+
sanitizeLooseJson,
|
|
1055
|
+
tryParseObject,
|
|
1056
|
+
uniqueStringList
|
|
1057
|
+
};
|
package/dist/esm/index.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { CrossPlatformScenarioConfigurator, ScenarioTrackingExtensions, LoadStrikeContext, LoadStrikePluginData, LoadStrikePluginDataTable, LoadStrikeReportData, LoadStrikeNodeType, LoadStrikeReportFormat, LoadStrikeResponse, LoadStrikeLogLevel, LoadStrikeScenarioOperation, LoadStrikeOperationType, LoadStrikeRunner, LoadStrikeScenario, LoadStrikeSimulation, LoadStrikeMetric, LoadStrikeCounter, LoadStrikeGauge, LoadStrikeStep, LoadStrikeThreshold } from "./runtime.js";
|
|
1
|
+
export { CrossPlatformScenarioConfigurator, ScenarioTrackingExtensions, LoadStrikeContext, LoadStrikePluginData, LoadStrikePluginDataTable, LoadStrikeNodeType, LoadStrikeReportFormat, LoadStrikeResponse, LoadStrikeLogLevel, LoadStrikeScenarioOperation, LoadStrikeOperationType, LoadStrikeRunner, LoadStrikeScenario, LoadStrikeSimulation, LoadStrikeMetric, LoadStrikeCounter, LoadStrikeGauge, LoadStrikeStep, LoadStrikeThreshold } from "./runtime.js";
|
|
3
2
|
export { CorrelationStoreConfiguration, CrossPlatformTrackingRuntime, InMemoryCorrelationStore, RedisCorrelationStoreOptions, RedisCorrelationStore, TrackingPayloadBuilder, TrackingFieldSelector } from "./correlation.js";
|
|
4
3
|
export { EndpointAdapterFactory, TrafficEndpointDefinition, HttpEndpointDefinition, KafkaEndpointDefinition, KafkaSaslOptions, RabbitMqEndpointDefinition, NatsEndpointDefinition, RedisStreamsEndpointDefinition, AzureEventHubsEndpointDefinition, DelegateStreamEndpointDefinition, PushDiffusionEndpointDefinition, HttpOAuth2ClientCredentialsOptions, HttpAuthOptions } from "./transports.js";
|
|
5
|
-
export {
|
|
6
|
-
export { CompositeReportingSink, ConsoleReportingSink, DatadogReportingSink, DatadogReportingSinkOptions, GrafanaLokiReportingSink, GrafanaLokiReportingSinkOptions, InfluxDbReportingSink, InfluxDbReportingSinkOptions, MemoryReportingSink, OtelCollectorReportingSink, OtelCollectorReportingSinkOptions, SplunkReportingSink, SplunkReportingSinkOptions, TimescaleDbReportingSink, TimescaleDbReportingSinkOptions } from "./sinks.js";
|
|
4
|
+
export { DatadogReportingSink, DatadogReportingSinkOptions, GrafanaLokiReportingSink, GrafanaLokiReportingSinkOptions, InfluxDbReportingSink, InfluxDbReportingSinkOptions, OtelCollectorReportingSink, OtelCollectorReportingSinkOptions, SplunkReportingSink, SplunkReportingSinkOptions, TimescaleDbReportingSink, TimescaleDbReportingSinkOptions } from "./sinks.js";
|
package/dist/esm/local.js
CHANGED
|
@@ -4,7 +4,8 @@ import * as childProcess from "node:child_process";
|
|
|
4
4
|
import { createHash, createVerify, randomUUID } from "node:crypto";
|
|
5
5
|
import { CorrelationStoreConfiguration, CrossPlatformTrackingRuntime, RedisCorrelationStoreOptions, RedisCorrelationStore, TrackingFieldSelector } from "./correlation.js";
|
|
6
6
|
import { EndpointAdapterFactory } from "./transports.js";
|
|
7
|
-
|
|
7
|
+
const DEFAULT_LICENSING_API_BASE_URL = "https://licensing.loadstrike.com";
|
|
8
|
+
let developmentLicensingApiBaseUrlOverride;
|
|
8
9
|
const BUILT_IN_WORKER_PLUGIN_NAMES = new Set([
|
|
9
10
|
"loadstrike failed responses",
|
|
10
11
|
"loadstrike correlation"
|
|
@@ -48,7 +49,7 @@ export class LoadStrikeLocalClient {
|
|
|
48
49
|
constructor(options = {}) {
|
|
49
50
|
this.signingKeyCache = new Map();
|
|
50
51
|
assertNoDisableLicenseEnforcementOption(options, "LoadStrikeLocalClient");
|
|
51
|
-
this.licensingApiBaseUrl =
|
|
52
|
+
this.licensingApiBaseUrl = resolveLicensingApiBaseUrl();
|
|
52
53
|
this.licenseValidationTimeoutMs = normalizeTimeoutMs(options.licenseValidationTimeoutMs);
|
|
53
54
|
}
|
|
54
55
|
async run(request) {
|
|
@@ -138,9 +139,10 @@ export class LoadStrikeLocalClient {
|
|
|
138
139
|
const timer = setTimeout(() => controller.abort(), this.licenseValidationTimeoutMs);
|
|
139
140
|
try {
|
|
140
141
|
const { response, json } = await this.postLicensingRequest("/api/v1/licenses/validate", payload, controller.signal);
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const
|
|
142
|
+
const isValid = pickValue(json, "IsValid", "isValid");
|
|
143
|
+
if (!response.ok || isValid !== true) {
|
|
144
|
+
const denialCode = stringOrDefault(pickValue(json, "DenialCode", "denialCode"), "unknown_denial");
|
|
145
|
+
const details = stringOrDefault(pickValue(json, "Message", "message"), "No additional details provided.");
|
|
144
146
|
throw new Error(`Runner key validation denied for '${runnerKey}'. Reason: ${denialCode}. ${details}`);
|
|
145
147
|
}
|
|
146
148
|
const runToken = stringOrDefault(pickValue(json, "RunToken", "SignedRunToken", "Token", "runToken"), "").trim();
|
|
@@ -218,7 +220,9 @@ export class LoadStrikeLocalClient {
|
|
|
218
220
|
}
|
|
219
221
|
async getSigningKey(keyId, algorithm) {
|
|
220
222
|
const nowMs = Date.now();
|
|
221
|
-
const
|
|
223
|
+
const normalizedKeyId = stringOrDefault(keyId, "default").trim() || "default";
|
|
224
|
+
const normalizedAlgorithm = stringOrDefault(algorithm, "RS256").toUpperCase();
|
|
225
|
+
const cacheKey = `${this.licensingApiBaseUrl.toLowerCase()}|${normalizedAlgorithm}:${normalizedKeyId}`;
|
|
222
226
|
const cached = this.signingKeyCache.get(cacheKey);
|
|
223
227
|
if (cached && cached.expiresAtUtc > nowMs) {
|
|
224
228
|
return cached;
|
|
@@ -226,17 +230,21 @@ export class LoadStrikeLocalClient {
|
|
|
226
230
|
const controller = new AbortController();
|
|
227
231
|
const timer = setTimeout(() => controller.abort(), this.licenseValidationTimeoutMs);
|
|
228
232
|
try {
|
|
229
|
-
const { response, json } = await this.getLicensingRequest(
|
|
233
|
+
const { response, json } = await this.getLicensingRequest(`/api/v1/licenses/signing-public-key?kid=${encodeURIComponent(normalizedKeyId)}`, controller.signal);
|
|
230
234
|
if (!response.ok) {
|
|
231
235
|
throw new Error(`Failed to resolve licensing signing key. status=${response.status}`);
|
|
232
236
|
}
|
|
233
|
-
const resolvedAlgorithm = stringOrDefault(pickValue(json, "Algorithm", "alg"),
|
|
234
|
-
const publicKeyPem =
|
|
237
|
+
const resolvedAlgorithm = stringOrDefault(pickValue(json, "Algorithm", "algorithm", "alg"), normalizedAlgorithm).toUpperCase();
|
|
238
|
+
const publicKeyPem = normalizePemText(pickValue(json, "PublicKeyPem", "publicKeyPem", "PublicKey", "publicKey", "Pem", "pem"));
|
|
235
239
|
if (!publicKeyPem.trim()) {
|
|
236
240
|
throw new Error("Runner key validation failed: signing key response is empty.");
|
|
237
241
|
}
|
|
242
|
+
const resolvedKeyId = stringOrDefault(pickValue(json, "KeyId", "keyId", "Kid", "kid"), normalizedKeyId).trim() || normalizedKeyId;
|
|
243
|
+
if (resolvedKeyId !== normalizedKeyId) {
|
|
244
|
+
throw new Error("Runner key validation failed: signing key response key id does not match requested key id.");
|
|
245
|
+
}
|
|
238
246
|
const keyRecord = {
|
|
239
|
-
keyId:
|
|
247
|
+
keyId: resolvedKeyId,
|
|
240
248
|
algorithm: resolvedAlgorithm,
|
|
241
249
|
issuer: stringOrDefault(pickValue(json, "Issuer", "issuer"), ""),
|
|
242
250
|
audience: stringOrDefault(pickValue(json, "Audience", "audience"), ""),
|
|
@@ -356,6 +364,12 @@ function normalizeLicensingApiBaseUrl(value) {
|
|
|
356
364
|
const normalized = (value ?? "").trim();
|
|
357
365
|
return normalized || DEFAULT_LICENSING_API_BASE_URL;
|
|
358
366
|
}
|
|
367
|
+
function resolveLicensingApiBaseUrl() {
|
|
368
|
+
return normalizeLicensingApiBaseUrl(process.env.LOADSTRIKE_LICENSING_API_BASE_URL ?? developmentLicensingApiBaseUrlOverride);
|
|
369
|
+
}
|
|
370
|
+
function setDevelopmentLicensingApiBaseUrlOverride(value) {
|
|
371
|
+
developmentLicensingApiBaseUrlOverride = value;
|
|
372
|
+
}
|
|
359
373
|
function normalizeTimeoutMs(value) {
|
|
360
374
|
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
361
375
|
return 10000;
|
|
@@ -411,14 +425,8 @@ function collectRequestedFeatures(request) {
|
|
|
411
425
|
if (hasCustomSink) {
|
|
412
426
|
features.add("extensions.reporting_sinks.custom");
|
|
413
427
|
}
|
|
414
|
-
if (pickValue(context, "ReportFinalizer", "reportFinalizer") != null) {
|
|
415
|
-
features.add("policy.report_finalizer_and_threshold_controls");
|
|
416
|
-
}
|
|
417
428
|
for (const scenarioValue of scenarios) {
|
|
418
429
|
const scenario = asRecord(scenarioValue);
|
|
419
|
-
for (const feature of normalizeStringArray(pickValue(scenario, "LicenseFeatures", "licenseFeatures"))) {
|
|
420
|
-
features.add(feature);
|
|
421
|
-
}
|
|
422
430
|
if (asList(scenario.Thresholds).length > 0) {
|
|
423
431
|
features.add("policy.report_finalizer_and_threshold_controls");
|
|
424
432
|
}
|
|
@@ -708,6 +716,8 @@ async function evaluateScenarioOutcome(scenario, requestCount, context) {
|
|
|
708
716
|
sourceTrackingField: sourceEndpoint.trackingField,
|
|
709
717
|
destinationTrackingField: destinationEndpoint?.trackingField,
|
|
710
718
|
destinationGatherByField: destinationEndpoint?.gatherByField,
|
|
719
|
+
trackingFieldValueCaseSensitive: toBoolean(pickValue(tracking, "TrackingFieldValueCaseSensitive", "trackingFieldValueCaseSensitive"), true),
|
|
720
|
+
gatherByFieldValueCaseSensitive: toBoolean(pickValue(tracking, "GatherByFieldValueCaseSensitive", "gatherByFieldValueCaseSensitive"), true),
|
|
711
721
|
correlationTimeoutMs: timeoutMs,
|
|
712
722
|
timeoutCountsAsFailure,
|
|
713
723
|
store: correlationStore ?? undefined
|
|
@@ -1088,11 +1098,11 @@ function normalizePayload(payload, endpoint, index) {
|
|
|
1088
1098
|
function readTrackingId(payload, selector) {
|
|
1089
1099
|
const normalized = selector.trim().toLowerCase();
|
|
1090
1100
|
if (normalized.startsWith("header:")) {
|
|
1091
|
-
const expected = selector.slice("header:".length).trim()
|
|
1101
|
+
const expected = selector.slice("header:".length).trim();
|
|
1092
1102
|
const headers = payload.headers ?? {};
|
|
1093
1103
|
for (const [key, value] of Object.entries(headers)) {
|
|
1094
1104
|
const normalizedValue = String(value ?? "").trim();
|
|
1095
|
-
if (key
|
|
1105
|
+
if (key === expected && normalizedValue) {
|
|
1096
1106
|
return normalizedValue;
|
|
1097
1107
|
}
|
|
1098
1108
|
}
|
|
@@ -1533,8 +1543,8 @@ function isRuntimeReportingSink(value) {
|
|
|
1533
1543
|
"SaveRealtimeStats",
|
|
1534
1544
|
"saveRealtimeMetrics",
|
|
1535
1545
|
"SaveRealtimeMetrics",
|
|
1536
|
-
"
|
|
1537
|
-
"
|
|
1546
|
+
"saveRunResult",
|
|
1547
|
+
"SaveRunResult",
|
|
1538
1548
|
"stop",
|
|
1539
1549
|
"Stop"
|
|
1540
1550
|
].some((name) => typeof record[name] === "function");
|
|
@@ -1560,6 +1570,20 @@ function stringOrDefault(value, fallback) {
|
|
|
1560
1570
|
}
|
|
1561
1571
|
return String(value);
|
|
1562
1572
|
}
|
|
1573
|
+
function normalizePemText(value) {
|
|
1574
|
+
let text = stringOrDefault(value, "").trim();
|
|
1575
|
+
if (!text) {
|
|
1576
|
+
return "";
|
|
1577
|
+
}
|
|
1578
|
+
if (text.length >= 2 && text.startsWith("\"") && text.endsWith("\"")) {
|
|
1579
|
+
text = text.slice(1, -1).trim();
|
|
1580
|
+
}
|
|
1581
|
+
text = text.replace(/\\r\\n/g, "\n").replace(/\\n/g, "\n").replace(/\\r/g, "\r").trim();
|
|
1582
|
+
if (text.length >= 2 && text.startsWith("\"") && text.endsWith("\"")) {
|
|
1583
|
+
text = text.slice(1, -1).trim();
|
|
1584
|
+
}
|
|
1585
|
+
return text;
|
|
1586
|
+
}
|
|
1563
1587
|
function asInt(value) {
|
|
1564
1588
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1565
1589
|
return Math.trunc(value);
|
|
@@ -1842,3 +1866,64 @@ function resolveTimeoutSeconds(context, secondsKey, secondsAlias, millisecondsKe
|
|
|
1842
1866
|
function asList(value) {
|
|
1843
1867
|
return Array.isArray(value) ? value : [];
|
|
1844
1868
|
}
|
|
1869
|
+
export const __loadstrikeTestExports = {
|
|
1870
|
+
addIfNotBlank,
|
|
1871
|
+
asNullableInt,
|
|
1872
|
+
asNumber,
|
|
1873
|
+
buildThresholdExpression,
|
|
1874
|
+
collectClaimStrings,
|
|
1875
|
+
collectRequestedFeatures,
|
|
1876
|
+
computeScenarioRequestCount,
|
|
1877
|
+
countCustomWorkerPlugins,
|
|
1878
|
+
countTargetedScenarios,
|
|
1879
|
+
decodeBase64Url,
|
|
1880
|
+
decodeJwtJsonSegment,
|
|
1881
|
+
deviceHash,
|
|
1882
|
+
enforceEntitlementClaims,
|
|
1883
|
+
enforceJwtLifetime,
|
|
1884
|
+
enforceRuntimePolicyClaims,
|
|
1885
|
+
evaluateScenarioOutcome,
|
|
1886
|
+
evaluateScenarioThresholds,
|
|
1887
|
+
fileContains,
|
|
1888
|
+
hasLinuxDesktopSession,
|
|
1889
|
+
hasTruthyEnv,
|
|
1890
|
+
inferLegacyHttpResponseSourceValue,
|
|
1891
|
+
isContainerHost,
|
|
1892
|
+
isLinuxLocalHost,
|
|
1893
|
+
isLocalHost,
|
|
1894
|
+
isRuntimeReportingSink,
|
|
1895
|
+
mapCorrelationStore,
|
|
1896
|
+
mapEnvironmentClassification,
|
|
1897
|
+
mapEndpointSpec,
|
|
1898
|
+
normalizeEndpointPayloadValue,
|
|
1899
|
+
normalizeLicensingApiBaseUrl,
|
|
1900
|
+
resolveLicensingApiBaseUrl,
|
|
1901
|
+
normalizeNodeType,
|
|
1902
|
+
normalizePayload,
|
|
1903
|
+
normalizeStringArray,
|
|
1904
|
+
normalizeTimeoutMs,
|
|
1905
|
+
parseBodyAsObject,
|
|
1906
|
+
parseJwt,
|
|
1907
|
+
readEpochClaim,
|
|
1908
|
+
readLinuxMachineId,
|
|
1909
|
+
readMacPlatformUuid,
|
|
1910
|
+
readOptionalTrackingSelectorValue,
|
|
1911
|
+
readRedisCorrelationStoreOptions,
|
|
1912
|
+
readTrackingId,
|
|
1913
|
+
readWindowsMachineGuid,
|
|
1914
|
+
resolveRuntimePolicy,
|
|
1915
|
+
resolveTimeoutSeconds,
|
|
1916
|
+
sanitizeLooseJson,
|
|
1917
|
+
sanitizeRequest,
|
|
1918
|
+
setJsonPathValue,
|
|
1919
|
+
setDevelopmentLicensingApiBaseUrlOverride,
|
|
1920
|
+
sleep,
|
|
1921
|
+
stringOrDefault,
|
|
1922
|
+
toBoolean,
|
|
1923
|
+
toContractNodeType,
|
|
1924
|
+
toStringMap,
|
|
1925
|
+
tryParseJson,
|
|
1926
|
+
validateRedisCorrelationStoreConfiguration,
|
|
1927
|
+
validateTrackingConfiguration,
|
|
1928
|
+
verifyJwtSignature
|
|
1929
|
+
};
|
package/dist/esm/reporting.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
-
import os from "node:os";
|
|
3
2
|
import { dirname, resolve } from "node:path";
|
|
4
3
|
import { fileURLToPath } from "node:url";
|
|
5
|
-
const REPORT_EOL =
|
|
4
|
+
const REPORT_EOL = "\n";
|
|
6
5
|
const REPORT_FALLBACK_SVG = "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 128 128'><defs><linearGradient id='g' x1='0' y1='0' x2='1' y2='1'><stop offset='0' stop-color='#64b5ff'/><stop offset='1' stop-color='#2f66db'/></linearGradient></defs><rect width='128' height='128' rx='24' fill='#081325'/><path d='M24 94L56 24l16 34 14-22 18 58h-16l-7-23-9 13-10-21-14 31H24z' fill='url(#g)'/></svg>";
|
|
7
6
|
const REPORT_LOGO_CACHE = new Map();
|
|
8
7
|
function resolveReportModuleDir() {
|
|
@@ -1256,3 +1255,20 @@ if(btns.length>0){show(btns[0].dataset.tab);}renderAllCharts();initPanePan();win
|
|
|
1256
1255
|
.split("__CHART_DATA__").join(chartDataJson)
|
|
1257
1256
|
.concat(REPORT_EOL);
|
|
1258
1257
|
}
|
|
1258
|
+
export const __loadstrikeTestExports = {
|
|
1259
|
+
buildDotnetFailedResponseContent,
|
|
1260
|
+
buildDotnetFailedResponseHtml,
|
|
1261
|
+
buildDotnetGroupedCorrelationSummaryHtml,
|
|
1262
|
+
buildDotnetHtmlTabs,
|
|
1263
|
+
buildDotnetMetricHtml,
|
|
1264
|
+
buildDotnetPluginHints,
|
|
1265
|
+
buildDotnetScenarioHtml,
|
|
1266
|
+
buildDotnetScenarioMeasurementHtml,
|
|
1267
|
+
buildDotnetStatusCodeHtml,
|
|
1268
|
+
buildDotnetStepHtml,
|
|
1269
|
+
buildDotnetStepMeasurementHtml,
|
|
1270
|
+
buildDotnetThresholdHtml,
|
|
1271
|
+
buildDotnetUngroupedCorrelationSummaryHtml,
|
|
1272
|
+
buildUngroupedCorrelationChartPayload,
|
|
1273
|
+
classifyStatusCodeBucket
|
|
1274
|
+
};
|