@glasstrace/sdk 0.12.1 → 0.12.3
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-MSMOH6IH.js → chunk-J576N5MN.js} +2 -1
- package/dist/index.cjs +109 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +109 -8
- package/dist/index.js.map +1 -1
- package/dist/{source-map-uploader-ZFCYOURS.js → source-map-uploader-ZHD654EG.js} +2 -2
- package/package.json +1 -1
- /package/dist/{chunk-MSMOH6IH.js.map → chunk-J576N5MN.js.map} +0 -0
- /package/dist/{source-map-uploader-ZFCYOURS.js.map → source-map-uploader-ZHD654EG.js.map} +0 -0
package/dist/index.d.cts
CHANGED
|
@@ -307,7 +307,7 @@ interface InitClaimResult {
|
|
|
307
307
|
* or request failure). Callers that do not need claim information
|
|
308
308
|
* can safely ignore the return value.
|
|
309
309
|
*/
|
|
310
|
-
declare function performInit(config: ResolvedConfig, anonKey: AnonApiKey | null, sdkVersion: string): Promise<InitClaimResult | null>;
|
|
310
|
+
declare function performInit(config: ResolvedConfig, anonKey: AnonApiKey | null, sdkVersion: string, healthReport?: SdkHealthReport | null): Promise<InitClaimResult | null>;
|
|
311
311
|
/**
|
|
312
312
|
* Returns the current capture config from the three-tier fallback chain:
|
|
313
313
|
* 1. In-memory config from latest init response
|
|
@@ -394,6 +394,10 @@ declare class GlasstraceExporter implements SpanExporter {
|
|
|
394
394
|
*/
|
|
395
395
|
notifyKeyResolved(): void;
|
|
396
396
|
shutdown(): Promise<void>;
|
|
397
|
+
/**
|
|
398
|
+
* Flushes any pending buffered spans (if the API key has resolved) and
|
|
399
|
+
* delegates to the underlying exporter's forceFlush to drain its queue.
|
|
400
|
+
*/
|
|
397
401
|
forceFlush(): Promise<void>;
|
|
398
402
|
/**
|
|
399
403
|
* Enriches a ReadableSpan with all glasstrace.* attributes.
|
package/dist/index.d.ts
CHANGED
|
@@ -307,7 +307,7 @@ interface InitClaimResult {
|
|
|
307
307
|
* or request failure). Callers that do not need claim information
|
|
308
308
|
* can safely ignore the return value.
|
|
309
309
|
*/
|
|
310
|
-
declare function performInit(config: ResolvedConfig, anonKey: AnonApiKey | null, sdkVersion: string): Promise<InitClaimResult | null>;
|
|
310
|
+
declare function performInit(config: ResolvedConfig, anonKey: AnonApiKey | null, sdkVersion: string, healthReport?: SdkHealthReport | null): Promise<InitClaimResult | null>;
|
|
311
311
|
/**
|
|
312
312
|
* Returns the current capture config from the three-tier fallback chain:
|
|
313
313
|
* 1. In-memory config from latest init response
|
|
@@ -394,6 +394,10 @@ declare class GlasstraceExporter implements SpanExporter {
|
|
|
394
394
|
*/
|
|
395
395
|
notifyKeyResolved(): void;
|
|
396
396
|
shutdown(): Promise<void>;
|
|
397
|
+
/**
|
|
398
|
+
* Flushes any pending buffered spans (if the API key has resolved) and
|
|
399
|
+
* delegates to the underlying exporter's forceFlush to drain its queue.
|
|
400
|
+
*/
|
|
397
401
|
forceFlush(): Promise<void>;
|
|
398
402
|
/**
|
|
399
403
|
* Enriches a ReadableSpan with all glasstrace.* attributes.
|
package/dist/index.js
CHANGED
|
@@ -9,10 +9,11 @@ import {
|
|
|
9
9
|
maybeShowMcpNudge,
|
|
10
10
|
readEnvVars,
|
|
11
11
|
resolveConfig,
|
|
12
|
+
sdkLog,
|
|
12
13
|
uploadSourceMaps,
|
|
13
14
|
uploadSourceMapsAuto,
|
|
14
15
|
uploadSourceMapsPresigned
|
|
15
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-J576N5MN.js";
|
|
16
17
|
import {
|
|
17
18
|
buildImportGraph,
|
|
18
19
|
discoverTestFiles,
|
|
@@ -30,6 +31,7 @@ import {
|
|
|
30
31
|
SessionIdSchema
|
|
31
32
|
} from "./chunk-OKIP4SRG.js";
|
|
32
33
|
import {
|
|
34
|
+
DiagLogLevel,
|
|
33
35
|
INVALID_SPAN_CONTEXT,
|
|
34
36
|
SamplingDecision,
|
|
35
37
|
SpanKind,
|
|
@@ -173,6 +175,58 @@ function classifyFetchTarget(url) {
|
|
|
173
175
|
return "unknown";
|
|
174
176
|
}
|
|
175
177
|
|
|
178
|
+
// src/health-collector.ts
|
|
179
|
+
var tracesExported = 0;
|
|
180
|
+
var tracesDropped = 0;
|
|
181
|
+
var initFailures = 0;
|
|
182
|
+
var lastConfigSyncAt = null;
|
|
183
|
+
function recordSpansExported(count) {
|
|
184
|
+
if (!Number.isFinite(count) || count < 0 || !Number.isInteger(count)) return;
|
|
185
|
+
tracesExported += count;
|
|
186
|
+
}
|
|
187
|
+
function recordSpansDropped(count) {
|
|
188
|
+
if (!Number.isFinite(count) || count < 0 || !Number.isInteger(count)) return;
|
|
189
|
+
tracesDropped += count;
|
|
190
|
+
}
|
|
191
|
+
function recordInitFailure() {
|
|
192
|
+
try {
|
|
193
|
+
initFailures += 1;
|
|
194
|
+
} catch {
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function recordConfigSync(timestamp) {
|
|
198
|
+
try {
|
|
199
|
+
lastConfigSyncAt = timestamp;
|
|
200
|
+
} catch {
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function collectHealthReport(sdkVersion) {
|
|
204
|
+
try {
|
|
205
|
+
const now = Date.now();
|
|
206
|
+
const configAge = lastConfigSyncAt !== null ? Math.max(0, now - lastConfigSyncAt) : 0;
|
|
207
|
+
return {
|
|
208
|
+
tracesExportedSinceLastInit: tracesExported,
|
|
209
|
+
tracesDropped,
|
|
210
|
+
initFailures,
|
|
211
|
+
configAge: Math.round(configAge),
|
|
212
|
+
sdkVersion
|
|
213
|
+
};
|
|
214
|
+
} catch {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function acknowledgeHealthReport(report) {
|
|
219
|
+
const exp = Math.max(0, report.tracesExportedSinceLastInit);
|
|
220
|
+
const expVal = tracesExported - exp;
|
|
221
|
+
tracesExported = Number.isFinite(expVal) ? Math.max(0, expVal) : tracesExported;
|
|
222
|
+
const drop = Math.max(0, report.tracesDropped);
|
|
223
|
+
const dropVal = tracesDropped - drop;
|
|
224
|
+
tracesDropped = Number.isFinite(dropVal) ? Math.max(0, dropVal) : tracesDropped;
|
|
225
|
+
const fail = Math.max(0, report.initFailures);
|
|
226
|
+
const failVal = initFailures - fail;
|
|
227
|
+
initFailures = Number.isFinite(failVal) ? Math.max(0, failVal) : initFailures;
|
|
228
|
+
}
|
|
229
|
+
|
|
176
230
|
// src/init-client.ts
|
|
177
231
|
var GLASSTRACE_DIR = ".glasstrace";
|
|
178
232
|
var CONFIG_FILE = "config";
|
|
@@ -222,6 +276,7 @@ function loadCachedConfig(projectRoot) {
|
|
|
222
276
|
}
|
|
223
277
|
const result = SdkInitResponseSchema.safeParse(cached.response);
|
|
224
278
|
if (result.success) {
|
|
279
|
+
recordConfigSync(cached.cachedAt);
|
|
225
280
|
return result.data;
|
|
226
281
|
}
|
|
227
282
|
console.warn("[glasstrace] Cached config failed validation. Using defaults.");
|
|
@@ -372,7 +427,7 @@ async function writeClaimedKey(newApiKey, projectRoot) {
|
|
|
372
427
|
} catch {
|
|
373
428
|
}
|
|
374
429
|
}
|
|
375
|
-
async function performInit(config, anonKey, sdkVersion) {
|
|
430
|
+
async function performInit(config, anonKey, sdkVersion, healthReport) {
|
|
376
431
|
if (rateLimitBackoff) {
|
|
377
432
|
rateLimitBackoff = false;
|
|
378
433
|
return null;
|
|
@@ -391,12 +446,16 @@ async function performInit(config, anonKey, sdkVersion) {
|
|
|
391
446
|
anonKey,
|
|
392
447
|
sdkVersion,
|
|
393
448
|
void 0,
|
|
394
|
-
void 0,
|
|
449
|
+
healthReport ?? void 0,
|
|
395
450
|
void 0,
|
|
396
451
|
controller.signal
|
|
397
452
|
);
|
|
398
453
|
clearTimeout(timeoutId);
|
|
399
454
|
currentConfig = result;
|
|
455
|
+
recordConfigSync(Date.now());
|
|
456
|
+
if (healthReport) {
|
|
457
|
+
acknowledgeHealthReport(healthReport);
|
|
458
|
+
}
|
|
400
459
|
await saveCachedConfig(result);
|
|
401
460
|
if (result.claimResult) {
|
|
402
461
|
try {
|
|
@@ -408,6 +467,7 @@ async function performInit(config, anonKey, sdkVersion) {
|
|
|
408
467
|
return null;
|
|
409
468
|
} catch (err) {
|
|
410
469
|
clearTimeout(timeoutId);
|
|
470
|
+
recordInitFailure();
|
|
411
471
|
if (err instanceof DOMException && err.name === "AbortError") {
|
|
412
472
|
console.warn("[glasstrace] ingestion_unreachable: Init request timed out.");
|
|
413
473
|
return null;
|
|
@@ -442,6 +502,7 @@ async function performInit(config, anonKey, sdkVersion) {
|
|
|
442
502
|
return null;
|
|
443
503
|
}
|
|
444
504
|
} catch (err) {
|
|
505
|
+
recordInitFailure();
|
|
445
506
|
console.warn(
|
|
446
507
|
`[glasstrace] Unexpected init error: ${err instanceof Error ? err.message : String(err)}`
|
|
447
508
|
);
|
|
@@ -526,8 +587,15 @@ var GlasstraceExporter = class {
|
|
|
526
587
|
const enrichedSpans = spans.map((span) => this.enrichSpan(span));
|
|
527
588
|
const exporter = this.ensureDelegate();
|
|
528
589
|
if (exporter) {
|
|
529
|
-
exporter.export(enrichedSpans,
|
|
590
|
+
exporter.export(enrichedSpans, (result) => {
|
|
591
|
+
if (result.code !== 0) {
|
|
592
|
+
sdkLog("warn", `[glasstrace] Span export failed: ${result.error?.message ?? "unknown error"}`);
|
|
593
|
+
}
|
|
594
|
+
resultCallback(result);
|
|
595
|
+
});
|
|
596
|
+
recordSpansExported(enrichedSpans.length);
|
|
530
597
|
} else {
|
|
598
|
+
recordSpansDropped(enrichedSpans.length);
|
|
531
599
|
resultCallback({ code: 0 });
|
|
532
600
|
}
|
|
533
601
|
}
|
|
@@ -546,6 +614,7 @@ var GlasstraceExporter = class {
|
|
|
546
614
|
console.warn(
|
|
547
615
|
`[glasstrace] Shutdown with ${this.pendingSpanCount} buffered spans \u2014 API key never resolved, spans lost.`
|
|
548
616
|
);
|
|
617
|
+
recordSpansDropped(this.pendingSpanCount);
|
|
549
618
|
for (const batch of this.pendingBatches) {
|
|
550
619
|
batch.resultCallback({ code: 0 });
|
|
551
620
|
}
|
|
@@ -556,7 +625,14 @@ var GlasstraceExporter = class {
|
|
|
556
625
|
return this.delegate.shutdown();
|
|
557
626
|
}
|
|
558
627
|
}
|
|
628
|
+
/**
|
|
629
|
+
* Flushes any pending buffered spans (if the API key has resolved) and
|
|
630
|
+
* delegates to the underlying exporter's forceFlush to drain its queue.
|
|
631
|
+
*/
|
|
559
632
|
forceFlush() {
|
|
633
|
+
if (this.getApiKey() !== API_KEY_PENDING && this.pendingBatches.length > 0) {
|
|
634
|
+
this.flushPending();
|
|
635
|
+
}
|
|
560
636
|
if (this.delegate?.forceFlush) {
|
|
561
637
|
return this.delegate.forceFlush();
|
|
562
638
|
}
|
|
@@ -688,6 +764,7 @@ var GlasstraceExporter = class {
|
|
|
688
764
|
while (this.pendingSpanCount > MAX_PENDING_SPANS && this.pendingBatches.length > 1) {
|
|
689
765
|
const evicted = this.pendingBatches.shift();
|
|
690
766
|
this.pendingSpanCount -= evicted.spans.length;
|
|
767
|
+
recordSpansDropped(evicted.spans.length);
|
|
691
768
|
evicted.resultCallback({ code: 0 });
|
|
692
769
|
if (!this.overflowLogged) {
|
|
693
770
|
this.overflowLogged = true;
|
|
@@ -709,9 +786,12 @@ var GlasstraceExporter = class {
|
|
|
709
786
|
if (this.pendingBatches.length === 0) return;
|
|
710
787
|
const exporter = this.ensureDelegate();
|
|
711
788
|
if (!exporter) {
|
|
789
|
+
let discardedCount = 0;
|
|
712
790
|
for (const batch of this.pendingBatches) {
|
|
791
|
+
discardedCount += batch.spans.length;
|
|
713
792
|
batch.resultCallback({ code: 0 });
|
|
714
793
|
}
|
|
794
|
+
recordSpansDropped(discardedCount);
|
|
715
795
|
this.pendingBatches = [];
|
|
716
796
|
this.pendingSpanCount = 0;
|
|
717
797
|
return;
|
|
@@ -721,7 +801,13 @@ var GlasstraceExporter = class {
|
|
|
721
801
|
this.pendingSpanCount = 0;
|
|
722
802
|
for (const batch of batches) {
|
|
723
803
|
const enriched = batch.spans.map((span) => this.enrichSpan(span));
|
|
724
|
-
exporter.export(enriched,
|
|
804
|
+
exporter.export(enriched, (result) => {
|
|
805
|
+
if (result.code !== 0) {
|
|
806
|
+
sdkLog("warn", `[glasstrace] Span export failed: ${result.error?.message ?? "unknown error"}`);
|
|
807
|
+
}
|
|
808
|
+
batch.resultCallback(result);
|
|
809
|
+
});
|
|
810
|
+
recordSpansExported(enriched.length);
|
|
725
811
|
}
|
|
726
812
|
}
|
|
727
813
|
};
|
|
@@ -3511,7 +3597,21 @@ async function configureOtel(config, sessionManager) {
|
|
|
3511
3597
|
_activeExporter = null;
|
|
3512
3598
|
return;
|
|
3513
3599
|
}
|
|
3514
|
-
|
|
3600
|
+
if (config.verbose) {
|
|
3601
|
+
diag.setLogger(
|
|
3602
|
+
{
|
|
3603
|
+
verbose: (msg) => sdkLog("info", `[otel] ${msg}`),
|
|
3604
|
+
debug: (msg) => sdkLog("info", `[otel] ${msg}`),
|
|
3605
|
+
info: (msg) => sdkLog("info", `[otel] ${msg}`),
|
|
3606
|
+
warn: (msg) => sdkLog("warn", `[otel] ${msg}`),
|
|
3607
|
+
error: (msg) => sdkLog("error", `[otel] ${msg}`)
|
|
3608
|
+
},
|
|
3609
|
+
DiagLogLevel.WARN
|
|
3610
|
+
);
|
|
3611
|
+
}
|
|
3612
|
+
const processor = new BatchSpanProcessor(glasstraceExporter, {
|
|
3613
|
+
scheduledDelayMillis: 1e3
|
|
3614
|
+
});
|
|
3515
3615
|
const provider = new BasicTracerProvider({
|
|
3516
3616
|
spanProcessors: [processor]
|
|
3517
3617
|
});
|
|
@@ -3672,7 +3772,8 @@ async function backgroundInit(config, anonKeyForInit, generation) {
|
|
|
3672
3772
|
if (config.verbose) {
|
|
3673
3773
|
console.info("[glasstrace] Background init firing.");
|
|
3674
3774
|
}
|
|
3675
|
-
const
|
|
3775
|
+
const healthReport = collectHealthReport("0.12.3");
|
|
3776
|
+
const initResult = await performInit(config, anonKeyForInit, "0.12.3", healthReport);
|
|
3676
3777
|
if (generation !== registrationGeneration) return;
|
|
3677
3778
|
if (initResult?.claimResult) {
|
|
3678
3779
|
setResolvedApiKey(initResult.claimResult.newApiKey);
|
|
@@ -3746,7 +3847,7 @@ async function handleSourceMapUpload(distDir) {
|
|
|
3746
3847
|
);
|
|
3747
3848
|
return;
|
|
3748
3849
|
}
|
|
3749
|
-
const { discoverSourceMapFiles: discoverSourceMapFiles2, computeBuildHash: computeBuildHash2, uploadSourceMaps: uploadSourceMaps2 } = await import("./source-map-uploader-
|
|
3850
|
+
const { discoverSourceMapFiles: discoverSourceMapFiles2, computeBuildHash: computeBuildHash2, uploadSourceMaps: uploadSourceMaps2 } = await import("./source-map-uploader-ZHD654EG.js");
|
|
3750
3851
|
const files = await discoverSourceMapFiles2(distDir);
|
|
3751
3852
|
if (files.length === 0) {
|
|
3752
3853
|
console.info("[glasstrace] No source map files found. Skipping upload.");
|