@bitfab/sdk 0.36.8 → 0.36.10
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-QUX6N7ON.js → chunk-AAMRJGZJ.js} +89 -19
- package/dist/chunk-AAMRJGZJ.js.map +1 -0
- package/dist/{chunk-B4HK3BPE.js → chunk-RSM2TLKG.js} +3 -3
- package/dist/index.cjs +88 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +2 -2
- package/dist/node.cjs +88 -19
- package/dist/node.cjs.map +1 -1
- package/dist/node.js +2 -2
- package/dist/{replay-7PUB6ZOG.js → replay-WKWBBIGE.js} +4 -2
- package/package.json +1 -1
- package/dist/chunk-QUX6N7ON.js.map +0 -1
- /package/dist/{chunk-B4HK3BPE.js.map → chunk-RSM2TLKG.js.map} +0 -0
- /package/dist/{replay-7PUB6ZOG.js.map → replay-WKWBBIGE.js.map} +0 -0
package/dist/index.d.cts
CHANGED
|
@@ -353,6 +353,12 @@ interface DeliveryReport {
|
|
|
353
353
|
closed: boolean;
|
|
354
354
|
/** Every carrier submitted under this trace came back accepted. */
|
|
355
355
|
delivered: boolean;
|
|
356
|
+
/**
|
|
357
|
+
* The server's assigned `traces.id`, read back from the OTLP ingest response.
|
|
358
|
+
* Absent when talking to a server that predates this field, or before any
|
|
359
|
+
* carrier for the trace has been acked.
|
|
360
|
+
*/
|
|
361
|
+
serverTraceId?: string;
|
|
356
362
|
}
|
|
357
363
|
declare class HttpClient {
|
|
358
364
|
private readonly apiKey;
|
|
@@ -390,6 +396,12 @@ declare class HttpClient {
|
|
|
390
396
|
* that was never tracked, so ordinary tracing costs no bookkeeping at all.
|
|
391
397
|
*/
|
|
392
398
|
trackTraceDeliveries(traceIds: string[]): void;
|
|
399
|
+
/**
|
|
400
|
+
* The server's assigned `traces.id` for a tracked trace if it has already
|
|
401
|
+
* been read back off an ingest response, without stopping tracking. Lets a
|
|
402
|
+
* replay surface the id mid-run for items whose spans already landed.
|
|
403
|
+
*/
|
|
404
|
+
peekServerTraceId(traceId: string): string | undefined;
|
|
393
405
|
/** Whether any tracked trace has had its closing carrier submitted. */
|
|
394
406
|
hasClosedDeliveries(traceIds: string[]): boolean;
|
|
395
407
|
/**
|
|
@@ -410,6 +422,12 @@ declare class HttpClient {
|
|
|
410
422
|
* delivered ref is proof its row exists: the same fact the replay status
|
|
411
423
|
* endpoint would report, already in hand.
|
|
412
424
|
*/
|
|
425
|
+
/**
|
|
426
|
+
* Record the server's assigned `traces.id` for each tracked source trace,
|
|
427
|
+
* read back from the OTLP ingest response. Keyed by source trace id, the same
|
|
428
|
+
* key the delivery ledger uses. Untracked ids are ignored.
|
|
429
|
+
*/
|
|
430
|
+
private recordServerTraceIds;
|
|
413
431
|
private recordDeliveredCarriers;
|
|
414
432
|
/**
|
|
415
433
|
* Track deferred span work so this client's own lifecycle waits for it, and
|
|
@@ -2557,7 +2575,7 @@ declare class BitfabFunction {
|
|
|
2557
2575
|
/**
|
|
2558
2576
|
* SDK version from package.json (injected at build time)
|
|
2559
2577
|
*/
|
|
2560
|
-
declare const __version__ = "0.36.
|
|
2578
|
+
declare const __version__ = "0.36.10";
|
|
2561
2579
|
|
|
2562
2580
|
/**
|
|
2563
2581
|
* Constants for the Bitfab SDK.
|
package/dist/index.d.ts
CHANGED
|
@@ -353,6 +353,12 @@ interface DeliveryReport {
|
|
|
353
353
|
closed: boolean;
|
|
354
354
|
/** Every carrier submitted under this trace came back accepted. */
|
|
355
355
|
delivered: boolean;
|
|
356
|
+
/**
|
|
357
|
+
* The server's assigned `traces.id`, read back from the OTLP ingest response.
|
|
358
|
+
* Absent when talking to a server that predates this field, or before any
|
|
359
|
+
* carrier for the trace has been acked.
|
|
360
|
+
*/
|
|
361
|
+
serverTraceId?: string;
|
|
356
362
|
}
|
|
357
363
|
declare class HttpClient {
|
|
358
364
|
private readonly apiKey;
|
|
@@ -390,6 +396,12 @@ declare class HttpClient {
|
|
|
390
396
|
* that was never tracked, so ordinary tracing costs no bookkeeping at all.
|
|
391
397
|
*/
|
|
392
398
|
trackTraceDeliveries(traceIds: string[]): void;
|
|
399
|
+
/**
|
|
400
|
+
* The server's assigned `traces.id` for a tracked trace if it has already
|
|
401
|
+
* been read back off an ingest response, without stopping tracking. Lets a
|
|
402
|
+
* replay surface the id mid-run for items whose spans already landed.
|
|
403
|
+
*/
|
|
404
|
+
peekServerTraceId(traceId: string): string | undefined;
|
|
393
405
|
/** Whether any tracked trace has had its closing carrier submitted. */
|
|
394
406
|
hasClosedDeliveries(traceIds: string[]): boolean;
|
|
395
407
|
/**
|
|
@@ -410,6 +422,12 @@ declare class HttpClient {
|
|
|
410
422
|
* delivered ref is proof its row exists: the same fact the replay status
|
|
411
423
|
* endpoint would report, already in hand.
|
|
412
424
|
*/
|
|
425
|
+
/**
|
|
426
|
+
* Record the server's assigned `traces.id` for each tracked source trace,
|
|
427
|
+
* read back from the OTLP ingest response. Keyed by source trace id, the same
|
|
428
|
+
* key the delivery ledger uses. Untracked ids are ignored.
|
|
429
|
+
*/
|
|
430
|
+
private recordServerTraceIds;
|
|
413
431
|
private recordDeliveredCarriers;
|
|
414
432
|
/**
|
|
415
433
|
* Track deferred span work so this client's own lifecycle waits for it, and
|
|
@@ -2557,7 +2575,7 @@ declare class BitfabFunction {
|
|
|
2557
2575
|
/**
|
|
2558
2576
|
* SDK version from package.json (injected at build time)
|
|
2559
2577
|
*/
|
|
2560
|
-
declare const __version__ = "0.36.
|
|
2578
|
+
declare const __version__ = "0.36.10";
|
|
2561
2579
|
|
|
2562
2580
|
/**
|
|
2563
2581
|
* Constants for the Bitfab SDK.
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
getCurrentReplayBranch,
|
|
12
12
|
getCurrentSpan,
|
|
13
13
|
getCurrentTrace
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-RSM2TLKG.js";
|
|
15
15
|
import {
|
|
16
16
|
BITFAB_PROGRESS_PREFIX,
|
|
17
17
|
BitfabError,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
flushTraces,
|
|
24
24
|
reportReplayProgress,
|
|
25
25
|
serializeReplayResult
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-AAMRJGZJ.js";
|
|
27
27
|
export {
|
|
28
28
|
BITFAB_PROGRESS_PREFIX,
|
|
29
29
|
Bitfab,
|
package/dist/node.cjs
CHANGED
|
@@ -88,7 +88,7 @@ var __version__;
|
|
|
88
88
|
var init_version_generated = __esm({
|
|
89
89
|
"src/version.generated.ts"() {
|
|
90
90
|
"use strict";
|
|
91
|
-
__version__ = "0.36.
|
|
91
|
+
__version__ = "0.36.10";
|
|
92
92
|
}
|
|
93
93
|
});
|
|
94
94
|
|
|
@@ -1442,6 +1442,10 @@ var init_http = __esm({
|
|
|
1442
1442
|
...error instanceof BitfabError && error.retryAfterMs !== void 0 ? { retryAfterMs: error.retryAfterMs } : {}
|
|
1443
1443
|
});
|
|
1444
1444
|
}
|
|
1445
|
+
const serverTraceIds = asPayloadRecord(response?.traceIds);
|
|
1446
|
+
if (serverTraceIds !== void 0) {
|
|
1447
|
+
this.recordServerTraceIds(serverTraceIds);
|
|
1448
|
+
}
|
|
1445
1449
|
const partialSuccess = asPayloadRecord(response?.partialSuccess);
|
|
1446
1450
|
const rejected = partialSuccess?.rejectedSpans;
|
|
1447
1451
|
if (rejected !== void 0 && rejected !== "0" && rejected !== 0) {
|
|
@@ -1466,6 +1470,14 @@ var init_http = __esm({
|
|
|
1466
1470
|
}
|
|
1467
1471
|
}
|
|
1468
1472
|
}
|
|
1473
|
+
/**
|
|
1474
|
+
* The server's assigned `traces.id` for a tracked trace if it has already
|
|
1475
|
+
* been read back off an ingest response, without stopping tracking. Lets a
|
|
1476
|
+
* replay surface the id mid-run for items whose spans already landed.
|
|
1477
|
+
*/
|
|
1478
|
+
peekServerTraceId(traceId) {
|
|
1479
|
+
return this.traceDeliveries.get(traceId)?.serverTraceId;
|
|
1480
|
+
}
|
|
1469
1481
|
/** Whether any tracked trace has had its closing carrier submitted. */
|
|
1470
1482
|
hasClosedDeliveries(traceIds) {
|
|
1471
1483
|
return traceIds.some((traceId) => this.traceDeliveries.get(traceId)?.closed);
|
|
@@ -1492,7 +1504,8 @@ var init_http = __esm({
|
|
|
1492
1504
|
closed: delivery.closed,
|
|
1493
1505
|
delivered: delivery.closingAcked && [...delivery.submittedSpanIds].every(
|
|
1494
1506
|
(spanId) => delivery.ackedSpanIds.has(spanId)
|
|
1495
|
-
)
|
|
1507
|
+
),
|
|
1508
|
+
serverTraceId: delivery.serverTraceId
|
|
1496
1509
|
};
|
|
1497
1510
|
}
|
|
1498
1511
|
return reports;
|
|
@@ -1521,6 +1534,23 @@ var init_http = __esm({
|
|
|
1521
1534
|
* delivered ref is proof its row exists: the same fact the replay status
|
|
1522
1535
|
* endpoint would report, already in hand.
|
|
1523
1536
|
*/
|
|
1537
|
+
/**
|
|
1538
|
+
* Record the server's assigned `traces.id` for each tracked source trace,
|
|
1539
|
+
* read back from the OTLP ingest response. Keyed by source trace id, the same
|
|
1540
|
+
* key the delivery ledger uses. Untracked ids are ignored.
|
|
1541
|
+
*/
|
|
1542
|
+
recordServerTraceIds(map) {
|
|
1543
|
+
for (const [sourceTraceId, serverTraceId] of Object.entries(map)) {
|
|
1544
|
+
if (typeof serverTraceId !== "string") {
|
|
1545
|
+
continue;
|
|
1546
|
+
}
|
|
1547
|
+
const delivery = this.traceDeliveries.get(sourceTraceId);
|
|
1548
|
+
if (delivery === void 0) {
|
|
1549
|
+
continue;
|
|
1550
|
+
}
|
|
1551
|
+
delivery.serverTraceId = serverTraceId;
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1524
1554
|
recordDeliveredCarriers(refs) {
|
|
1525
1555
|
for (const ref of refs) {
|
|
1526
1556
|
const delivery = this.traceDeliveries.get(ref.traceId);
|
|
@@ -2362,6 +2392,7 @@ __export(replay_exports, {
|
|
|
2362
2392
|
replay: () => replay,
|
|
2363
2393
|
reportReplayProgress: () => reportReplayProgress,
|
|
2364
2394
|
serializeReplayResult: () => serializeReplayResult,
|
|
2395
|
+
sleepForReplayPersistence: () => sleepForReplayPersistence,
|
|
2365
2396
|
waitForReplayPersistence: () => waitForReplayPersistence
|
|
2366
2397
|
});
|
|
2367
2398
|
function dbBranchEnabled(dbBranch) {
|
|
@@ -2657,13 +2688,17 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
2657
2688
|
}
|
|
2658
2689
|
if (!httpClient.hasClosedDeliveries(replayedTraceIds)) {
|
|
2659
2690
|
httpClient.takeTraceDeliveries(replayedTraceIds);
|
|
2660
|
-
return;
|
|
2691
|
+
return {};
|
|
2661
2692
|
}
|
|
2662
2693
|
const flushed = await flushTraces(REPLAY_PERSISTENCE_TIMEOUT_MS);
|
|
2663
2694
|
const deliveries = httpClient.takeTraceDeliveries(replayedTraceIds);
|
|
2664
2695
|
const expectedSpanCounts = {};
|
|
2696
|
+
const readBackTraceIds = {};
|
|
2665
2697
|
let allDelivered = true;
|
|
2666
2698
|
for (const [traceId, delivery] of Object.entries(deliveries)) {
|
|
2699
|
+
if (delivery.serverTraceId !== void 0) {
|
|
2700
|
+
readBackTraceIds[traceId] = delivery.serverTraceId;
|
|
2701
|
+
}
|
|
2667
2702
|
if (!delivery.closed) {
|
|
2668
2703
|
continue;
|
|
2669
2704
|
}
|
|
@@ -2671,7 +2706,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
2671
2706
|
allDelivered = allDelivered && delivery.delivered;
|
|
2672
2707
|
}
|
|
2673
2708
|
if (allDelivered) {
|
|
2674
|
-
return;
|
|
2709
|
+
return readBackTraceIds;
|
|
2675
2710
|
}
|
|
2676
2711
|
const deadline = Date.now() + REPLAY_PERSISTENCE_TIMEOUT_MS;
|
|
2677
2712
|
let missing = Object.keys(expectedSpanCounts).length;
|
|
@@ -2685,22 +2720,23 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
2685
2720
|
(traceId) => ready[traceId] === void 0
|
|
2686
2721
|
).length;
|
|
2687
2722
|
if (missing === 0) {
|
|
2688
|
-
return;
|
|
2723
|
+
return readBackTraceIds;
|
|
2689
2724
|
}
|
|
2690
2725
|
if (Date.now() >= deadline) {
|
|
2691
2726
|
break;
|
|
2692
2727
|
}
|
|
2693
|
-
await
|
|
2728
|
+
await sleepForReplayPersistence(
|
|
2729
|
+
Math.min(100, Math.max(0, deadline - Date.now()))
|
|
2730
|
+
);
|
|
2694
2731
|
}
|
|
2695
2732
|
const cause = flushed ? "" : " Delivery was also not confirmed before the flush deadline, so the spans likely never reached the server.";
|
|
2696
2733
|
throw new BitfabError(
|
|
2697
2734
|
`Replay traces were not fully persisted before the delivery deadline (testRunId ${testRunId}, missing ${missing} of ${Object.keys(expectedSpanCounts).length} trace(s)).${cause}`
|
|
2698
2735
|
);
|
|
2699
2736
|
}
|
|
2700
|
-
function
|
|
2737
|
+
function sleepForReplayPersistence(ms) {
|
|
2701
2738
|
return new Promise((resolve) => {
|
|
2702
|
-
|
|
2703
|
-
unrefTimer(timer);
|
|
2739
|
+
setTimeout(resolve, ms);
|
|
2704
2740
|
});
|
|
2705
2741
|
}
|
|
2706
2742
|
async function mapWithConcurrency2(tasks, maxConcurrency, onSettled, onStarted) {
|
|
@@ -2712,7 +2748,7 @@ async function mapWithConcurrency2(tasks, maxConcurrency, onSettled, onStarted)
|
|
|
2712
2748
|
onStarted?.(index);
|
|
2713
2749
|
const result = await tasks[index]();
|
|
2714
2750
|
results[index] = result;
|
|
2715
|
-
onSettled?.(result, index);
|
|
2751
|
+
await onSettled?.(result, index);
|
|
2716
2752
|
}
|
|
2717
2753
|
}
|
|
2718
2754
|
const workers = Array.from(
|
|
@@ -2802,10 +2838,36 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2802
2838
|
let started = 0;
|
|
2803
2839
|
let succeeded = 0;
|
|
2804
2840
|
let errored = 0;
|
|
2841
|
+
let flushInFlight = null;
|
|
2842
|
+
let flushPending = false;
|
|
2843
|
+
const flushFinishedItemTrace = () => {
|
|
2844
|
+
flushPending = true;
|
|
2845
|
+
if (!flushInFlight) {
|
|
2846
|
+
flushInFlight = (async () => {
|
|
2847
|
+
try {
|
|
2848
|
+
while (flushPending) {
|
|
2849
|
+
flushPending = false;
|
|
2850
|
+
await httpClient.settleDeferredWork(REPLAY_PERSISTENCE_TIMEOUT_MS);
|
|
2851
|
+
await flushTraces(REPLAY_PERSISTENCE_TIMEOUT_MS);
|
|
2852
|
+
}
|
|
2853
|
+
} finally {
|
|
2854
|
+
flushInFlight = null;
|
|
2855
|
+
}
|
|
2856
|
+
})();
|
|
2857
|
+
}
|
|
2858
|
+
return flushInFlight;
|
|
2859
|
+
};
|
|
2805
2860
|
const resultItems = await mapWithConcurrency2(
|
|
2806
2861
|
tasks,
|
|
2807
2862
|
maxConcurrency,
|
|
2808
|
-
(item) => {
|
|
2863
|
+
async (item, index) => {
|
|
2864
|
+
let serverTraceId = null;
|
|
2865
|
+
try {
|
|
2866
|
+
await flushFinishedItemTrace();
|
|
2867
|
+
serverTraceId = httpClient.peekServerTraceId(replayedTraceIds[index]) ?? null;
|
|
2868
|
+
} catch {
|
|
2869
|
+
}
|
|
2870
|
+
item.traceId = serverTraceId;
|
|
2809
2871
|
completed += 1;
|
|
2810
2872
|
if (item.error === null) {
|
|
2811
2873
|
succeeded += 1;
|
|
@@ -2820,11 +2882,12 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2820
2882
|
succeeded,
|
|
2821
2883
|
errored,
|
|
2822
2884
|
item: {
|
|
2823
|
-
// The server
|
|
2824
|
-
//
|
|
2825
|
-
//
|
|
2826
|
-
//
|
|
2827
|
-
|
|
2885
|
+
// The server's assigned traces.id, read back off the ingest
|
|
2886
|
+
// response and surfaced as this item finishes. Null only if the
|
|
2887
|
+
// per-item flush could not confirm delivery in time; the end-of-run
|
|
2888
|
+
// barrier then fills the returned ReplayItem. The client-side
|
|
2889
|
+
// placeholder is never surfaced.
|
|
2890
|
+
traceId: serverTraceId,
|
|
2828
2891
|
originalTraceId: item.originalTraceId ?? null,
|
|
2829
2892
|
originalSpanId: item.originalSpanId ?? null,
|
|
2830
2893
|
// Deprecated aliases for originalTraceId/originalSpanId.
|
|
@@ -2870,12 +2933,19 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2870
2933
|
}
|
|
2871
2934
|
} : void 0
|
|
2872
2935
|
);
|
|
2873
|
-
await preserveReplayFailure(
|
|
2936
|
+
const deliveredTraceIds = await preserveReplayFailure(
|
|
2874
2937
|
() => waitForReplayPersistence(httpClient, testRunId, replayedTraceIds),
|
|
2875
2938
|
resultItems,
|
|
2876
2939
|
testRunId,
|
|
2877
2940
|
fullTestRunUrl
|
|
2878
2941
|
);
|
|
2942
|
+
for (let index = 0; index < resultItems.length; index += 1) {
|
|
2943
|
+
const localId = replayedTraceIds[index];
|
|
2944
|
+
const readBack = localId ? deliveredTraceIds[localId] : void 0;
|
|
2945
|
+
if (readBack !== void 0) {
|
|
2946
|
+
resultItems[index].traceId = readBack;
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
2879
2949
|
const completeResult = await preserveReplayFailure(
|
|
2880
2950
|
() => httpClient.completeReplay(testRunId),
|
|
2881
2951
|
resultItems,
|
|
@@ -2891,7 +2961,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2891
2961
|
const item = resultItems[index];
|
|
2892
2962
|
const localId = replayedTraceIds[index];
|
|
2893
2963
|
const mapped = localId ? serverTraceIds[localId] : void 0;
|
|
2894
|
-
item.traceId = mapped ?? null;
|
|
2964
|
+
item.traceId = item.traceId ?? mapped ?? null;
|
|
2895
2965
|
if (item.error === null) {
|
|
2896
2966
|
completedCount += 1;
|
|
2897
2967
|
if (mapped === void 0) {
|
|
@@ -2979,7 +3049,6 @@ var init_replay = __esm({
|
|
|
2979
3049
|
init_randomUuid();
|
|
2980
3050
|
init_replayContext();
|
|
2981
3051
|
init_serialize();
|
|
2982
|
-
init_unrefTimer();
|
|
2983
3052
|
REPLAY_PERSISTENCE_TIMEOUT_MS = 3e4;
|
|
2984
3053
|
BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
|
|
2985
3054
|
ReplayError = class extends BitfabError {
|