bitfab 0.36.9 → 0.36.11
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-MBKY42QC.js → chunk-EKOAKLZC.js} +100 -22
- package/dist/chunk-EKOAKLZC.js.map +1 -0
- package/dist/{chunk-TJAFKZ4X.js → chunk-VDFPZYLH.js} +3 -3
- package/dist/index.cjs +99 -21
- 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 +99 -21
- package/dist/node.cjs.map +1 -1
- package/dist/node.js +2 -2
- package/dist/{replay-MH5QFXET.js → replay-TW3ONJ3W.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-MBKY42QC.js.map +0 -1
- /package/dist/{chunk-TJAFKZ4X.js.map → chunk-VDFPZYLH.js.map} +0 -0
- /package/dist/{replay-MH5QFXET.js.map → replay-TW3ONJ3W.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.11";
|
|
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.11";
|
|
2561
2579
|
|
|
2562
2580
|
/**
|
|
2563
2581
|
* Constants for the Bitfab SDK.
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
getCurrentReplayBranch,
|
|
21
21
|
getCurrentSpan,
|
|
22
22
|
getCurrentTrace
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-VDFPZYLH.js";
|
|
24
24
|
import {
|
|
25
25
|
BITFAB_PROGRESS_PREFIX,
|
|
26
26
|
BitfabError,
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
flushTraces,
|
|
33
33
|
reportReplayProgress,
|
|
34
34
|
serializeReplayResult
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-EKOAKLZC.js";
|
|
36
36
|
export {
|
|
37
37
|
BITFAB_PROGRESS_PREFIX,
|
|
38
38
|
Bitfab,
|
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.11";
|
|
101
101
|
}
|
|
102
102
|
});
|
|
103
103
|
|
|
@@ -1451,6 +1451,10 @@ var init_http = __esm({
|
|
|
1451
1451
|
...error instanceof BitfabError && error.retryAfterMs !== void 0 ? { retryAfterMs: error.retryAfterMs } : {}
|
|
1452
1452
|
});
|
|
1453
1453
|
}
|
|
1454
|
+
const serverTraceIds = asPayloadRecord(response?.traceIds);
|
|
1455
|
+
if (serverTraceIds !== void 0) {
|
|
1456
|
+
this.recordServerTraceIds(serverTraceIds);
|
|
1457
|
+
}
|
|
1454
1458
|
const partialSuccess = asPayloadRecord(response?.partialSuccess);
|
|
1455
1459
|
const rejected = partialSuccess?.rejectedSpans;
|
|
1456
1460
|
if (rejected !== void 0 && rejected !== "0" && rejected !== 0) {
|
|
@@ -1475,6 +1479,14 @@ var init_http = __esm({
|
|
|
1475
1479
|
}
|
|
1476
1480
|
}
|
|
1477
1481
|
}
|
|
1482
|
+
/**
|
|
1483
|
+
* The server's assigned `traces.id` for a tracked trace if it has already
|
|
1484
|
+
* been read back off an ingest response, without stopping tracking. Lets a
|
|
1485
|
+
* replay surface the id mid-run for items whose spans already landed.
|
|
1486
|
+
*/
|
|
1487
|
+
peekServerTraceId(traceId) {
|
|
1488
|
+
return this.traceDeliveries.get(traceId)?.serverTraceId;
|
|
1489
|
+
}
|
|
1478
1490
|
/** Whether any tracked trace has had its closing carrier submitted. */
|
|
1479
1491
|
hasClosedDeliveries(traceIds) {
|
|
1480
1492
|
return traceIds.some((traceId) => this.traceDeliveries.get(traceId)?.closed);
|
|
@@ -1501,7 +1513,8 @@ var init_http = __esm({
|
|
|
1501
1513
|
closed: delivery.closed,
|
|
1502
1514
|
delivered: delivery.closingAcked && [...delivery.submittedSpanIds].every(
|
|
1503
1515
|
(spanId) => delivery.ackedSpanIds.has(spanId)
|
|
1504
|
-
)
|
|
1516
|
+
),
|
|
1517
|
+
serverTraceId: delivery.serverTraceId
|
|
1505
1518
|
};
|
|
1506
1519
|
}
|
|
1507
1520
|
return reports;
|
|
@@ -1530,6 +1543,23 @@ var init_http = __esm({
|
|
|
1530
1543
|
* delivered ref is proof its row exists: the same fact the replay status
|
|
1531
1544
|
* endpoint would report, already in hand.
|
|
1532
1545
|
*/
|
|
1546
|
+
/**
|
|
1547
|
+
* Record the server's assigned `traces.id` for each tracked source trace,
|
|
1548
|
+
* read back from the OTLP ingest response. Keyed by source trace id, the same
|
|
1549
|
+
* key the delivery ledger uses. Untracked ids are ignored.
|
|
1550
|
+
*/
|
|
1551
|
+
recordServerTraceIds(map) {
|
|
1552
|
+
for (const [sourceTraceId, serverTraceId] of Object.entries(map)) {
|
|
1553
|
+
if (typeof serverTraceId !== "string") {
|
|
1554
|
+
continue;
|
|
1555
|
+
}
|
|
1556
|
+
const delivery = this.traceDeliveries.get(sourceTraceId);
|
|
1557
|
+
if (delivery === void 0) {
|
|
1558
|
+
continue;
|
|
1559
|
+
}
|
|
1560
|
+
delivery.serverTraceId = serverTraceId;
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1533
1563
|
recordDeliveredCarriers(refs) {
|
|
1534
1564
|
for (const ref of refs) {
|
|
1535
1565
|
const delivery = this.traceDeliveries.get(ref.traceId);
|
|
@@ -2246,7 +2276,7 @@ async function captureCodeChangeFromGit(cwd, label) {
|
|
|
2246
2276
|
const tracked = await git(root, [
|
|
2247
2277
|
"diff",
|
|
2248
2278
|
"--name-status",
|
|
2249
|
-
"--
|
|
2279
|
+
"--find-renames",
|
|
2250
2280
|
"-z",
|
|
2251
2281
|
base,
|
|
2252
2282
|
"--",
|
|
@@ -2262,23 +2292,23 @@ async function captureCodeChangeFromGit(cwd, label) {
|
|
|
2262
2292
|
]);
|
|
2263
2293
|
const entries = [
|
|
2264
2294
|
...parseNameStatusZ(tracked ?? ""),
|
|
2265
|
-
...(untracked ?? "").split(NUL).filter((p) => p.length > 0).map((path) => ({ status: "A", path }))
|
|
2295
|
+
...(untracked ?? "").split(NUL).filter((p) => p.length > 0).map((path) => ({ status: "A", beforePath: path, path }))
|
|
2266
2296
|
];
|
|
2267
2297
|
if (entries.length === 0) {
|
|
2268
2298
|
return null;
|
|
2269
2299
|
}
|
|
2270
2300
|
const files = [];
|
|
2271
2301
|
let totalBytes = 0;
|
|
2272
|
-
for (const { status, path } of entries) {
|
|
2302
|
+
for (const { status, beforePath, path } of entries) {
|
|
2273
2303
|
if (files.length >= MAX_FILES) {
|
|
2274
2304
|
break;
|
|
2275
2305
|
}
|
|
2276
|
-
const beforeBytes = status === "A" ? 0 : await blobBytes(base,
|
|
2306
|
+
const beforeBytes = status === "A" ? 0 : await blobBytes(base, beforePath);
|
|
2277
2307
|
const afterBytes = status === "D" ? 0 : await workingBytes(path);
|
|
2278
2308
|
if (beforeBytes > MAX_FILE_BYTES || afterBytes > MAX_FILE_BYTES) {
|
|
2279
2309
|
continue;
|
|
2280
2310
|
}
|
|
2281
|
-
const before = (status === "A" ? "" : await git(root, ["show", `${base}:${
|
|
2311
|
+
const before = (status === "A" ? "" : await git(root, ["show", `${base}:${beforePath}`]) ?? "").replace(/\r\n/g, "\n");
|
|
2282
2312
|
const after = (status === "D" ? "" : await readWorkingFile(readFile, root, path)).replace(/\r\n/g, "\n");
|
|
2283
2313
|
if (before === after) {
|
|
2284
2314
|
continue;
|
|
@@ -2336,8 +2366,18 @@ async function readWorkingFile(readFile, root, path) {
|
|
|
2336
2366
|
function parseNameStatusZ(raw) {
|
|
2337
2367
|
const parts = raw.split(NUL).filter((p) => p.length > 0);
|
|
2338
2368
|
const out = [];
|
|
2339
|
-
|
|
2340
|
-
|
|
2369
|
+
let i = 0;
|
|
2370
|
+
while (i + 1 < parts.length) {
|
|
2371
|
+
const status = parts[i].charAt(0);
|
|
2372
|
+
i += 1;
|
|
2373
|
+
const beforePath = parts[i];
|
|
2374
|
+
i += 1;
|
|
2375
|
+
if ((status === "R" || status === "C") && i < parts.length) {
|
|
2376
|
+
out.push({ status, beforePath, path: parts[i] });
|
|
2377
|
+
i += 1;
|
|
2378
|
+
} else {
|
|
2379
|
+
out.push({ status, beforePath, path: beforePath });
|
|
2380
|
+
}
|
|
2341
2381
|
}
|
|
2342
2382
|
return out;
|
|
2343
2383
|
}
|
|
@@ -2667,13 +2707,17 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
2667
2707
|
}
|
|
2668
2708
|
if (!httpClient.hasClosedDeliveries(replayedTraceIds)) {
|
|
2669
2709
|
httpClient.takeTraceDeliveries(replayedTraceIds);
|
|
2670
|
-
return;
|
|
2710
|
+
return {};
|
|
2671
2711
|
}
|
|
2672
2712
|
const flushed = await flushTraces(REPLAY_PERSISTENCE_TIMEOUT_MS);
|
|
2673
2713
|
const deliveries = httpClient.takeTraceDeliveries(replayedTraceIds);
|
|
2674
2714
|
const expectedSpanCounts = {};
|
|
2715
|
+
const readBackTraceIds = {};
|
|
2675
2716
|
let allDelivered = true;
|
|
2676
2717
|
for (const [traceId, delivery] of Object.entries(deliveries)) {
|
|
2718
|
+
if (delivery.serverTraceId !== void 0) {
|
|
2719
|
+
readBackTraceIds[traceId] = delivery.serverTraceId;
|
|
2720
|
+
}
|
|
2677
2721
|
if (!delivery.closed) {
|
|
2678
2722
|
continue;
|
|
2679
2723
|
}
|
|
@@ -2681,7 +2725,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
2681
2725
|
allDelivered = allDelivered && delivery.delivered;
|
|
2682
2726
|
}
|
|
2683
2727
|
if (allDelivered) {
|
|
2684
|
-
return;
|
|
2728
|
+
return readBackTraceIds;
|
|
2685
2729
|
}
|
|
2686
2730
|
const deadline = Date.now() + REPLAY_PERSISTENCE_TIMEOUT_MS;
|
|
2687
2731
|
let missing = Object.keys(expectedSpanCounts).length;
|
|
@@ -2695,7 +2739,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
2695
2739
|
(traceId) => ready[traceId] === void 0
|
|
2696
2740
|
).length;
|
|
2697
2741
|
if (missing === 0) {
|
|
2698
|
-
return;
|
|
2742
|
+
return readBackTraceIds;
|
|
2699
2743
|
}
|
|
2700
2744
|
if (Date.now() >= deadline) {
|
|
2701
2745
|
break;
|
|
@@ -2723,7 +2767,7 @@ async function mapWithConcurrency2(tasks, maxConcurrency, onSettled, onStarted)
|
|
|
2723
2767
|
onStarted?.(index);
|
|
2724
2768
|
const result = await tasks[index]();
|
|
2725
2769
|
results[index] = result;
|
|
2726
|
-
onSettled?.(result, index);
|
|
2770
|
+
await onSettled?.(result, index);
|
|
2727
2771
|
}
|
|
2728
2772
|
}
|
|
2729
2773
|
const workers = Array.from(
|
|
@@ -2813,10 +2857,36 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2813
2857
|
let started = 0;
|
|
2814
2858
|
let succeeded = 0;
|
|
2815
2859
|
let errored = 0;
|
|
2860
|
+
let flushInFlight = null;
|
|
2861
|
+
let flushPending = false;
|
|
2862
|
+
const flushFinishedItemTrace = () => {
|
|
2863
|
+
flushPending = true;
|
|
2864
|
+
if (!flushInFlight) {
|
|
2865
|
+
flushInFlight = (async () => {
|
|
2866
|
+
try {
|
|
2867
|
+
while (flushPending) {
|
|
2868
|
+
flushPending = false;
|
|
2869
|
+
await httpClient.settleDeferredWork(REPLAY_PERSISTENCE_TIMEOUT_MS);
|
|
2870
|
+
await flushTraces(REPLAY_PERSISTENCE_TIMEOUT_MS);
|
|
2871
|
+
}
|
|
2872
|
+
} finally {
|
|
2873
|
+
flushInFlight = null;
|
|
2874
|
+
}
|
|
2875
|
+
})();
|
|
2876
|
+
}
|
|
2877
|
+
return flushInFlight;
|
|
2878
|
+
};
|
|
2816
2879
|
const resultItems = await mapWithConcurrency2(
|
|
2817
2880
|
tasks,
|
|
2818
2881
|
maxConcurrency,
|
|
2819
|
-
(item) => {
|
|
2882
|
+
async (item, index) => {
|
|
2883
|
+
let serverTraceId = null;
|
|
2884
|
+
try {
|
|
2885
|
+
await flushFinishedItemTrace();
|
|
2886
|
+
serverTraceId = httpClient.peekServerTraceId(replayedTraceIds[index]) ?? null;
|
|
2887
|
+
} catch {
|
|
2888
|
+
}
|
|
2889
|
+
item.traceId = serverTraceId;
|
|
2820
2890
|
completed += 1;
|
|
2821
2891
|
if (item.error === null) {
|
|
2822
2892
|
succeeded += 1;
|
|
@@ -2831,11 +2901,12 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2831
2901
|
succeeded,
|
|
2832
2902
|
errored,
|
|
2833
2903
|
item: {
|
|
2834
|
-
// The server
|
|
2835
|
-
//
|
|
2836
|
-
//
|
|
2837
|
-
//
|
|
2838
|
-
|
|
2904
|
+
// The server's assigned traces.id, read back off the ingest
|
|
2905
|
+
// response and surfaced as this item finishes. Null only if the
|
|
2906
|
+
// per-item flush could not confirm delivery in time; the end-of-run
|
|
2907
|
+
// barrier then fills the returned ReplayItem. The client-side
|
|
2908
|
+
// placeholder is never surfaced.
|
|
2909
|
+
traceId: serverTraceId,
|
|
2839
2910
|
originalTraceId: item.originalTraceId ?? null,
|
|
2840
2911
|
originalSpanId: item.originalSpanId ?? null,
|
|
2841
2912
|
// Deprecated aliases for originalTraceId/originalSpanId.
|
|
@@ -2881,12 +2952,19 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2881
2952
|
}
|
|
2882
2953
|
} : void 0
|
|
2883
2954
|
);
|
|
2884
|
-
await preserveReplayFailure(
|
|
2955
|
+
const deliveredTraceIds = await preserveReplayFailure(
|
|
2885
2956
|
() => waitForReplayPersistence(httpClient, testRunId, replayedTraceIds),
|
|
2886
2957
|
resultItems,
|
|
2887
2958
|
testRunId,
|
|
2888
2959
|
fullTestRunUrl
|
|
2889
2960
|
);
|
|
2961
|
+
for (let index = 0; index < resultItems.length; index += 1) {
|
|
2962
|
+
const localId = replayedTraceIds[index];
|
|
2963
|
+
const readBack = localId ? deliveredTraceIds[localId] : void 0;
|
|
2964
|
+
if (readBack !== void 0) {
|
|
2965
|
+
resultItems[index].traceId = readBack;
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2890
2968
|
const completeResult = await preserveReplayFailure(
|
|
2891
2969
|
() => httpClient.completeReplay(testRunId),
|
|
2892
2970
|
resultItems,
|
|
@@ -2902,7 +2980,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2902
2980
|
const item = resultItems[index];
|
|
2903
2981
|
const localId = replayedTraceIds[index];
|
|
2904
2982
|
const mapped = localId ? serverTraceIds[localId] : void 0;
|
|
2905
|
-
item.traceId = mapped ?? null;
|
|
2983
|
+
item.traceId = item.traceId ?? mapped ?? null;
|
|
2906
2984
|
if (item.error === null) {
|
|
2907
2985
|
completedCount += 1;
|
|
2908
2986
|
if (mapped === void 0) {
|