@dxos/tracing 0.8.4-main.bc674ce → 0.8.4-main.bd9b33e6c8
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/lib/browser/index.mjs +157 -36
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +157 -36
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/api.d.ts +3 -1
- package/dist/types/src/api.d.ts.map +1 -1
- package/dist/types/src/remote/tracing.d.ts +34 -0
- package/dist/types/src/remote/tracing.d.ts.map +1 -1
- package/dist/types/src/trace-processor.d.ts +7 -2
- package/dist/types/src/trace-processor.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -9
- package/src/api.ts +19 -12
- package/src/remote/tracing.ts +133 -11
- package/src/trace-processor.ts +25 -13
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
2
|
|
|
3
3
|
// src/api.ts
|
|
4
|
-
import { Context as
|
|
4
|
+
import { Context as Context3 } from "@dxos/context";
|
|
5
5
|
|
|
6
6
|
// src/symbols.ts
|
|
7
|
-
var symbolTracingContext = Symbol("dxos.tracing.context");
|
|
7
|
+
var symbolTracingContext = /* @__PURE__ */ Symbol("dxos.tracing.context");
|
|
8
8
|
var getTracingContext = (target) => {
|
|
9
9
|
return target[symbolTracingContext] ??= {
|
|
10
10
|
infoProperties: {},
|
|
@@ -15,6 +15,7 @@ var TRACE_SPAN_ATTRIBUTE = "dxos.trace-span";
|
|
|
15
15
|
|
|
16
16
|
// src/trace-processor.ts
|
|
17
17
|
import { unrefTimeout } from "@dxos/async";
|
|
18
|
+
import { Context as Context2 } from "@dxos/context";
|
|
18
19
|
import { LogLevel, getContextFromEntry, log } from "@dxos/log";
|
|
19
20
|
import { getPrototypeSpecificInstanceId } from "@dxos/util";
|
|
20
21
|
|
|
@@ -285,29 +286,132 @@ var RemoteMetrics = class {
|
|
|
285
286
|
};
|
|
286
287
|
|
|
287
288
|
// src/remote/tracing.ts
|
|
289
|
+
var MAX_ENDED_CONTEXTS = 1e4;
|
|
288
290
|
var RemoteTracing = class {
|
|
289
291
|
_tracing;
|
|
290
292
|
_spanMap = /* @__PURE__ */ new Map();
|
|
293
|
+
_idToSpan = /* @__PURE__ */ new Map();
|
|
294
|
+
/**
|
|
295
|
+
* Retains OTEL span contexts after spans end so that periodic/background
|
|
296
|
+
* operations referencing a completed parent (via `this._ctx`) still produce
|
|
297
|
+
* correlated child spans instead of orphaned root traces.
|
|
298
|
+
*/
|
|
299
|
+
_endedSpanContexts = /* @__PURE__ */ new Map();
|
|
300
|
+
/**
|
|
301
|
+
* Buffers flushSpan calls that arrive before a processor is registered,
|
|
302
|
+
* so early startup spans are not silently dropped.
|
|
303
|
+
*/
|
|
304
|
+
_pendingFlushes = [];
|
|
291
305
|
registerProcessor(processor) {
|
|
292
306
|
this._tracing = processor;
|
|
307
|
+
const pending = this._pendingFlushes;
|
|
308
|
+
this._pendingFlushes = null;
|
|
309
|
+
if (pending) {
|
|
310
|
+
for (const { span: span2, isEnd } of pending) {
|
|
311
|
+
this._replayFlush(span2, isEnd);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
/** Returns the opaque OTEL context for the given DXOS span ID, if one exists. */
|
|
316
|
+
getSpanContext(spanId) {
|
|
317
|
+
const tracingSpan = this._idToSpan.get(spanId);
|
|
318
|
+
if (tracingSpan) {
|
|
319
|
+
return this._spanMap.get(tracingSpan)?.spanContext;
|
|
320
|
+
}
|
|
321
|
+
return this._endedSpanContexts.get(spanId);
|
|
322
|
+
}
|
|
323
|
+
/** Wraps execution so that the remote span is active as parent context. */
|
|
324
|
+
wrapExecution(span2, fn) {
|
|
325
|
+
const remoteSpan = this._spanMap.get(span2);
|
|
326
|
+
if (remoteSpan?.wrapExecution) {
|
|
327
|
+
return remoteSpan.wrapExecution(fn);
|
|
328
|
+
}
|
|
329
|
+
return fn();
|
|
293
330
|
}
|
|
294
331
|
flushSpan(span2) {
|
|
332
|
+
if (!span2.showInRemoteTracing) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
295
335
|
if (!this._tracing) {
|
|
336
|
+
this._pendingFlushes?.push({
|
|
337
|
+
span: span2,
|
|
338
|
+
isEnd: !!span2.endTs
|
|
339
|
+
});
|
|
296
340
|
return;
|
|
297
341
|
}
|
|
298
342
|
if (!span2.endTs) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
343
|
+
this._startRemoteSpan(span2);
|
|
344
|
+
} else {
|
|
345
|
+
this._endRemoteSpan(span2);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
_startRemoteSpan(span2) {
|
|
349
|
+
let parentContext;
|
|
350
|
+
if (span2.parentId != null) {
|
|
351
|
+
const parentTracingSpan = this._idToSpan.get(span2.parentId);
|
|
352
|
+
if (parentTracingSpan) {
|
|
353
|
+
parentContext = this._spanMap.get(parentTracingSpan)?.spanContext;
|
|
354
|
+
}
|
|
355
|
+
if (parentContext == null) {
|
|
356
|
+
parentContext = this._endedSpanContexts.get(span2.parentId);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
const attributes = {};
|
|
360
|
+
if (span2.sanitizedClassName) {
|
|
361
|
+
attributes.entryPoint = span2.sanitizedClassName;
|
|
362
|
+
}
|
|
363
|
+
for (const [key, value] of Object.entries(span2.attributes)) {
|
|
364
|
+
attributes[key.startsWith("ctx.") ? key : `ctx.${key}`] = value;
|
|
365
|
+
}
|
|
366
|
+
const remoteSpan = this._tracing.startSpan({
|
|
367
|
+
name: span2.name,
|
|
368
|
+
op: span2.op ?? "function",
|
|
369
|
+
attributes,
|
|
370
|
+
parentContext
|
|
371
|
+
});
|
|
372
|
+
this._spanMap.set(span2, remoteSpan);
|
|
373
|
+
this._idToSpan.set(span2.id, span2);
|
|
374
|
+
}
|
|
375
|
+
_endRemoteSpan(span2) {
|
|
376
|
+
const remoteSpan = this._spanMap.get(span2);
|
|
377
|
+
if (remoteSpan) {
|
|
378
|
+
if (remoteSpan.spanContext != null) {
|
|
379
|
+
this._endedSpanContexts.set(span2.id, remoteSpan.spanContext);
|
|
380
|
+
this._evictEndedContexts();
|
|
381
|
+
}
|
|
382
|
+
remoteSpan.end();
|
|
383
|
+
this._spanMap.delete(span2);
|
|
384
|
+
this._idToSpan.delete(span2.id);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Replays a buffered flush that was queued before the processor was registered.
|
|
389
|
+
* For spans that started AND ended before registration, replays both events.
|
|
390
|
+
*/
|
|
391
|
+
_replayFlush(span2, isEnd) {
|
|
392
|
+
if (!isEnd) {
|
|
393
|
+
this._startRemoteSpan(span2);
|
|
394
|
+
if (span2.endTs != null) {
|
|
395
|
+
this._endRemoteSpan(span2);
|
|
396
|
+
}
|
|
305
397
|
} else {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
remoteSpan.end();
|
|
309
|
-
this._spanMap.delete(span2);
|
|
398
|
+
if (!this._spanMap.has(span2)) {
|
|
399
|
+
this._startRemoteSpan(span2);
|
|
310
400
|
}
|
|
401
|
+
this._endRemoteSpan(span2);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
_evictEndedContexts() {
|
|
405
|
+
if (this._endedSpanContexts.size <= MAX_ENDED_CONTEXTS) {
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
const iterator = this._endedSpanContexts.keys();
|
|
409
|
+
while (this._endedSpanContexts.size > MAX_ENDED_CONTEXTS) {
|
|
410
|
+
const oldest = iterator.next();
|
|
411
|
+
if (oldest.done) {
|
|
412
|
+
break;
|
|
413
|
+
}
|
|
414
|
+
this._endedSpanContexts.delete(oldest.value);
|
|
311
415
|
}
|
|
312
416
|
}
|
|
313
417
|
};
|
|
@@ -457,7 +561,7 @@ var TraceProcessor = class {
|
|
|
457
561
|
constructor() {
|
|
458
562
|
log.addProcessor(this._logProcessor.bind(this), void 0, {
|
|
459
563
|
F: __dxlog_file3,
|
|
460
|
-
L:
|
|
564
|
+
L: 104,
|
|
461
565
|
S: this,
|
|
462
566
|
C: (f, a) => f(...a)
|
|
463
567
|
});
|
|
@@ -683,7 +787,8 @@ var TracingSpan = class _TracingSpan {
|
|
|
683
787
|
endTs = null;
|
|
684
788
|
error = null;
|
|
685
789
|
_showInBrowserTimeline;
|
|
686
|
-
|
|
790
|
+
_showInRemoteTracing;
|
|
791
|
+
_ctx;
|
|
687
792
|
constructor(_traceProcessor, params) {
|
|
688
793
|
this._traceProcessor = _traceProcessor;
|
|
689
794
|
this.id = _TracingSpan.nextId++;
|
|
@@ -691,14 +796,19 @@ var TracingSpan = class _TracingSpan {
|
|
|
691
796
|
this.resourceId = _traceProcessor.getResourceId(params.instance);
|
|
692
797
|
this.startTs = performance.now();
|
|
693
798
|
this._showInBrowserTimeline = params.showInBrowserTimeline;
|
|
799
|
+
this._showInRemoteTracing = params.showInRemoteTracing ?? true;
|
|
694
800
|
this.op = params.op;
|
|
695
801
|
this.attributes = params.attributes ?? {};
|
|
802
|
+
const baseCtx = params.parentCtx ?? new Context2(void 0, {
|
|
803
|
+
F: __dxlog_file3,
|
|
804
|
+
L: 397
|
|
805
|
+
});
|
|
806
|
+
this._ctx = this._showInRemoteTracing ? baseCtx.derive({
|
|
807
|
+
attributes: {
|
|
808
|
+
[TRACE_SPAN_ATTRIBUTE]: this.id
|
|
809
|
+
}
|
|
810
|
+
}) : baseCtx.derive();
|
|
696
811
|
if (params.parentCtx) {
|
|
697
|
-
this._ctx = params.parentCtx.derive({
|
|
698
|
-
attributes: {
|
|
699
|
-
[TRACE_SPAN_ATTRIBUTE]: this.id
|
|
700
|
-
}
|
|
701
|
-
});
|
|
702
812
|
const parentId = params.parentCtx.getAttribute(TRACE_SPAN_ATTRIBUTE);
|
|
703
813
|
if (typeof parentId === "number") {
|
|
704
814
|
this.parentId = parentId;
|
|
@@ -709,9 +819,17 @@ var TracingSpan = class _TracingSpan {
|
|
|
709
819
|
const resource2 = this._traceProcessor.resources.get(this.resourceId);
|
|
710
820
|
return resource2 ? `${resource2.sanitizedClassName}#${resource2.data.instanceId}.${this.methodName}` : this.methodName;
|
|
711
821
|
}
|
|
822
|
+
/** Sanitized class name of the owning resource, if available. */
|
|
823
|
+
get sanitizedClassName() {
|
|
824
|
+
const resource2 = this.resourceId != null ? this._traceProcessor.resources.get(this.resourceId) : void 0;
|
|
825
|
+
return resource2?.sanitizedClassName;
|
|
826
|
+
}
|
|
712
827
|
get ctx() {
|
|
713
828
|
return this._ctx;
|
|
714
829
|
}
|
|
830
|
+
get showInRemoteTracing() {
|
|
831
|
+
return this._showInRemoteTracing;
|
|
832
|
+
}
|
|
715
833
|
markSuccess() {
|
|
716
834
|
this.endTs = performance.now();
|
|
717
835
|
this._traceProcessor._flushSpan(this);
|
|
@@ -818,13 +936,13 @@ var areEqualShallow = (a, b) => {
|
|
|
818
936
|
return true;
|
|
819
937
|
};
|
|
820
938
|
var sanitizeClassName = (className) => {
|
|
939
|
+
let name = className.replace(/^_+/, "");
|
|
821
940
|
const SANITIZE_REGEX = /[^_](\d+)$/;
|
|
822
|
-
const m =
|
|
823
|
-
if (
|
|
824
|
-
|
|
825
|
-
} else {
|
|
826
|
-
return className.slice(0, -m[1].length);
|
|
941
|
+
const m = name.match(SANITIZE_REGEX);
|
|
942
|
+
if (m) {
|
|
943
|
+
name = name.slice(0, -m[1].length);
|
|
827
944
|
}
|
|
945
|
+
return name;
|
|
828
946
|
};
|
|
829
947
|
var isSetLike = (value) => value instanceof Set || typeof value === "object" && value !== null && Object.getPrototypeOf(value).constructor.name === "ComplexSet";
|
|
830
948
|
var isMapLike = (value) => value instanceof Map || typeof value === "object" && value !== null && Object.getPrototypeOf(value).constructor.name === "ComplexMap";
|
|
@@ -854,30 +972,33 @@ var info = (opts = {}) => (target, propertyKey, descriptor) => {
|
|
|
854
972
|
var mark = (name) => {
|
|
855
973
|
performance.mark(name);
|
|
856
974
|
};
|
|
857
|
-
var span = ({ showInBrowserTimeline = false, op, attributes } = {}) => (target, propertyKey, descriptor) => {
|
|
975
|
+
var span = ({ showInBrowserTimeline = false, showInRemoteTracing = true, op, attributes } = {}) => (target, propertyKey, descriptor) => {
|
|
858
976
|
const method = descriptor.value;
|
|
859
977
|
descriptor.value = async function(...args) {
|
|
860
|
-
const
|
|
978
|
+
const explicitCtx = args[0] instanceof Context3 ? args[0] : null;
|
|
861
979
|
const span2 = TRACE_PROCESSOR.traceSpan({
|
|
862
|
-
parentCtx,
|
|
980
|
+
parentCtx: explicitCtx,
|
|
863
981
|
methodName: propertyKey,
|
|
864
982
|
instance: this,
|
|
865
983
|
showInBrowserTimeline,
|
|
984
|
+
showInRemoteTracing,
|
|
866
985
|
op,
|
|
867
986
|
attributes
|
|
868
987
|
});
|
|
869
|
-
const callArgs =
|
|
988
|
+
const callArgs = explicitCtx ? [
|
|
870
989
|
span2.ctx,
|
|
871
990
|
...args.slice(1)
|
|
872
991
|
] : args;
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
992
|
+
return TRACE_PROCESSOR.remoteTracing.wrapExecution(span2, async () => {
|
|
993
|
+
try {
|
|
994
|
+
return await method.apply(this, callArgs);
|
|
995
|
+
} catch (err) {
|
|
996
|
+
span2.markError(err);
|
|
997
|
+
throw err;
|
|
998
|
+
} finally {
|
|
999
|
+
span2.markSuccess();
|
|
1000
|
+
}
|
|
1001
|
+
});
|
|
881
1002
|
};
|
|
882
1003
|
};
|
|
883
1004
|
var spans = /* @__PURE__ */ new Map();
|