bitfab 0.36.7 → 0.36.9
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/dist/{chunk-CFECTUDU.js → chunk-MBKY42QC.js} +379 -160
- package/dist/chunk-MBKY42QC.js.map +1 -0
- package/dist/{chunk-EDOZ3DP3.js → chunk-TJAFKZ4X.js} +3 -3
- package/dist/index.cjs +389 -164
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +56 -8
- package/dist/index.d.ts +56 -8
- package/dist/index.js +2 -2
- package/dist/node.cjs +389 -164
- package/dist/node.cjs.map +1 -1
- package/dist/node.js +2 -2
- package/dist/replay-MH5QFXET.js +21 -0
- package/package.json +1 -1
- package/dist/chunk-CFECTUDU.js.map +0 -1
- package/dist/replay-RAKYO5UI.js +0 -17
- /package/dist/{chunk-EDOZ3DP3.js.map → chunk-TJAFKZ4X.js.map} +0 -0
- /package/dist/{replay-RAKYO5UI.js.map → replay-MH5QFXET.js.map} +0 -0
package/dist/node.cjs
CHANGED
|
@@ -97,7 +97,7 @@ var __version__;
|
|
|
97
97
|
var init_version_generated = __esm({
|
|
98
98
|
"src/version.generated.ts"() {
|
|
99
99
|
"use strict";
|
|
100
|
-
__version__ = "0.36.
|
|
100
|
+
__version__ = "0.36.9";
|
|
101
101
|
}
|
|
102
102
|
});
|
|
103
103
|
|
|
@@ -223,10 +223,11 @@ var init_errors = __esm({
|
|
|
223
223
|
"src/errors.ts"() {
|
|
224
224
|
"use strict";
|
|
225
225
|
BitfabError = class extends Error {
|
|
226
|
-
constructor(message, url, status) {
|
|
226
|
+
constructor(message, url, status, retryAfterMs) {
|
|
227
227
|
super(message);
|
|
228
228
|
this.url = url;
|
|
229
229
|
this.status = status;
|
|
230
|
+
this.retryAfterMs = retryAfterMs;
|
|
230
231
|
this.name = "BitfabError";
|
|
231
232
|
}
|
|
232
233
|
};
|
|
@@ -542,6 +543,23 @@ var init_serializePayload = __esm({
|
|
|
542
543
|
}
|
|
543
544
|
});
|
|
544
545
|
|
|
546
|
+
// src/transportTypes.ts
|
|
547
|
+
var DeliveryError;
|
|
548
|
+
var init_transportTypes = __esm({
|
|
549
|
+
"src/transportTypes.ts"() {
|
|
550
|
+
"use strict";
|
|
551
|
+
DeliveryError = class extends Error {
|
|
552
|
+
constructor(message, options = {}) {
|
|
553
|
+
super(message);
|
|
554
|
+
this.name = "DeliveryError";
|
|
555
|
+
this.retryable = options.retryable ?? false;
|
|
556
|
+
this.oversized = options.oversized ?? false;
|
|
557
|
+
this.retryAfterMs = options.retryAfterMs;
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
|
|
545
563
|
// src/unrefTimer.ts
|
|
546
564
|
function unrefTimer(timer) {
|
|
547
565
|
const handle = timer;
|
|
@@ -581,59 +599,6 @@ function logError(message, error) {
|
|
|
581
599
|
} catch {
|
|
582
600
|
}
|
|
583
601
|
}
|
|
584
|
-
function recordTraceSubmission(operation, payload) {
|
|
585
|
-
const sourceTraceId = resolveSourceTraceId(payload);
|
|
586
|
-
if (sourceTraceId === void 0) {
|
|
587
|
-
return;
|
|
588
|
-
}
|
|
589
|
-
if (operation === "external_span") {
|
|
590
|
-
const rawSpan = asRecord2(payload.rawSpan);
|
|
591
|
-
if (typeof rawSpan?.id !== "string") {
|
|
592
|
-
submissionCounter += 1;
|
|
593
|
-
}
|
|
594
|
-
const sourceSpanId = typeof rawSpan?.id === "string" ? rawSpan.id : `submission-${submissionCounter}`;
|
|
595
|
-
const existing = traceSubmissionSpanIds.get(sourceTraceId);
|
|
596
|
-
if (existing) {
|
|
597
|
-
existing.add(sourceSpanId);
|
|
598
|
-
} else {
|
|
599
|
-
traceSubmissionSpanIds.set(sourceTraceId, /* @__PURE__ */ new Set([sourceSpanId]));
|
|
600
|
-
}
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
|
-
if (payload.completed !== true) {
|
|
604
|
-
return;
|
|
605
|
-
}
|
|
606
|
-
if (typeof payload.testRunId === "string") {
|
|
607
|
-
replayTraceSubmissions.add(sourceTraceId);
|
|
608
|
-
if (!traceSubmissionSpanIds.has(sourceTraceId)) {
|
|
609
|
-
traceSubmissionSpanIds.set(sourceTraceId, /* @__PURE__ */ new Set());
|
|
610
|
-
}
|
|
611
|
-
} else {
|
|
612
|
-
traceSubmissionSpanIds.delete(sourceTraceId);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
function takeReplaySpanCounts(traceIds) {
|
|
616
|
-
const counts = {};
|
|
617
|
-
for (const traceId of traceIds) {
|
|
618
|
-
if (!replayTraceSubmissions.has(traceId)) {
|
|
619
|
-
continue;
|
|
620
|
-
}
|
|
621
|
-
counts[traceId] = traceSubmissionSpanIds.get(traceId)?.size ?? 0;
|
|
622
|
-
traceSubmissionSpanIds.delete(traceId);
|
|
623
|
-
replayTraceSubmissions.delete(traceId);
|
|
624
|
-
}
|
|
625
|
-
return counts;
|
|
626
|
-
}
|
|
627
|
-
function asRecord2(value) {
|
|
628
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
629
|
-
}
|
|
630
|
-
function resolveSourceTraceId(payload) {
|
|
631
|
-
if (typeof payload.sourceTraceId === "string") {
|
|
632
|
-
return payload.sourceTraceId;
|
|
633
|
-
}
|
|
634
|
-
const rawTrace = asRecord2(payload.externalTrace) ?? asRecord2(payload.rawTrace);
|
|
635
|
-
return typeof rawTrace?.id === "string" ? rawTrace.id : void 0;
|
|
636
|
-
}
|
|
637
602
|
function otlpValue(value) {
|
|
638
603
|
if (typeof value === "boolean") {
|
|
639
604
|
return { boolValue: value };
|
|
@@ -691,7 +656,11 @@ function spanToOtlp(span) {
|
|
|
691
656
|
}
|
|
692
657
|
function encodeSpan(span) {
|
|
693
658
|
const json = JSON.stringify(spanToOtlp(span));
|
|
694
|
-
return {
|
|
659
|
+
return {
|
|
660
|
+
json,
|
|
661
|
+
size: byteLength(json),
|
|
662
|
+
ref: carrierRefs.get(span)
|
|
663
|
+
};
|
|
695
664
|
}
|
|
696
665
|
function trimEncodedSpan(span) {
|
|
697
666
|
try {
|
|
@@ -774,48 +743,27 @@ async function mapWithConcurrency(items, limit, task) {
|
|
|
774
743
|
await Promise.all(workers);
|
|
775
744
|
return results;
|
|
776
745
|
}
|
|
777
|
-
function responseStatus(error) {
|
|
778
|
-
return error instanceof BitfabError ? error.status : void 0;
|
|
779
|
-
}
|
|
780
746
|
function isRetryable(error) {
|
|
781
|
-
|
|
782
|
-
if (status === void 0) {
|
|
783
|
-
return true;
|
|
784
|
-
}
|
|
785
|
-
return RETRYABLE_STATUSES.has(status) || status >= 500;
|
|
747
|
+
return error instanceof DeliveryError && error.retryable;
|
|
786
748
|
}
|
|
787
|
-
function
|
|
788
|
-
|
|
749
|
+
function isOversized(error) {
|
|
750
|
+
return error instanceof DeliveryError && error.oversized;
|
|
789
751
|
}
|
|
790
|
-
function
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
}
|
|
752
|
+
function retryWaitMillis(error, attempt, remainingMillis) {
|
|
753
|
+
const requested = error instanceof DeliveryError ? error.retryAfterMs : void 0;
|
|
754
|
+
const affordable = remainingMillis / 2;
|
|
755
|
+
if (requested !== void 0) {
|
|
756
|
+
return requested < affordable ? requested : null;
|
|
796
757
|
}
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
const rawSpan = asRecord2(payload.rawSpan);
|
|
804
|
-
const rawTrace = asRecord2(payload.externalTrace) ?? asRecord2(payload.rawTrace);
|
|
805
|
-
const raw = rawSpan?.[field] ?? rawTrace?.[field];
|
|
806
|
-
if (typeof raw !== "string") {
|
|
807
|
-
return void 0;
|
|
808
|
-
}
|
|
809
|
-
const parsed = Date.parse(raw);
|
|
810
|
-
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
758
|
+
const backoff = Math.min(
|
|
759
|
+
RETRY_BASE_DELAY_MILLIS * 2 ** attempt,
|
|
760
|
+
RETRY_BACKOFF_CEILING_MILLIS
|
|
761
|
+
);
|
|
762
|
+
const jittered = backoff / 2 + Math.random() * (backoff / 2);
|
|
763
|
+
return jittered < affordable ? jittered : null;
|
|
811
764
|
}
|
|
812
|
-
function
|
|
813
|
-
|
|
814
|
-
if (spanData?.error != null) {
|
|
815
|
-
return true;
|
|
816
|
-
}
|
|
817
|
-
const errors = payload.errors;
|
|
818
|
-
return Array.isArray(errors) ? errors.length > 0 : Boolean(errors);
|
|
765
|
+
function endSpan(span, endTime) {
|
|
766
|
+
span.end(endTime);
|
|
819
767
|
}
|
|
820
768
|
function createOtelTransport(options) {
|
|
821
769
|
return new OtelBatchTransport({
|
|
@@ -854,7 +802,7 @@ function shutdownOtelTransports(timeoutMs = DEFAULT_LIFECYCLE_TIMEOUT_MS) {
|
|
|
854
802
|
(transport, remaining) => transport.shutdown(remaining)
|
|
855
803
|
);
|
|
856
804
|
}
|
|
857
|
-
var import_api, import_core, import_resources, import_sdk_trace_base, OPERATION_ATTRIBUTE, PAYLOAD_ATTRIBUTE,
|
|
805
|
+
var import_api, import_core, import_resources, import_sdk_trace_base, OPERATION_ATTRIBUTE, PAYLOAD_ATTRIBUTE, MAX_EXPORT_REQUEST_BYTES, MAX_DECOMPRESSED_REQUEST_BYTES, MAX_REQUEST_BYTES_ENV, EXPORT_CONCURRENCY_ENV, MAX_QUEUE_SIZE, DIRECT_MAX_EXPORT_BATCH_SIZE, DIRECT_MAX_REQUEST_BATCH_SIZE, DEFAULT_EXPORT_CONCURRENCY, MAX_EXPORT_CONCURRENCY, SCHEDULE_DELAY_MILLIS, EXPORT_TIMEOUT_MILLIS, RETRY_BASE_DELAY_MILLIS, RETRY_BACKOFF_CEILING_MILLIS, MAX_SEND_ATTEMPTS, DEFAULT_LIFECYCLE_TIMEOUT_MS, liveTransports, carrierRefs, SPAN_SEPARATOR_BYTES, BitfabSpanExporter, DeliveryTrackingExporter, OtelBatchTransport;
|
|
858
806
|
var init_otel = __esm({
|
|
859
807
|
"src/otel.ts"() {
|
|
860
808
|
"use strict";
|
|
@@ -868,11 +816,11 @@ var init_otel = __esm({
|
|
|
868
816
|
init_payloadBudget();
|
|
869
817
|
init_readEnv();
|
|
870
818
|
init_serializePayload();
|
|
819
|
+
init_transportTypes();
|
|
871
820
|
init_unrefTimer();
|
|
872
821
|
init_warnOnce();
|
|
873
822
|
OPERATION_ATTRIBUTE = "bitfab.operation";
|
|
874
823
|
PAYLOAD_ATTRIBUTE = "bitfab.payload";
|
|
875
|
-
OTLP_TRACES_ENDPOINT = "/api/sdk/otel/v1/traces";
|
|
876
824
|
MAX_EXPORT_REQUEST_BYTES = 3e6;
|
|
877
825
|
MAX_DECOMPRESSED_REQUEST_BYTES = 8e6;
|
|
878
826
|
MAX_REQUEST_BYTES_ENV = "BITFAB_OTEL_MAX_REQUEST_BYTES";
|
|
@@ -884,25 +832,23 @@ var init_otel = __esm({
|
|
|
884
832
|
MAX_EXPORT_CONCURRENCY = 64;
|
|
885
833
|
SCHEDULE_DELAY_MILLIS = 5e3;
|
|
886
834
|
EXPORT_TIMEOUT_MILLIS = 3e4;
|
|
887
|
-
|
|
835
|
+
RETRY_BASE_DELAY_MILLIS = 100;
|
|
836
|
+
RETRY_BACKOFF_CEILING_MILLIS = 5e3;
|
|
888
837
|
MAX_SEND_ATTEMPTS = 3;
|
|
889
838
|
DEFAULT_LIFECYCLE_TIMEOUT_MS = 3e4;
|
|
890
|
-
RETRYABLE_STATUSES = /* @__PURE__ */ new Set([408, 425, 429]);
|
|
891
839
|
liveTransports = /* @__PURE__ */ new Set();
|
|
892
|
-
|
|
893
|
-
replayTraceSubmissions = /* @__PURE__ */ new Set();
|
|
894
|
-
submissionCounter = 0;
|
|
840
|
+
carrierRefs = /* @__PURE__ */ new WeakMap();
|
|
895
841
|
SPAN_SEPARATOR_BYTES = 1;
|
|
896
|
-
OtlpPayloadTooLargeError = class extends Error {
|
|
897
|
-
};
|
|
898
|
-
OtlpPartialSuccessError = class extends Error {
|
|
899
|
-
};
|
|
900
842
|
BitfabSpanExporter = class {
|
|
901
|
-
constructor(directSender, maxRequestBytes, maxRequestBatchSize, exportConcurrency) {
|
|
843
|
+
constructor(directSender, maxRequestBytes, maxRequestBatchSize, exportConcurrency, onDelivered, exportTimeoutMillis = EXPORT_TIMEOUT_MILLIS) {
|
|
902
844
|
this.directSender = directSender;
|
|
903
845
|
this.maxRequestBytes = maxRequestBytes;
|
|
904
846
|
this.maxRequestBatchSize = maxRequestBatchSize;
|
|
905
847
|
this.exportConcurrency = exportConcurrency;
|
|
848
|
+
this.onDelivered = onDelivered;
|
|
849
|
+
this.exportTimeoutMillis = exportTimeoutMillis;
|
|
850
|
+
/** Epoch ms until which the server has asked this exporter to stay away. */
|
|
851
|
+
this.throttledUntil = 0;
|
|
906
852
|
}
|
|
907
853
|
export(spans, resultCallback) {
|
|
908
854
|
void this.exportAsync(spans).then(
|
|
@@ -968,6 +914,7 @@ var init_otel = __esm({
|
|
|
968
914
|
);
|
|
969
915
|
if (prepared.wireBytes <= this.maxRequestBytes) {
|
|
970
916
|
await this.sendWithRetries(prepared);
|
|
917
|
+
this.reportDelivered(batch.spans);
|
|
971
918
|
return true;
|
|
972
919
|
}
|
|
973
920
|
}
|
|
@@ -995,15 +942,12 @@ var init_otel = __esm({
|
|
|
995
942
|
alreadyTrimmed = true;
|
|
996
943
|
}
|
|
997
944
|
} catch (error) {
|
|
998
|
-
if (error
|
|
945
|
+
if (isOversized(error)) {
|
|
999
946
|
logError(
|
|
1000
947
|
batch.spans.length === 1 ? "a single OpenTelemetry span exceeded the ingestion request limit and could not be exported" : "an OpenTelemetry span batch exceeded the ingestion request limit and could not be exported"
|
|
1001
948
|
);
|
|
1002
949
|
return false;
|
|
1003
950
|
}
|
|
1004
|
-
if (error instanceof OtlpPartialSuccessError) {
|
|
1005
|
-
return false;
|
|
1006
|
-
}
|
|
1007
951
|
logError("failed to export an OpenTelemetry span batch", error);
|
|
1008
952
|
return false;
|
|
1009
953
|
}
|
|
@@ -1021,37 +965,79 @@ var init_otel = __esm({
|
|
|
1021
965
|
* the server does not yet understand. The fix is a client-supplied
|
|
1022
966
|
* idempotency key that ingestion dedupes on.
|
|
1023
967
|
*/
|
|
968
|
+
/**
|
|
969
|
+
* Remember a throttle the server asked for, so the requests fanned out
|
|
970
|
+
* alongside this one respect it too. Delaying only the request that was
|
|
971
|
+
* refused leaves the other seven in the window hitting a server that just
|
|
972
|
+
* asked for room.
|
|
973
|
+
*/
|
|
974
|
+
recordThrottle(error) {
|
|
975
|
+
const requested = error instanceof DeliveryError ? error.retryAfterMs : void 0;
|
|
976
|
+
if (requested !== void 0) {
|
|
977
|
+
this.throttledUntil = Math.max(
|
|
978
|
+
this.throttledUntil,
|
|
979
|
+
Date.now() + requested
|
|
980
|
+
);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Waits out an active throttle, or reports the batch undeliverable when the
|
|
985
|
+
* throttle outlasts what we are willing to hold it for. Either way nothing is
|
|
986
|
+
* sent while the server has asked us to stay away.
|
|
987
|
+
*/
|
|
988
|
+
async awaitThrottle(deadline) {
|
|
989
|
+
const remaining = this.throttledUntil - Date.now();
|
|
990
|
+
if (remaining <= 0) {
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
if (remaining >= (deadline - Date.now()) / 2) {
|
|
994
|
+
throw new DeliveryError(
|
|
995
|
+
`OTLP ingestion is throttled for another ${remaining}ms, longer than the export budget`
|
|
996
|
+
);
|
|
997
|
+
}
|
|
998
|
+
await delay(remaining);
|
|
999
|
+
}
|
|
1024
1000
|
async sendWithRetries(request) {
|
|
1001
|
+
const deadline = Date.now() + this.exportTimeoutMillis;
|
|
1025
1002
|
for (let attempt = 0; attempt < MAX_SEND_ATTEMPTS; attempt += 1) {
|
|
1026
1003
|
try {
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
request,
|
|
1030
|
-
EXPORT_TIMEOUT_MILLIS
|
|
1031
|
-
);
|
|
1032
|
-
const partialSuccess = asRecord2(response?.partialSuccess);
|
|
1033
|
-
const rejected = partialSuccess?.rejectedSpans;
|
|
1034
|
-
if (rejected !== void 0 && rejected !== "0" && rejected !== 0) {
|
|
1035
|
-
logError(
|
|
1036
|
-
`OTLP ingestion rejected ${rejected} span(s): ${partialSuccess?.errorMessage ?? "no reason provided"}`
|
|
1037
|
-
);
|
|
1038
|
-
throw new OtlpPartialSuccessError();
|
|
1039
|
-
}
|
|
1004
|
+
await this.awaitThrottle(deadline);
|
|
1005
|
+
await this.directSender(request, Math.max(0, deadline - Date.now()));
|
|
1040
1006
|
return;
|
|
1041
1007
|
} catch (error) {
|
|
1042
|
-
if (error
|
|
1008
|
+
if (isOversized(error)) {
|
|
1043
1009
|
throw error;
|
|
1044
1010
|
}
|
|
1045
|
-
|
|
1046
|
-
throw new OtlpPayloadTooLargeError();
|
|
1047
|
-
}
|
|
1011
|
+
this.recordThrottle(error);
|
|
1048
1012
|
if (attempt === MAX_SEND_ATTEMPTS - 1 || !isRetryable(error)) {
|
|
1049
1013
|
throw error;
|
|
1050
1014
|
}
|
|
1051
|
-
|
|
1015
|
+
const wait = retryWaitMillis(error, attempt, deadline - Date.now());
|
|
1016
|
+
if (wait === null) {
|
|
1017
|
+
throw error;
|
|
1018
|
+
}
|
|
1019
|
+
await delay(wait);
|
|
1052
1020
|
}
|
|
1053
1021
|
}
|
|
1054
1022
|
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Announce the carriers a request delivered. Wrapped because a listener that
|
|
1025
|
+
* throws must never turn a delivered batch into a failed export.
|
|
1026
|
+
*/
|
|
1027
|
+
reportDelivered(spans) {
|
|
1028
|
+
if (this.onDelivered === void 0) {
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
const refs = spans.map((span) => span.ref).filter((ref) => ref !== void 0);
|
|
1032
|
+
if (refs.length === 0) {
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
try {
|
|
1036
|
+
this.onDelivered(refs);
|
|
1037
|
+
} catch (error) {
|
|
1038
|
+
logError("a delivery listener threw", error);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1055
1041
|
async shutdown() {
|
|
1056
1042
|
}
|
|
1057
1043
|
async forceFlush() {
|
|
@@ -1109,7 +1095,9 @@ var init_otel = __esm({
|
|
|
1109
1095
|
options.directSender,
|
|
1110
1096
|
maxRequestBytes,
|
|
1111
1097
|
maxRequestBatchSize,
|
|
1112
|
-
options.exportConcurrency ?? DEFAULT_EXPORT_CONCURRENCY
|
|
1098
|
+
options.exportConcurrency ?? DEFAULT_EXPORT_CONCURRENCY,
|
|
1099
|
+
options.onDelivered,
|
|
1100
|
+
options.exportTimeoutMillis ?? EXPORT_TIMEOUT_MILLIS
|
|
1113
1101
|
)
|
|
1114
1102
|
);
|
|
1115
1103
|
this.processor = new import_sdk_trace_base.BatchSpanProcessor(this.deliveryTracker, {
|
|
@@ -1133,8 +1121,7 @@ var init_otel = __esm({
|
|
|
1133
1121
|
this.tracer = this.provider.getTracer("bitfab", __version__);
|
|
1134
1122
|
liveTransports.add(this);
|
|
1135
1123
|
}
|
|
1136
|
-
submit(operation, payload) {
|
|
1137
|
-
recordTraceSubmission(operation, payload);
|
|
1124
|
+
submit(operation, payload, meta = {}) {
|
|
1138
1125
|
if (this.closed) {
|
|
1139
1126
|
warnOnce(
|
|
1140
1127
|
"otel-submit-after-shutdown",
|
|
@@ -1155,17 +1142,20 @@ var init_otel = __esm({
|
|
|
1155
1142
|
].join(", ")}); they were stubbed so the span still ships, but the trace may be incomplete or not replayable.`
|
|
1156
1143
|
);
|
|
1157
1144
|
}
|
|
1158
|
-
const span = this.tracer.startSpan(
|
|
1145
|
+
const span = this.tracer.startSpan(meta.name ?? `bitfab.${operation}`, {
|
|
1159
1146
|
attributes: {
|
|
1160
1147
|
[OPERATION_ATTRIBUTE]: operation,
|
|
1161
1148
|
[PAYLOAD_ATTRIBUTE]: body
|
|
1162
1149
|
},
|
|
1163
|
-
startTime:
|
|
1150
|
+
startTime: meta.startTime
|
|
1164
1151
|
});
|
|
1165
|
-
if (
|
|
1152
|
+
if (meta.ref !== void 0) {
|
|
1153
|
+
carrierRefs.set(span, meta.ref);
|
|
1154
|
+
}
|
|
1155
|
+
if (meta.errored === true) {
|
|
1166
1156
|
span.setStatus({ code: import_api.SpanStatusCode.ERROR });
|
|
1167
1157
|
}
|
|
1168
|
-
endSpan(span,
|
|
1158
|
+
endSpan(span, meta.endTime);
|
|
1169
1159
|
} catch (error) {
|
|
1170
1160
|
logError("failed to queue an OpenTelemetry span", error);
|
|
1171
1161
|
}
|
|
@@ -1215,9 +1205,6 @@ function flushTraceTransports(timeoutMs) {
|
|
|
1215
1205
|
function shutdownTraceTransports(timeoutMs) {
|
|
1216
1206
|
return shutdownOtelTransports(timeoutMs);
|
|
1217
1207
|
}
|
|
1218
|
-
function takeReplaySpanCounts2(traceIds) {
|
|
1219
|
-
return takeReplaySpanCounts(traceIds);
|
|
1220
|
-
}
|
|
1221
1208
|
var init_transport = __esm({
|
|
1222
1209
|
"src/transport.ts"() {
|
|
1223
1210
|
"use strict";
|
|
@@ -1266,7 +1253,96 @@ async function waitForPromises(promises, timeoutMs) {
|
|
|
1266
1253
|
}
|
|
1267
1254
|
}
|
|
1268
1255
|
}
|
|
1269
|
-
|
|
1256
|
+
function readHeader(response, name) {
|
|
1257
|
+
try {
|
|
1258
|
+
return response.headers?.get(name) ?? null;
|
|
1259
|
+
} catch {
|
|
1260
|
+
return null;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
function parseRetryAfterMs(header) {
|
|
1264
|
+
const value = header?.trim();
|
|
1265
|
+
if (!value) {
|
|
1266
|
+
return void 0;
|
|
1267
|
+
}
|
|
1268
|
+
const seconds = Number(value);
|
|
1269
|
+
if (Number.isFinite(seconds)) {
|
|
1270
|
+
return seconds >= 0 ? seconds * 1e3 : void 0;
|
|
1271
|
+
}
|
|
1272
|
+
const at = Date.parse(value);
|
|
1273
|
+
if (Number.isNaN(at)) {
|
|
1274
|
+
return void 0;
|
|
1275
|
+
}
|
|
1276
|
+
return Math.max(0, at - Date.now());
|
|
1277
|
+
}
|
|
1278
|
+
function carrierMeta(operation, payload, ref) {
|
|
1279
|
+
return {
|
|
1280
|
+
ref,
|
|
1281
|
+
name: carrierName(operation, payload),
|
|
1282
|
+
startTime: payloadTimestamp(payload, "started_at"),
|
|
1283
|
+
endTime: payloadTimestamp(payload, "ended_at"),
|
|
1284
|
+
errored: payloadHasError(payload)
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
function carrierName(operation, payload) {
|
|
1288
|
+
if (operation === "external_span") {
|
|
1289
|
+
const spanData = asPayloadRecord(
|
|
1290
|
+
asPayloadRecord(payload.rawSpan)?.span_data
|
|
1291
|
+
);
|
|
1292
|
+
if (typeof spanData?.name === "string") {
|
|
1293
|
+
return spanData.name;
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
if (typeof payload.traceFunctionKey === "string") {
|
|
1297
|
+
return payload.traceFunctionKey;
|
|
1298
|
+
}
|
|
1299
|
+
return `bitfab.${operation}`;
|
|
1300
|
+
}
|
|
1301
|
+
function payloadTimestamp(payload, field) {
|
|
1302
|
+
const rawSpan = asPayloadRecord(payload.rawSpan);
|
|
1303
|
+
const rawTrace = asPayloadRecord(payload.externalTrace) ?? asPayloadRecord(payload.rawTrace);
|
|
1304
|
+
const raw = rawSpan?.[field] ?? rawTrace?.[field];
|
|
1305
|
+
if (typeof raw !== "string") {
|
|
1306
|
+
return void 0;
|
|
1307
|
+
}
|
|
1308
|
+
const parsed = Date.parse(raw);
|
|
1309
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
1310
|
+
}
|
|
1311
|
+
function payloadHasError(payload) {
|
|
1312
|
+
const spanData = asPayloadRecord(asPayloadRecord(payload.rawSpan)?.span_data);
|
|
1313
|
+
if (spanData?.error != null) {
|
|
1314
|
+
return true;
|
|
1315
|
+
}
|
|
1316
|
+
const errors = payload.errors;
|
|
1317
|
+
return Array.isArray(errors) ? errors.length > 0 : Boolean(errors);
|
|
1318
|
+
}
|
|
1319
|
+
function asPayloadRecord(value) {
|
|
1320
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
1321
|
+
}
|
|
1322
|
+
function carrierRef(payload) {
|
|
1323
|
+
const traceId = sourceTraceIdOf(payload);
|
|
1324
|
+
if (traceId === void 0) {
|
|
1325
|
+
return void 0;
|
|
1326
|
+
}
|
|
1327
|
+
const rawSpan = payload.rawSpan;
|
|
1328
|
+
if (rawSpan === void 0) {
|
|
1329
|
+
return { traceId };
|
|
1330
|
+
}
|
|
1331
|
+
const spanId = rawSpan?.id;
|
|
1332
|
+
return {
|
|
1333
|
+
traceId,
|
|
1334
|
+
spanId: typeof spanId === "string" ? spanId : `submission-${++carrierSeq}`
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1337
|
+
function sourceTraceIdOf(payload) {
|
|
1338
|
+
if (typeof payload.sourceTraceId === "string") {
|
|
1339
|
+
return payload.sourceTraceId;
|
|
1340
|
+
}
|
|
1341
|
+
const rawTrace = payload.externalTrace ?? payload.rawTrace;
|
|
1342
|
+
const id = rawTrace?.id;
|
|
1343
|
+
return typeof id === "string" ? id : void 0;
|
|
1344
|
+
}
|
|
1345
|
+
var REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS, OTLP_TRACES_ENDPOINT, RETRYABLE_STATUSES, EXIT_FLUSH_TIMEOUT_MS, DEFAULT_LIFECYCLE_TIMEOUT_MS2, pendingTracePromises, carrierSeq, HttpClient;
|
|
1270
1346
|
var init_http = __esm({
|
|
1271
1347
|
"src/http.ts"() {
|
|
1272
1348
|
"use strict";
|
|
@@ -1276,9 +1352,12 @@ var init_http = __esm({
|
|
|
1276
1352
|
init_replayContext();
|
|
1277
1353
|
init_serializePayload();
|
|
1278
1354
|
init_transport();
|
|
1355
|
+
init_transportTypes();
|
|
1279
1356
|
init_unrefTimer();
|
|
1280
1357
|
init_warnOnce();
|
|
1281
1358
|
REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS = 3e5;
|
|
1359
|
+
OTLP_TRACES_ENDPOINT = "/api/sdk/otel/v1/traces";
|
|
1360
|
+
RETRYABLE_STATUSES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
1282
1361
|
EXIT_FLUSH_TIMEOUT_MS = 5e3;
|
|
1283
1362
|
DEFAULT_LIFECYCLE_TIMEOUT_MS2 = 3e4;
|
|
1284
1363
|
pendingTracePromises = /* @__PURE__ */ new Set();
|
|
@@ -1298,8 +1377,12 @@ var init_http = __esm({
|
|
|
1298
1377
|
});
|
|
1299
1378
|
});
|
|
1300
1379
|
}
|
|
1380
|
+
carrierSeq = 0;
|
|
1301
1381
|
HttpClient = class {
|
|
1302
1382
|
constructor(config) {
|
|
1383
|
+
// Only traces a caller asked about are tracked, so ordinary tracing stores
|
|
1384
|
+
// nothing here.
|
|
1385
|
+
this.traceDeliveries = /* @__PURE__ */ new Map();
|
|
1303
1386
|
// Deferred span work owned by THIS client. The module-global set backs the
|
|
1304
1387
|
// process-wide `flushTraces()` and the exit hook, but per-client lifecycle
|
|
1305
1388
|
// must not wait on another client's slow finalize: a false `close()` failure
|
|
@@ -1335,13 +1418,131 @@ var init_http = __esm({
|
|
|
1335
1418
|
}
|
|
1336
1419
|
if (!this.traceTransport) {
|
|
1337
1420
|
this.traceTransport = createTraceTransport({
|
|
1338
|
-
directSender: (
|
|
1339
|
-
|
|
1340
|
-
})
|
|
1421
|
+
directSender: (request, timeoutMs) => this.deliverCarriers(request, timeoutMs),
|
|
1422
|
+
onDelivered: (refs) => this.recordDeliveredCarriers(refs)
|
|
1341
1423
|
});
|
|
1342
1424
|
}
|
|
1343
1425
|
return this.traceTransport;
|
|
1344
1426
|
}
|
|
1427
|
+
/**
|
|
1428
|
+
* Post one encoded batch and decide what the server's answer means, so the
|
|
1429
|
+
* transport never reads a response. Rejections and permanent statuses come
|
|
1430
|
+
* back as a non-retryable {@link DeliveryError}; anything the server might
|
|
1431
|
+
* still accept on a second try comes back retryable.
|
|
1432
|
+
*/
|
|
1433
|
+
async deliverCarriers(request, timeoutMs) {
|
|
1434
|
+
let response;
|
|
1435
|
+
try {
|
|
1436
|
+
response = await this.sendPrepared(
|
|
1437
|
+
OTLP_TRACES_ENDPOINT,
|
|
1438
|
+
request,
|
|
1439
|
+
{ timeout: timeoutMs }
|
|
1440
|
+
);
|
|
1441
|
+
} catch (error) {
|
|
1442
|
+
const status = error instanceof BitfabError ? error.status : void 0;
|
|
1443
|
+
if (status === void 0) {
|
|
1444
|
+
throw new DeliveryError(`OTLP ingestion failed: ${String(error)}`, {
|
|
1445
|
+
retryable: true
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
throw new DeliveryError(`OTLP ingestion failed with HTTP ${status}`, {
|
|
1449
|
+
retryable: RETRYABLE_STATUSES.has(status),
|
|
1450
|
+
oversized: status === 413,
|
|
1451
|
+
...error instanceof BitfabError && error.retryAfterMs !== void 0 ? { retryAfterMs: error.retryAfterMs } : {}
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
const partialSuccess = asPayloadRecord(response?.partialSuccess);
|
|
1455
|
+
const rejected = partialSuccess?.rejectedSpans;
|
|
1456
|
+
if (rejected !== void 0 && rejected !== "0" && rejected !== 0) {
|
|
1457
|
+
throw new DeliveryError(
|
|
1458
|
+
`OTLP ingestion rejected ${rejected} span(s): ${partialSuccess?.errorMessage ?? "no reason provided"}`
|
|
1459
|
+
);
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
/**
|
|
1463
|
+
* Start tracking delivery for `traceIds`. Nothing is recorded for a trace
|
|
1464
|
+
* that was never tracked, so ordinary tracing costs no bookkeeping at all.
|
|
1465
|
+
*/
|
|
1466
|
+
trackTraceDeliveries(traceIds) {
|
|
1467
|
+
for (const traceId of traceIds) {
|
|
1468
|
+
if (!this.traceDeliveries.has(traceId)) {
|
|
1469
|
+
this.traceDeliveries.set(traceId, {
|
|
1470
|
+
submittedSpanIds: /* @__PURE__ */ new Set(),
|
|
1471
|
+
ackedSpanIds: /* @__PURE__ */ new Set(),
|
|
1472
|
+
closed: false,
|
|
1473
|
+
closingAcked: false
|
|
1474
|
+
});
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
/** Whether any tracked trace has had its closing carrier submitted. */
|
|
1479
|
+
hasClosedDeliveries(traceIds) {
|
|
1480
|
+
return traceIds.some((traceId) => this.traceDeliveries.get(traceId)?.closed);
|
|
1481
|
+
}
|
|
1482
|
+
/**
|
|
1483
|
+
* Report what each tracked trace submitted and whether the server confirmed
|
|
1484
|
+
* it, and stop tracking them. Every id passed is freed, so a caller cannot
|
|
1485
|
+
* leak a record for a trace that never closed.
|
|
1486
|
+
*
|
|
1487
|
+
* `delivered` is only meaningful once a flush has settled: acks land before
|
|
1488
|
+
* an export resolves, so a flush that reported success has already collected
|
|
1489
|
+
* every ack it is going to collect.
|
|
1490
|
+
*/
|
|
1491
|
+
takeTraceDeliveries(traceIds) {
|
|
1492
|
+
const reports = {};
|
|
1493
|
+
for (const traceId of traceIds) {
|
|
1494
|
+
const delivery = this.traceDeliveries.get(traceId);
|
|
1495
|
+
if (delivery === void 0) {
|
|
1496
|
+
continue;
|
|
1497
|
+
}
|
|
1498
|
+
this.traceDeliveries.delete(traceId);
|
|
1499
|
+
reports[traceId] = {
|
|
1500
|
+
spanCount: delivery.submittedSpanIds.size,
|
|
1501
|
+
closed: delivery.closed,
|
|
1502
|
+
delivered: delivery.closingAcked && [...delivery.submittedSpanIds].every(
|
|
1503
|
+
(spanId) => delivery.ackedSpanIds.has(spanId)
|
|
1504
|
+
)
|
|
1505
|
+
};
|
|
1506
|
+
}
|
|
1507
|
+
return reports;
|
|
1508
|
+
}
|
|
1509
|
+
/** Build a carrier's meta and record what it adds to its trace's expected set. */
|
|
1510
|
+
recordedMeta(operation, payload, ref) {
|
|
1511
|
+
this.recordSubmittedCarrier(ref);
|
|
1512
|
+
return carrierMeta(operation, payload, ref);
|
|
1513
|
+
}
|
|
1514
|
+
recordSubmittedCarrier(ref) {
|
|
1515
|
+
if (ref === void 0) {
|
|
1516
|
+
return;
|
|
1517
|
+
}
|
|
1518
|
+
const delivery = this.traceDeliveries.get(ref.traceId);
|
|
1519
|
+
if (delivery === void 0) {
|
|
1520
|
+
return;
|
|
1521
|
+
}
|
|
1522
|
+
if (ref.spanId === void 0) {
|
|
1523
|
+
delivery.closed = true;
|
|
1524
|
+
} else {
|
|
1525
|
+
delivery.submittedSpanIds.add(ref.spanId);
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
/**
|
|
1529
|
+
* Ingestion commits every carrier in a request before it answers, so a
|
|
1530
|
+
* delivered ref is proof its row exists: the same fact the replay status
|
|
1531
|
+
* endpoint would report, already in hand.
|
|
1532
|
+
*/
|
|
1533
|
+
recordDeliveredCarriers(refs) {
|
|
1534
|
+
for (const ref of refs) {
|
|
1535
|
+
const delivery = this.traceDeliveries.get(ref.traceId);
|
|
1536
|
+
if (delivery === void 0) {
|
|
1537
|
+
continue;
|
|
1538
|
+
}
|
|
1539
|
+
if (ref.spanId === void 0) {
|
|
1540
|
+
delivery.closingAcked = true;
|
|
1541
|
+
} else {
|
|
1542
|
+
delivery.ackedSpanIds.add(ref.spanId);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1345
1546
|
/**
|
|
1346
1547
|
* Track deferred span work so this client's own lifecycle waits for it, and
|
|
1347
1548
|
* so the process-wide flush and exit hook do too.
|
|
@@ -1451,7 +1652,8 @@ var init_http = __esm({
|
|
|
1451
1652
|
throw new BitfabError(
|
|
1452
1653
|
`HTTP ${response.status}: ${errorText.slice(0, 500)}`,
|
|
1453
1654
|
void 0,
|
|
1454
|
-
response.status
|
|
1655
|
+
response.status,
|
|
1656
|
+
parseRetryAfterMs(readHeader(response, "retry-after"))
|
|
1455
1657
|
);
|
|
1456
1658
|
}
|
|
1457
1659
|
const result = await response.json();
|
|
@@ -1537,11 +1739,12 @@ var init_http = __esm({
|
|
|
1537
1739
|
* the OTLP carrier has no path to carry it.
|
|
1538
1740
|
*/
|
|
1539
1741
|
sendInternalTrace(functionId, payload) {
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1742
|
+
const body = { ...payload, functionId, sdkVersion: __version__ };
|
|
1743
|
+
this.getTraceTransport()?.submit(
|
|
1744
|
+
"internal_trace",
|
|
1745
|
+
body,
|
|
1746
|
+
carrierMeta("internal_trace", body, void 0)
|
|
1747
|
+
);
|
|
1545
1748
|
}
|
|
1546
1749
|
/**
|
|
1547
1750
|
* Queue an external span (from withSpan wrapper or OpenAI tracing) onto this
|
|
@@ -1550,10 +1753,11 @@ var init_http = __esm({
|
|
|
1550
1753
|
* promise.
|
|
1551
1754
|
*/
|
|
1552
1755
|
sendExternalSpan(payload) {
|
|
1553
|
-
this.getTraceTransport()?.submit(
|
|
1554
|
-
|
|
1555
|
-
sdkVersion: __version__
|
|
1556
|
-
|
|
1756
|
+
this.getTraceTransport()?.submit(
|
|
1757
|
+
"external_span",
|
|
1758
|
+
{ ...payload, sdkVersion: __version__ },
|
|
1759
|
+
this.recordedMeta("external_span", payload, carrierRef(payload))
|
|
1760
|
+
);
|
|
1557
1761
|
}
|
|
1558
1762
|
/**
|
|
1559
1763
|
* Queue an external trace completion (from OpenAI tracing) onto this
|
|
@@ -1562,10 +1766,15 @@ var init_http = __esm({
|
|
|
1562
1766
|
* server-authoritative barrier in `replay.ts`, not by awaiting this call.
|
|
1563
1767
|
*/
|
|
1564
1768
|
sendExternalTrace(payload) {
|
|
1565
|
-
this.getTraceTransport()?.submit(
|
|
1566
|
-
|
|
1567
|
-
sdkVersion: __version__
|
|
1568
|
-
|
|
1769
|
+
this.getTraceTransport()?.submit(
|
|
1770
|
+
"external_trace",
|
|
1771
|
+
{ ...payload, sdkVersion: __version__ },
|
|
1772
|
+
this.recordedMeta(
|
|
1773
|
+
"external_trace",
|
|
1774
|
+
payload,
|
|
1775
|
+
payload.completed === true ? carrierRef(payload) : void 0
|
|
1776
|
+
)
|
|
1777
|
+
);
|
|
1569
1778
|
}
|
|
1570
1779
|
/**
|
|
1571
1780
|
* Partial update of an existing trace identified by its Bitfab trace ID.
|
|
@@ -2161,7 +2370,9 @@ __export(replay_exports, {
|
|
|
2161
2370
|
ReplayError: () => ReplayError,
|
|
2162
2371
|
replay: () => replay,
|
|
2163
2372
|
reportReplayProgress: () => reportReplayProgress,
|
|
2164
|
-
serializeReplayResult: () => serializeReplayResult
|
|
2373
|
+
serializeReplayResult: () => serializeReplayResult,
|
|
2374
|
+
sleepForReplayPersistence: () => sleepForReplayPersistence,
|
|
2375
|
+
waitForReplayPersistence: () => waitForReplayPersistence
|
|
2165
2376
|
});
|
|
2166
2377
|
function dbBranchEnabled(dbBranch) {
|
|
2167
2378
|
return dbBranch !== void 0 && dbBranch !== false;
|
|
@@ -2449,15 +2660,29 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
2449
2660
|
REPLAY_PERSISTENCE_TIMEOUT_MS
|
|
2450
2661
|
);
|
|
2451
2662
|
if (!deferredSettled) {
|
|
2663
|
+
httpClient.takeTraceDeliveries(replayedTraceIds);
|
|
2452
2664
|
throw new BitfabError(
|
|
2453
2665
|
`Replay could not settle deferred span work before the deadline, so the expected span counts are incomplete (testRunId ${testRunId}).`
|
|
2454
2666
|
);
|
|
2455
2667
|
}
|
|
2456
|
-
|
|
2457
|
-
|
|
2668
|
+
if (!httpClient.hasClosedDeliveries(replayedTraceIds)) {
|
|
2669
|
+
httpClient.takeTraceDeliveries(replayedTraceIds);
|
|
2458
2670
|
return;
|
|
2459
2671
|
}
|
|
2460
2672
|
const flushed = await flushTraces(REPLAY_PERSISTENCE_TIMEOUT_MS);
|
|
2673
|
+
const deliveries = httpClient.takeTraceDeliveries(replayedTraceIds);
|
|
2674
|
+
const expectedSpanCounts = {};
|
|
2675
|
+
let allDelivered = true;
|
|
2676
|
+
for (const [traceId, delivery] of Object.entries(deliveries)) {
|
|
2677
|
+
if (!delivery.closed) {
|
|
2678
|
+
continue;
|
|
2679
|
+
}
|
|
2680
|
+
expectedSpanCounts[traceId] = delivery.spanCount;
|
|
2681
|
+
allDelivered = allDelivered && delivery.delivered;
|
|
2682
|
+
}
|
|
2683
|
+
if (allDelivered) {
|
|
2684
|
+
return;
|
|
2685
|
+
}
|
|
2461
2686
|
const deadline = Date.now() + REPLAY_PERSISTENCE_TIMEOUT_MS;
|
|
2462
2687
|
let missing = Object.keys(expectedSpanCounts).length;
|
|
2463
2688
|
while (true) {
|
|
@@ -2475,17 +2700,18 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
2475
2700
|
if (Date.now() >= deadline) {
|
|
2476
2701
|
break;
|
|
2477
2702
|
}
|
|
2478
|
-
await
|
|
2703
|
+
await sleepForReplayPersistence(
|
|
2704
|
+
Math.min(100, Math.max(0, deadline - Date.now()))
|
|
2705
|
+
);
|
|
2479
2706
|
}
|
|
2480
2707
|
const cause = flushed ? "" : " Delivery was also not confirmed before the flush deadline, so the spans likely never reached the server.";
|
|
2481
2708
|
throw new BitfabError(
|
|
2482
2709
|
`Replay traces were not fully persisted before the delivery deadline (testRunId ${testRunId}, missing ${missing} of ${Object.keys(expectedSpanCounts).length} trace(s)).${cause}`
|
|
2483
2710
|
);
|
|
2484
2711
|
}
|
|
2485
|
-
function
|
|
2712
|
+
function sleepForReplayPersistence(ms) {
|
|
2486
2713
|
return new Promise((resolve) => {
|
|
2487
|
-
|
|
2488
|
-
unrefTimer(timer);
|
|
2714
|
+
setTimeout(resolve, ms);
|
|
2489
2715
|
});
|
|
2490
2716
|
}
|
|
2491
2717
|
async function mapWithConcurrency2(tasks, maxConcurrency, onSettled, onStarted) {
|
|
@@ -2566,6 +2792,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2566
2792
|
...registeredOverrides
|
|
2567
2793
|
];
|
|
2568
2794
|
const replayedTraceIds = serverItems.map(() => randomUuid());
|
|
2795
|
+
httpClient.trackTraceDeliveries(replayedTraceIds);
|
|
2569
2796
|
const tasks = serverItems.map(
|
|
2570
2797
|
(serverItem, index) => () => processItem(
|
|
2571
2798
|
httpClient,
|
|
@@ -2763,8 +2990,6 @@ var init_replay = __esm({
|
|
|
2763
2990
|
init_randomUuid();
|
|
2764
2991
|
init_replayContext();
|
|
2765
2992
|
init_serialize();
|
|
2766
|
-
init_transport();
|
|
2767
|
-
init_unrefTimer();
|
|
2768
2993
|
REPLAY_PERSISTENCE_TIMEOUT_MS = 3e4;
|
|
2769
2994
|
BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
|
|
2770
2995
|
ReplayError = class extends BitfabError {
|