@dxos/tracing 0.8.4-main.fffef41 → 0.8.4-staging.ac66bdf99f
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 +328 -339
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +328 -339
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/api.d.ts +36 -17
- package/dist/types/src/api.d.ts.map +1 -1
- package/dist/types/src/buffering-backend.d.ts +24 -0
- package/dist/types/src/buffering-backend.d.ts.map +1 -0
- package/dist/types/src/diagnostic.d.ts +2 -2
- package/dist/types/src/diagnostic.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/remote/index.d.ts +0 -1
- package/dist/types/src/remote/index.d.ts.map +1 -1
- package/dist/types/src/symbols.d.ts +0 -1
- package/dist/types/src/symbols.d.ts.map +1 -1
- package/dist/types/src/trace-processor.d.ts +16 -52
- package/dist/types/src/trace-processor.d.ts.map +1 -1
- package/dist/types/src/tracing-types.d.ts +67 -0
- package/dist/types/src/tracing-types.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -9
- package/src/api.ts +237 -35
- package/src/buffering-backend.ts +112 -0
- package/src/diagnostic.ts +2 -2
- package/src/index.ts +1 -2
- package/src/remote/index.ts +0 -1
- package/src/symbols.ts +0 -2
- package/src/trace-processor.ts +58 -258
- package/src/tracing-types.ts +77 -0
- package/src/tracing.test.ts +513 -4
- package/dist/types/src/remote/tracing.d.ts +0 -23
- package/dist/types/src/remote/tracing.d.ts.map +0 -1
- package/dist/types/src/trace-sender.d.ts +0 -9
- package/dist/types/src/trace-sender.d.ts.map +0 -1
- package/src/remote/tracing.ts +0 -53
- package/src/trace-sender.ts +0 -88
|
@@ -1,21 +1,105 @@
|
|
|
1
1
|
// src/api.ts
|
|
2
|
-
import { Context as Context2 } from "@dxos/context";
|
|
2
|
+
import { Context as Context2, LifecycleState, Resource, TRACE_SPAN_ATTRIBUTE } from "@dxos/context";
|
|
3
3
|
|
|
4
4
|
// src/symbols.ts
|
|
5
|
-
var symbolTracingContext = Symbol("dxos.tracing.context");
|
|
5
|
+
var symbolTracingContext = /* @__PURE__ */ Symbol("dxos.tracing.context");
|
|
6
6
|
var getTracingContext = (target) => {
|
|
7
7
|
return target[symbolTracingContext] ??= {
|
|
8
8
|
infoProperties: {},
|
|
9
9
|
metricsProperties: {}
|
|
10
10
|
};
|
|
11
11
|
};
|
|
12
|
-
var TRACE_SPAN_ATTRIBUTE = "dxos.trace-span";
|
|
13
12
|
|
|
14
13
|
// src/trace-processor.ts
|
|
15
|
-
import {
|
|
16
|
-
import { LogLevel, getContextFromEntry, log } from "@dxos/log";
|
|
14
|
+
import { LogLevel, log } from "@dxos/log";
|
|
17
15
|
import { getPrototypeSpecificInstanceId } from "@dxos/util";
|
|
18
16
|
|
|
17
|
+
// src/buffering-backend.ts
|
|
18
|
+
var BUFFERED_PREFIX = "buffered-";
|
|
19
|
+
var BufferedSpan = class {
|
|
20
|
+
options;
|
|
21
|
+
spanContext;
|
|
22
|
+
startTime;
|
|
23
|
+
delegate;
|
|
24
|
+
#ended = false;
|
|
25
|
+
#endTime;
|
|
26
|
+
#error;
|
|
27
|
+
#hasError = false;
|
|
28
|
+
constructor(options, id) {
|
|
29
|
+
this.options = options;
|
|
30
|
+
this.spanContext = {
|
|
31
|
+
traceparent: `${BUFFERED_PREFIX}${id}`
|
|
32
|
+
};
|
|
33
|
+
this.startTime = Date.now();
|
|
34
|
+
}
|
|
35
|
+
end(endTime) {
|
|
36
|
+
if (this.delegate) {
|
|
37
|
+
this.delegate.end(endTime);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
this.#endTime = endTime ?? Date.now();
|
|
41
|
+
this.#ended = true;
|
|
42
|
+
}
|
|
43
|
+
setError(err) {
|
|
44
|
+
if (this.delegate) {
|
|
45
|
+
this.delegate.setError?.(err);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
this.#error = err;
|
|
49
|
+
this.#hasError = true;
|
|
50
|
+
}
|
|
51
|
+
replay(real) {
|
|
52
|
+
if (this.#hasError) {
|
|
53
|
+
real.setError?.(this.#error);
|
|
54
|
+
}
|
|
55
|
+
if (this.#ended) {
|
|
56
|
+
real.end(this.#endTime);
|
|
57
|
+
} else {
|
|
58
|
+
this.delegate = real;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
var BufferingTracingBackend = class {
|
|
63
|
+
#pending = [];
|
|
64
|
+
#counter = 0;
|
|
65
|
+
startSpan(options) {
|
|
66
|
+
const span2 = new BufferedSpan(options, ++this.#counter);
|
|
67
|
+
this.#pending.push(span2);
|
|
68
|
+
return span2;
|
|
69
|
+
}
|
|
70
|
+
/** Discard all buffered spans without replaying them. */
|
|
71
|
+
clear() {
|
|
72
|
+
this.#pending.length = 0;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Replay all buffered spans into {@link backend}.
|
|
76
|
+
*
|
|
77
|
+
* @returns Map from synthetic buffered traceparent to real {@link TraceContextData},
|
|
78
|
+
* used by the post-drain translating wrapper to resolve stale buffered IDs
|
|
79
|
+
* still present on in-flight {@link Context} objects.
|
|
80
|
+
*/
|
|
81
|
+
drain(backend) {
|
|
82
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
83
|
+
for (const buffered of this.#pending) {
|
|
84
|
+
let parentContext = buffered.options.parentContext;
|
|
85
|
+
if (parentContext && parentContext.traceparent.startsWith(BUFFERED_PREFIX)) {
|
|
86
|
+
parentContext = idMap.get(parentContext.traceparent) ?? parentContext;
|
|
87
|
+
}
|
|
88
|
+
const real = backend.startSpan({
|
|
89
|
+
...buffered.options,
|
|
90
|
+
parentContext,
|
|
91
|
+
startTime: buffered.startTime
|
|
92
|
+
});
|
|
93
|
+
if (real.spanContext) {
|
|
94
|
+
idMap.set(buffered.spanContext.traceparent, real.spanContext);
|
|
95
|
+
}
|
|
96
|
+
buffered.replay(real);
|
|
97
|
+
}
|
|
98
|
+
this.#pending.length = 0;
|
|
99
|
+
return idMap;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
19
103
|
// src/diagnostic.ts
|
|
20
104
|
import { asyncTimeout } from "@dxos/async";
|
|
21
105
|
import { invariant } from "@dxos/invariant";
|
|
@@ -282,124 +366,6 @@ var RemoteMetrics = class {
|
|
|
282
366
|
}
|
|
283
367
|
};
|
|
284
368
|
|
|
285
|
-
// src/remote/tracing.ts
|
|
286
|
-
var RemoteTracing = class {
|
|
287
|
-
_tracing;
|
|
288
|
-
_spanMap = /* @__PURE__ */ new Map();
|
|
289
|
-
registerProcessor(processor) {
|
|
290
|
-
this._tracing = processor;
|
|
291
|
-
}
|
|
292
|
-
flushSpan(span2) {
|
|
293
|
-
if (!this._tracing) {
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
if (!span2.endTs) {
|
|
297
|
-
const remoteSpan = this._tracing.startSpan({
|
|
298
|
-
name: span2.methodName,
|
|
299
|
-
op: span2.op ?? "function",
|
|
300
|
-
attributes: span2.attributes
|
|
301
|
-
});
|
|
302
|
-
this._spanMap.set(span2, remoteSpan);
|
|
303
|
-
} else {
|
|
304
|
-
const remoteSpan = this._spanMap.get(span2);
|
|
305
|
-
if (remoteSpan) {
|
|
306
|
-
remoteSpan.end();
|
|
307
|
-
this._spanMap.delete(span2);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
// src/trace-sender.ts
|
|
314
|
-
import { Stream } from "@dxos/codec-protobuf/stream";
|
|
315
|
-
var TraceSender = class {
|
|
316
|
-
_traceProcessor;
|
|
317
|
-
constructor(_traceProcessor) {
|
|
318
|
-
this._traceProcessor = _traceProcessor;
|
|
319
|
-
}
|
|
320
|
-
streamTrace(request) {
|
|
321
|
-
return new Stream(({ ctx, next }) => {
|
|
322
|
-
const flushEvents = (resources, spans2, logs) => {
|
|
323
|
-
const event = {
|
|
324
|
-
resourceAdded: [],
|
|
325
|
-
resourceRemoved: [],
|
|
326
|
-
spanAdded: [],
|
|
327
|
-
logAdded: []
|
|
328
|
-
};
|
|
329
|
-
if (resources) {
|
|
330
|
-
for (const id of resources) {
|
|
331
|
-
const entry = this._traceProcessor.resources.get(id);
|
|
332
|
-
if (entry) {
|
|
333
|
-
event.resourceAdded.push({
|
|
334
|
-
resource: entry.data
|
|
335
|
-
});
|
|
336
|
-
} else {
|
|
337
|
-
event.resourceRemoved.push({
|
|
338
|
-
id
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
} else {
|
|
343
|
-
for (const entry of this._traceProcessor.resources.values()) {
|
|
344
|
-
event.resourceAdded.push({
|
|
345
|
-
resource: entry.data
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
if (spans2) {
|
|
350
|
-
for (const id of spans2) {
|
|
351
|
-
const span2 = this._traceProcessor.spans.get(id);
|
|
352
|
-
if (span2) {
|
|
353
|
-
event.spanAdded.push({
|
|
354
|
-
span: span2
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
} else {
|
|
359
|
-
for (const span2 of this._traceProcessor.spans.values()) {
|
|
360
|
-
event.spanAdded.push({
|
|
361
|
-
span: span2
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
if (logs) {
|
|
366
|
-
for (const log2 of logs) {
|
|
367
|
-
event.logAdded.push({
|
|
368
|
-
log: log2
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
} else {
|
|
372
|
-
for (const log2 of this._traceProcessor.logs) {
|
|
373
|
-
event.logAdded.push({
|
|
374
|
-
log: log2
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
if (event.resourceAdded.length > 0 || event.resourceRemoved.length > 0 || event.spanAdded.length > 0) {
|
|
379
|
-
next(event);
|
|
380
|
-
}
|
|
381
|
-
};
|
|
382
|
-
const flush = () => {
|
|
383
|
-
flushEvents(subscription.dirtyResources, subscription.dirtySpans, subscription.newLogs);
|
|
384
|
-
subscription.dirtyResources.clear();
|
|
385
|
-
subscription.dirtySpans.clear();
|
|
386
|
-
subscription.newLogs.length = 0;
|
|
387
|
-
};
|
|
388
|
-
const subscription = {
|
|
389
|
-
flush,
|
|
390
|
-
dirtyResources: /* @__PURE__ */ new Set(),
|
|
391
|
-
dirtySpans: /* @__PURE__ */ new Set(),
|
|
392
|
-
newLogs: []
|
|
393
|
-
};
|
|
394
|
-
this._traceProcessor.subscriptions.add(subscription);
|
|
395
|
-
ctx.onDispose(() => {
|
|
396
|
-
this._traceProcessor.subscriptions.delete(subscription);
|
|
397
|
-
});
|
|
398
|
-
flushEvents(null, null, null);
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
};
|
|
402
|
-
|
|
403
369
|
// src/weak-ref.ts
|
|
404
370
|
var WeakRefMock = class {
|
|
405
371
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
|
@@ -434,35 +400,61 @@ var ResourceEntry = class {
|
|
|
434
400
|
}
|
|
435
401
|
};
|
|
436
402
|
var MAX_RESOURCE_RECORDS = 2e3;
|
|
437
|
-
var MAX_SPAN_RECORDS = 1e3;
|
|
438
403
|
var MAX_LOG_RECORDS = 1e3;
|
|
439
|
-
var REFRESH_INTERVAL = 1e3;
|
|
440
404
|
var MAX_INFO_OBJECT_DEPTH = 8;
|
|
441
|
-
var IS_CLOUDFLARE_WORKERS = !!globalThis?.navigator?.userAgent?.includes("Cloudflare-Workers");
|
|
442
405
|
var TraceProcessor = class {
|
|
443
406
|
diagnostics = new DiagnosticsManager();
|
|
444
407
|
diagnosticsChannel = new DiagnosticsChannel();
|
|
445
408
|
remoteMetrics = new RemoteMetrics();
|
|
446
|
-
|
|
447
|
-
|
|
409
|
+
#bufferingBackend = new BufferingTracingBackend();
|
|
410
|
+
#activeBackend = this.#bufferingBackend;
|
|
411
|
+
/**
|
|
412
|
+
* Tracing backend. Initially a buffering backend that records spans;
|
|
413
|
+
* once the observability package sets a real backend, the buffer is drained
|
|
414
|
+
* and a thin translating wrapper is installed that resolves stale buffered
|
|
415
|
+
* parent IDs still held by in-flight {@link Context} objects.
|
|
416
|
+
*
|
|
417
|
+
* The wrapper only allocates when a `buffered-*` parent is actually encountered;
|
|
418
|
+
* the common path is a single `startsWith` check and direct passthrough.
|
|
419
|
+
*/
|
|
420
|
+
get tracingBackend() {
|
|
421
|
+
return this.#activeBackend;
|
|
422
|
+
}
|
|
423
|
+
set tracingBackend(backend) {
|
|
424
|
+
if (!backend || backend === this.#bufferingBackend) {
|
|
425
|
+
this.#bufferingBackend.clear();
|
|
426
|
+
this.#activeBackend = this.#bufferingBackend;
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
const idMap = this.#bufferingBackend.drain(backend);
|
|
430
|
+
this.#activeBackend = {
|
|
431
|
+
startSpan: (options) => {
|
|
432
|
+
const parent = options.parentContext;
|
|
433
|
+
if (parent?.traceparent.startsWith(BUFFERED_PREFIX)) {
|
|
434
|
+
const translated = idMap.get(parent.traceparent);
|
|
435
|
+
if (translated) {
|
|
436
|
+
return backend.startSpan({
|
|
437
|
+
...options,
|
|
438
|
+
parentContext: translated
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return backend.startSpan(options);
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
}
|
|
448
446
|
resources = /* @__PURE__ */ new Map();
|
|
449
447
|
resourceInstanceIndex = /* @__PURE__ */ new WeakMap();
|
|
450
448
|
resourceIdList = [];
|
|
451
|
-
spans = /* @__PURE__ */ new Map();
|
|
452
|
-
spanIdList = [];
|
|
453
449
|
logs = [];
|
|
454
450
|
_instanceTag = null;
|
|
455
451
|
constructor() {
|
|
456
452
|
log.addProcessor(this._logProcessor.bind(this), void 0, {
|
|
457
453
|
F: __dxlog_file3,
|
|
458
|
-
L:
|
|
454
|
+
L: 108,
|
|
459
455
|
S: this,
|
|
460
456
|
C: (f, a) => f(...a)
|
|
461
457
|
});
|
|
462
|
-
if (!IS_CLOUDFLARE_WORKERS) {
|
|
463
|
-
const refreshInterval = setInterval(this.refresh.bind(this), REFRESH_INTERVAL);
|
|
464
|
-
unrefTimeout(refreshInterval);
|
|
465
|
-
}
|
|
466
458
|
if (DiagnosticsChannel.supported) {
|
|
467
459
|
this.diagnosticsChannel.serve(this.diagnostics);
|
|
468
460
|
}
|
|
@@ -472,10 +464,7 @@ var TraceProcessor = class {
|
|
|
472
464
|
this._instanceTag = tag;
|
|
473
465
|
this.diagnostics.setInstanceTag(tag);
|
|
474
466
|
}
|
|
475
|
-
/**
|
|
476
|
-
* @internal
|
|
477
|
-
*/
|
|
478
|
-
// TODO(burdon): Comment.
|
|
467
|
+
/** @internal */
|
|
479
468
|
createTraceResource(params) {
|
|
480
469
|
const id = this.resources.size;
|
|
481
470
|
const tracingContext = getTracingContext(Object.getPrototypeOf(params.instance));
|
|
@@ -496,24 +485,10 @@ var TraceProcessor = class {
|
|
|
496
485
|
if (this.resourceIdList.length > MAX_RESOURCE_RECORDS) {
|
|
497
486
|
this._clearResources();
|
|
498
487
|
}
|
|
499
|
-
this._markResourceDirty(id);
|
|
500
|
-
}
|
|
501
|
-
createTraceSender() {
|
|
502
|
-
return new TraceSender(this);
|
|
503
|
-
}
|
|
504
|
-
traceSpan(params) {
|
|
505
|
-
const span2 = new TracingSpan(this, params);
|
|
506
|
-
this._flushSpan(span2);
|
|
507
|
-
return span2;
|
|
508
488
|
}
|
|
509
489
|
// TODO(burdon): Not implemented.
|
|
510
490
|
addLink(parent, child, opts) {
|
|
511
491
|
}
|
|
512
|
-
//
|
|
513
|
-
// Getters
|
|
514
|
-
//
|
|
515
|
-
// TODO(burdon): Define type.
|
|
516
|
-
// TODO(burdon): Reconcile with system service.
|
|
517
492
|
getDiagnostics() {
|
|
518
493
|
this.refresh();
|
|
519
494
|
return {
|
|
@@ -521,7 +496,6 @@ var TraceProcessor = class {
|
|
|
521
496
|
`${entry.sanitizedClassName}#${entry.data.instanceId}`,
|
|
522
497
|
entry.data
|
|
523
498
|
])),
|
|
524
|
-
spans: Array.from(this.spans.values()),
|
|
525
499
|
logs: this.logs.filter((log2) => log2.level >= LogLevel.INFO)
|
|
526
500
|
};
|
|
527
501
|
}
|
|
@@ -576,43 +550,8 @@ var TraceProcessor = class {
|
|
|
576
550
|
for (const key of Object.keys(tracingContext.metricsProperties)) {
|
|
577
551
|
instance[key]._tick?.(time);
|
|
578
552
|
}
|
|
579
|
-
let _changed = false;
|
|
580
|
-
const oldInfo = resource2.data.info;
|
|
581
553
|
resource2.data.info = this.getResourceInfo(instance);
|
|
582
|
-
_changed ||= !areEqualShallow(oldInfo, resource2.data.info);
|
|
583
|
-
const oldMetrics = resource2.data.metrics;
|
|
584
554
|
resource2.data.metrics = this.getResourceMetrics(instance);
|
|
585
|
-
_changed ||= !areEqualShallow(oldMetrics, resource2.data.metrics);
|
|
586
|
-
this._markResourceDirty(resource2.data.id);
|
|
587
|
-
}
|
|
588
|
-
for (const subscription of this.subscriptions) {
|
|
589
|
-
subscription.flush();
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
//
|
|
593
|
-
// Implementation
|
|
594
|
-
//
|
|
595
|
-
/**
|
|
596
|
-
* @internal
|
|
597
|
-
*/
|
|
598
|
-
_flushSpan(runtimeSpan) {
|
|
599
|
-
const span2 = runtimeSpan.serialize();
|
|
600
|
-
this.spans.set(span2.id, span2);
|
|
601
|
-
this.spanIdList.push(span2.id);
|
|
602
|
-
if (this.spanIdList.length > MAX_SPAN_RECORDS) {
|
|
603
|
-
this._clearSpans();
|
|
604
|
-
}
|
|
605
|
-
this._markSpanDirty(span2.id);
|
|
606
|
-
this.remoteTracing.flushSpan(runtimeSpan);
|
|
607
|
-
}
|
|
608
|
-
_markResourceDirty(id) {
|
|
609
|
-
for (const subscription of this.subscriptions) {
|
|
610
|
-
subscription.dirtyResources.add(id);
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
_markSpanDirty(id) {
|
|
614
|
-
for (const subscription of this.subscriptions) {
|
|
615
|
-
subscription.dirtySpans.add(id);
|
|
616
555
|
}
|
|
617
556
|
}
|
|
618
557
|
_clearResources() {
|
|
@@ -621,20 +560,11 @@ var TraceProcessor = class {
|
|
|
621
560
|
this.resources.delete(id);
|
|
622
561
|
}
|
|
623
562
|
}
|
|
624
|
-
_clearSpans() {
|
|
625
|
-
while (this.spanIdList.length > MAX_SPAN_RECORDS) {
|
|
626
|
-
const id = this.spanIdList.shift();
|
|
627
|
-
this.spans.delete(id);
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
563
|
_pushLog(log2) {
|
|
631
564
|
this.logs.push(log2);
|
|
632
565
|
if (this.logs.length > MAX_LOG_RECORDS) {
|
|
633
566
|
this.logs.shift();
|
|
634
567
|
}
|
|
635
|
-
for (const subscription of this.subscriptions) {
|
|
636
|
-
subscription.newLogs.push(log2);
|
|
637
|
-
}
|
|
638
568
|
}
|
|
639
569
|
_logProcessor = (config, entry) => {
|
|
640
570
|
switch (entry.level) {
|
|
@@ -646,18 +576,21 @@ var TraceProcessor = class {
|
|
|
646
576
|
if (!resource2) {
|
|
647
577
|
return;
|
|
648
578
|
}
|
|
649
|
-
const context =
|
|
650
|
-
|
|
651
|
-
|
|
579
|
+
const context = {
|
|
580
|
+
...entry.computedContext
|
|
581
|
+
};
|
|
582
|
+
if (entry.computedError !== void 0) {
|
|
583
|
+
context.error = entry.computedError;
|
|
652
584
|
}
|
|
585
|
+
const { filename, line } = entry.computedMeta;
|
|
653
586
|
const entryToPush = {
|
|
654
587
|
level: entry.level,
|
|
655
|
-
message: entry.message ??
|
|
588
|
+
message: entry.message ?? entry.computedError ?? "",
|
|
656
589
|
context,
|
|
657
|
-
timestamp:
|
|
590
|
+
timestamp: new Date(entry.timestamp),
|
|
658
591
|
meta: {
|
|
659
|
-
file:
|
|
660
|
-
line:
|
|
592
|
+
file: filename ?? "",
|
|
593
|
+
line: line ?? 0,
|
|
661
594
|
resourceId: resource2.data.id
|
|
662
595
|
}
|
|
663
596
|
};
|
|
@@ -668,94 +601,6 @@ var TraceProcessor = class {
|
|
|
668
601
|
}
|
|
669
602
|
};
|
|
670
603
|
};
|
|
671
|
-
var TracingSpan = class _TracingSpan {
|
|
672
|
-
_traceProcessor;
|
|
673
|
-
static nextId = 0;
|
|
674
|
-
id;
|
|
675
|
-
parentId = null;
|
|
676
|
-
methodName;
|
|
677
|
-
resourceId = null;
|
|
678
|
-
op;
|
|
679
|
-
attributes;
|
|
680
|
-
startTs;
|
|
681
|
-
endTs = null;
|
|
682
|
-
error = null;
|
|
683
|
-
_showInBrowserTimeline;
|
|
684
|
-
_ctx = null;
|
|
685
|
-
constructor(_traceProcessor, params) {
|
|
686
|
-
this._traceProcessor = _traceProcessor;
|
|
687
|
-
this.id = _TracingSpan.nextId++;
|
|
688
|
-
this.methodName = params.methodName;
|
|
689
|
-
this.resourceId = _traceProcessor.getResourceId(params.instance);
|
|
690
|
-
this.startTs = performance.now();
|
|
691
|
-
this._showInBrowserTimeline = params.showInBrowserTimeline;
|
|
692
|
-
this.op = params.op;
|
|
693
|
-
this.attributes = params.attributes ?? {};
|
|
694
|
-
if (params.parentCtx) {
|
|
695
|
-
this._ctx = params.parentCtx.derive({
|
|
696
|
-
attributes: {
|
|
697
|
-
[TRACE_SPAN_ATTRIBUTE]: this.id
|
|
698
|
-
}
|
|
699
|
-
});
|
|
700
|
-
const parentId = params.parentCtx.getAttribute(TRACE_SPAN_ATTRIBUTE);
|
|
701
|
-
if (typeof parentId === "number") {
|
|
702
|
-
this.parentId = parentId;
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
get name() {
|
|
707
|
-
const resource2 = this._traceProcessor.resources.get(this.resourceId);
|
|
708
|
-
return resource2 ? `${resource2.sanitizedClassName}#${resource2.data.instanceId}.${this.methodName}` : this.methodName;
|
|
709
|
-
}
|
|
710
|
-
get ctx() {
|
|
711
|
-
return this._ctx;
|
|
712
|
-
}
|
|
713
|
-
markSuccess() {
|
|
714
|
-
this.endTs = performance.now();
|
|
715
|
-
this._traceProcessor._flushSpan(this);
|
|
716
|
-
if (this._showInBrowserTimeline) {
|
|
717
|
-
this._markInBrowserTimeline();
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
markError(err) {
|
|
721
|
-
this.endTs = performance.now();
|
|
722
|
-
this.error = serializeError(err);
|
|
723
|
-
this._traceProcessor._flushSpan(this);
|
|
724
|
-
if (this._showInBrowserTimeline) {
|
|
725
|
-
this._markInBrowserTimeline();
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
serialize() {
|
|
729
|
-
return {
|
|
730
|
-
id: this.id,
|
|
731
|
-
resourceId: this.resourceId ?? void 0,
|
|
732
|
-
methodName: this.methodName,
|
|
733
|
-
parentId: this.parentId ?? void 0,
|
|
734
|
-
startTs: this.startTs.toFixed(3),
|
|
735
|
-
endTs: this.endTs?.toFixed(3) ?? void 0,
|
|
736
|
-
error: this.error ?? void 0
|
|
737
|
-
};
|
|
738
|
-
}
|
|
739
|
-
_markInBrowserTimeline() {
|
|
740
|
-
if (typeof globalThis?.performance?.measure === "function") {
|
|
741
|
-
performance.measure(this.name, {
|
|
742
|
-
start: this.startTs,
|
|
743
|
-
end: this.endTs
|
|
744
|
-
});
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
};
|
|
748
|
-
var serializeError = (err) => {
|
|
749
|
-
if (err instanceof Error) {
|
|
750
|
-
return {
|
|
751
|
-
name: err.name,
|
|
752
|
-
message: err.message
|
|
753
|
-
};
|
|
754
|
-
}
|
|
755
|
-
return {
|
|
756
|
-
message: String(err)
|
|
757
|
-
};
|
|
758
|
-
};
|
|
759
604
|
var TRACE_PROCESSOR = globalThis.TRACE_PROCESSOR ??= new TraceProcessor();
|
|
760
605
|
var sanitizeValue = (value, depth, traceProcessor) => {
|
|
761
606
|
switch (typeof value) {
|
|
@@ -802,33 +647,46 @@ var sanitizeValue = (value, depth, traceProcessor) => {
|
|
|
802
647
|
return value.toString();
|
|
803
648
|
}
|
|
804
649
|
};
|
|
805
|
-
var areEqualShallow = (a, b) => {
|
|
806
|
-
for (const key in a) {
|
|
807
|
-
if (!(key in b) || a[key] !== b[key]) {
|
|
808
|
-
return false;
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
for (const key in b) {
|
|
812
|
-
if (!(key in a) || a[key] !== b[key]) {
|
|
813
|
-
return false;
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
return true;
|
|
817
|
-
};
|
|
818
650
|
var sanitizeClassName = (className) => {
|
|
651
|
+
let name = className.replace(/^_+/, "");
|
|
819
652
|
const SANITIZE_REGEX = /[^_](\d+)$/;
|
|
820
|
-
const m =
|
|
821
|
-
if (
|
|
822
|
-
|
|
823
|
-
} else {
|
|
824
|
-
return className.slice(0, -m[1].length);
|
|
653
|
+
const m = name.match(SANITIZE_REGEX);
|
|
654
|
+
if (m) {
|
|
655
|
+
name = name.slice(0, -m[1].length);
|
|
825
656
|
}
|
|
657
|
+
return name;
|
|
826
658
|
};
|
|
827
659
|
var isSetLike = (value) => value instanceof Set || typeof value === "object" && value !== null && Object.getPrototypeOf(value).constructor.name === "ComplexSet";
|
|
828
660
|
var isMapLike = (value) => value instanceof Map || typeof value === "object" && value !== null && Object.getPrototypeOf(value).constructor.name === "ComplexMap";
|
|
829
661
|
|
|
830
662
|
// src/api.ts
|
|
663
|
+
var __dxlog_file4 = "/__w/dxos/dxos/packages/common/tracing/src/api.ts";
|
|
664
|
+
var LIFECYCLE_SPAN = /* @__PURE__ */ Symbol("dxos.tracing.lifecycle-span");
|
|
665
|
+
var TRACE_ALL_KEY = "dxos.debug.traceAll";
|
|
666
|
+
var collectSpanAttributes = (instance, spanAttributes) => {
|
|
667
|
+
const proto = Object.getPrototypeOf(instance);
|
|
668
|
+
if (!proto) {
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
const tracingContext = getTracingContext(proto);
|
|
672
|
+
for (const [key, { options }] of Object.entries(tracingContext.infoProperties)) {
|
|
673
|
+
if (!options.spanAttribute) {
|
|
674
|
+
continue;
|
|
675
|
+
}
|
|
676
|
+
try {
|
|
677
|
+
const value = typeof instance[key] === "function" ? instance[key]() : instance[key];
|
|
678
|
+
if (value != null) {
|
|
679
|
+
const resolved = options.enum ? options.enum[value] : String(value);
|
|
680
|
+
spanAttributes[`ctx.${key}`] = resolved;
|
|
681
|
+
}
|
|
682
|
+
} catch {
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
};
|
|
831
686
|
var resource = (options) => (constructor) => {
|
|
687
|
+
if (options?.lifecycle && !(constructor.prototype instanceof Resource)) {
|
|
688
|
+
throw new Error(`@trace.resource({ lifecycle: true }) requires ${constructor.name} to extend Resource`);
|
|
689
|
+
}
|
|
832
690
|
const klass = /* @__PURE__ */ (() => class extends constructor {
|
|
833
691
|
constructor(...rest) {
|
|
834
692
|
super(...rest);
|
|
@@ -839,6 +697,68 @@ var resource = (options) => (constructor) => {
|
|
|
839
697
|
});
|
|
840
698
|
}
|
|
841
699
|
})();
|
|
700
|
+
if (options?.lifecycle) {
|
|
701
|
+
const sanitizedName = sanitizeClassName(constructor.name);
|
|
702
|
+
const proto = klass.prototype;
|
|
703
|
+
const originalOpen = proto.open;
|
|
704
|
+
const originalClose = proto.close;
|
|
705
|
+
proto.open = async function(ctx) {
|
|
706
|
+
const self = this;
|
|
707
|
+
if (self._lifecycleState !== LifecycleState.CLOSED) {
|
|
708
|
+
return originalOpen.call(this, ctx);
|
|
709
|
+
}
|
|
710
|
+
const parentSpanContext = ctx?.getAttribute(TRACE_SPAN_ATTRIBUTE);
|
|
711
|
+
const resourceEntry = TRACE_PROCESSOR.resourceInstanceIndex.get(this);
|
|
712
|
+
const spanAttributes = {};
|
|
713
|
+
if (resourceEntry) {
|
|
714
|
+
spanAttributes.entryPoint = resourceEntry.sanitizedClassName;
|
|
715
|
+
}
|
|
716
|
+
const remoteSpan = TRACE_PROCESSOR.tracingBackend?.startSpan({
|
|
717
|
+
name: `${sanitizedName}.lifecycle`,
|
|
718
|
+
op: "lifecycle",
|
|
719
|
+
attributes: spanAttributes,
|
|
720
|
+
parentContext: parentSpanContext
|
|
721
|
+
});
|
|
722
|
+
self[LIFECYCLE_SPAN] = remoteSpan;
|
|
723
|
+
let openCtx = ctx;
|
|
724
|
+
if (remoteSpan?.spanContext != null) {
|
|
725
|
+
const traceAttrs = {
|
|
726
|
+
[TRACE_SPAN_ATTRIBUTE]: remoteSpan.spanContext
|
|
727
|
+
};
|
|
728
|
+
openCtx = ctx ? ctx.derive({
|
|
729
|
+
attributes: traceAttrs
|
|
730
|
+
}) : new Context2({
|
|
731
|
+
attributes: traceAttrs
|
|
732
|
+
}, {
|
|
733
|
+
F: __dxlog_file4,
|
|
734
|
+
L: 104
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
try {
|
|
738
|
+
return await originalOpen.call(this, openCtx);
|
|
739
|
+
} catch (err) {
|
|
740
|
+
remoteSpan?.setError?.(err);
|
|
741
|
+
remoteSpan?.end();
|
|
742
|
+
self[LIFECYCLE_SPAN] = void 0;
|
|
743
|
+
throw err;
|
|
744
|
+
}
|
|
745
|
+
};
|
|
746
|
+
proto.close = async function(ctx) {
|
|
747
|
+
const self = this;
|
|
748
|
+
const remoteSpan = self[LIFECYCLE_SPAN];
|
|
749
|
+
try {
|
|
750
|
+
return await originalClose.call(this, ctx);
|
|
751
|
+
} catch (err) {
|
|
752
|
+
remoteSpan?.setError?.(err);
|
|
753
|
+
throw err;
|
|
754
|
+
} finally {
|
|
755
|
+
if (remoteSpan) {
|
|
756
|
+
remoteSpan.end();
|
|
757
|
+
self[LIFECYCLE_SPAN] = void 0;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
}
|
|
842
762
|
Object.defineProperty(klass, "name", {
|
|
843
763
|
value: constructor.name
|
|
844
764
|
});
|
|
@@ -852,45 +772,117 @@ var info = (opts = {}) => (target, propertyKey, descriptor) => {
|
|
|
852
772
|
var mark = (name) => {
|
|
853
773
|
performance.mark(name);
|
|
854
774
|
};
|
|
855
|
-
var span = ({ showInBrowserTimeline = false, op, attributes } = {}) => (target, propertyKey, descriptor) => {
|
|
775
|
+
var span = ({ showInBrowserTimeline = false, showInRemoteTracing = true, op, attributes } = {}) => (target, propertyKey, descriptor) => {
|
|
856
776
|
const method = descriptor.value;
|
|
857
777
|
descriptor.value = async function(...args) {
|
|
858
778
|
const parentCtx = args[0] instanceof Context2 ? args[0] : null;
|
|
859
|
-
const
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
779
|
+
const startTs = performance.now();
|
|
780
|
+
const parentSpanContext = parentCtx?.getAttribute(TRACE_SPAN_ATTRIBUTE);
|
|
781
|
+
const resourceEntry = TRACE_PROCESSOR.resourceInstanceIndex.get(this);
|
|
782
|
+
const className = resourceEntry?.sanitizedClassName ?? sanitizeClassName(target.constructor?.name ?? "unknown");
|
|
783
|
+
const spanName = `${className}.${propertyKey}`;
|
|
784
|
+
const spanAttributes = {};
|
|
785
|
+
if (resourceEntry) {
|
|
786
|
+
spanAttributes.entryPoint = resourceEntry.sanitizedClassName;
|
|
787
|
+
}
|
|
788
|
+
collectSpanAttributes(this, spanAttributes);
|
|
789
|
+
if (attributes) {
|
|
790
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
791
|
+
spanAttributes[key.startsWith("ctx.") ? key : `ctx.${key}`] = value;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
const remoteSpan = showInRemoteTracing ? TRACE_PROCESSOR.tracingBackend?.startSpan({
|
|
795
|
+
name: spanName,
|
|
796
|
+
op: op ?? "function",
|
|
797
|
+
attributes: spanAttributes,
|
|
798
|
+
parentContext: parentSpanContext
|
|
799
|
+
}) : void 0;
|
|
800
|
+
let callArgs = args;
|
|
801
|
+
if (parentCtx) {
|
|
802
|
+
const childCtx = remoteSpan?.spanContext != null ? parentCtx.derive({
|
|
803
|
+
attributes: {
|
|
804
|
+
[TRACE_SPAN_ATTRIBUTE]: remoteSpan.spanContext
|
|
805
|
+
}
|
|
806
|
+
}) : parentCtx.derive();
|
|
807
|
+
callArgs = [
|
|
808
|
+
childCtx,
|
|
809
|
+
...args.slice(1)
|
|
810
|
+
];
|
|
811
|
+
}
|
|
871
812
|
try {
|
|
872
813
|
return await method.apply(this, callArgs);
|
|
873
814
|
} catch (err) {
|
|
874
|
-
|
|
815
|
+
remoteSpan?.setError?.(err);
|
|
875
816
|
throw err;
|
|
876
817
|
} finally {
|
|
877
|
-
|
|
818
|
+
remoteSpan?.end();
|
|
819
|
+
if (showInBrowserTimeline && typeof globalThis?.performance?.measure === "function") {
|
|
820
|
+
performance.measure(spanName, {
|
|
821
|
+
start: startTs,
|
|
822
|
+
end: performance.now()
|
|
823
|
+
});
|
|
824
|
+
}
|
|
878
825
|
}
|
|
879
826
|
};
|
|
880
827
|
};
|
|
881
|
-
var
|
|
828
|
+
var manualSpans = /* @__PURE__ */ new Map();
|
|
829
|
+
var manualSpanTimestamps = /* @__PURE__ */ new Map();
|
|
882
830
|
var spanStart = (params) => {
|
|
883
|
-
if (
|
|
884
|
-
return;
|
|
831
|
+
if (manualSpans.has(params.id) || manualSpanTimestamps.has(params.id)) {
|
|
832
|
+
return params.parentCtx;
|
|
833
|
+
}
|
|
834
|
+
const resourceEntry = TRACE_PROCESSOR.resourceInstanceIndex.get(params.instance);
|
|
835
|
+
const className = resourceEntry?.sanitizedClassName ?? "unknown";
|
|
836
|
+
const spanName = `${className}.${params.methodName}`;
|
|
837
|
+
if (params.showInBrowserTimeline) {
|
|
838
|
+
manualSpanTimestamps.set(params.id, {
|
|
839
|
+
name: spanName,
|
|
840
|
+
startTs: performance.now()
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
if (params.showInRemoteTracing === false || !TRACE_PROCESSOR.tracingBackend) {
|
|
844
|
+
return params.parentCtx;
|
|
845
|
+
}
|
|
846
|
+
const parentSpanContext = params.parentCtx?.getAttribute(TRACE_SPAN_ATTRIBUTE);
|
|
847
|
+
const spanAttributes = {};
|
|
848
|
+
if (resourceEntry) {
|
|
849
|
+
spanAttributes.entryPoint = resourceEntry.sanitizedClassName;
|
|
850
|
+
}
|
|
851
|
+
collectSpanAttributes(params.instance, spanAttributes);
|
|
852
|
+
if (params.attributes) {
|
|
853
|
+
for (const [key, value] of Object.entries(params.attributes)) {
|
|
854
|
+
spanAttributes[key.startsWith("ctx.") ? key : `ctx.${key}`] = value;
|
|
855
|
+
}
|
|
885
856
|
}
|
|
886
|
-
const
|
|
887
|
-
|
|
857
|
+
const remoteSpan = TRACE_PROCESSOR.tracingBackend.startSpan({
|
|
858
|
+
name: spanName,
|
|
859
|
+
op: params.op ?? "function",
|
|
860
|
+
attributes: spanAttributes,
|
|
861
|
+
parentContext: parentSpanContext
|
|
862
|
+
});
|
|
863
|
+
manualSpans.set(params.id, remoteSpan);
|
|
864
|
+
if (params.parentCtx && remoteSpan.spanContext != null) {
|
|
865
|
+
return params.parentCtx.derive({
|
|
866
|
+
attributes: {
|
|
867
|
+
[TRACE_SPAN_ATTRIBUTE]: remoteSpan.spanContext
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
return params.parentCtx;
|
|
888
872
|
};
|
|
889
873
|
var spanEnd = (id) => {
|
|
890
|
-
const
|
|
891
|
-
if (
|
|
892
|
-
|
|
893
|
-
|
|
874
|
+
const remoteSpan = manualSpans.get(id);
|
|
875
|
+
if (remoteSpan) {
|
|
876
|
+
remoteSpan.end();
|
|
877
|
+
manualSpans.delete(id);
|
|
878
|
+
}
|
|
879
|
+
const timestamps = manualSpanTimestamps.get(id);
|
|
880
|
+
if (timestamps && typeof globalThis?.performance?.measure === "function") {
|
|
881
|
+
performance.measure(timestamps.name, {
|
|
882
|
+
start: timestamps.startTs,
|
|
883
|
+
end: performance.now()
|
|
884
|
+
});
|
|
885
|
+
manualSpanTimestamps.delete(id);
|
|
894
886
|
}
|
|
895
887
|
};
|
|
896
888
|
var metricsCounter = () => (target, propertyKey, descriptor) => {
|
|
@@ -1108,16 +1100,13 @@ export {
|
|
|
1108
1100
|
DiagnosticsManager,
|
|
1109
1101
|
MapCounter,
|
|
1110
1102
|
RemoteMetrics,
|
|
1111
|
-
RemoteTracing,
|
|
1112
1103
|
ResourceEntry,
|
|
1104
|
+
TRACE_ALL_KEY,
|
|
1113
1105
|
TRACE_PROCESSOR,
|
|
1114
|
-
TRACE_SPAN_ATTRIBUTE,
|
|
1115
1106
|
TimeSeriesCounter,
|
|
1116
1107
|
TimeUsageCounter,
|
|
1117
1108
|
TraceDiagnosticImpl,
|
|
1118
1109
|
TraceProcessor,
|
|
1119
|
-
TraceSender,
|
|
1120
|
-
TracingSpan,
|
|
1121
1110
|
UnaryCounter,
|
|
1122
1111
|
getTracingContext,
|
|
1123
1112
|
sanitizeClassName,
|