@dxos/tracing 0.8.4-main.fd6878d → 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 +334 -353
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +334 -353
- 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";
|
|
@@ -121,18 +205,15 @@ var DiagnosticsChannel = class _DiagnosticsChannel {
|
|
|
121
205
|
static get supported() {
|
|
122
206
|
return globalThis.BroadcastChannel != null;
|
|
123
207
|
}
|
|
124
|
-
_ctx
|
|
208
|
+
_ctx = new Context(void 0, {
|
|
209
|
+
F: __dxlog_file2,
|
|
210
|
+
L: 46
|
|
211
|
+
});
|
|
125
212
|
// Separate channels becauase the client and server may be in the same process.
|
|
126
|
-
_serveChannel;
|
|
127
|
-
_clientChannel;
|
|
213
|
+
_serveChannel = void 0;
|
|
214
|
+
_clientChannel = void 0;
|
|
128
215
|
constructor(_channelName = DEFAULT_CHANNEL_NAME) {
|
|
129
216
|
this._channelName = _channelName;
|
|
130
|
-
this._ctx = new Context(void 0, {
|
|
131
|
-
F: __dxlog_file2,
|
|
132
|
-
L: 46
|
|
133
|
-
});
|
|
134
|
-
this._serveChannel = void 0;
|
|
135
|
-
this._clientChannel = void 0;
|
|
136
217
|
if (_DiagnosticsChannel.supported) {
|
|
137
218
|
this._serveChannel = new BroadcastChannel(_channelName);
|
|
138
219
|
this._clientChannel = new BroadcastChannel(_channelName);
|
|
@@ -285,124 +366,6 @@ var RemoteMetrics = class {
|
|
|
285
366
|
}
|
|
286
367
|
};
|
|
287
368
|
|
|
288
|
-
// src/remote/tracing.ts
|
|
289
|
-
var RemoteTracing = class {
|
|
290
|
-
_tracing;
|
|
291
|
-
_spanMap = /* @__PURE__ */ new Map();
|
|
292
|
-
registerProcessor(processor) {
|
|
293
|
-
this._tracing = processor;
|
|
294
|
-
}
|
|
295
|
-
flushSpan(span2) {
|
|
296
|
-
if (!this._tracing) {
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
if (!span2.endTs) {
|
|
300
|
-
const remoteSpan = this._tracing.startSpan({
|
|
301
|
-
name: span2.methodName,
|
|
302
|
-
op: span2.op ?? "function",
|
|
303
|
-
attributes: span2.attributes
|
|
304
|
-
});
|
|
305
|
-
this._spanMap.set(span2, remoteSpan);
|
|
306
|
-
} else {
|
|
307
|
-
const remoteSpan = this._spanMap.get(span2);
|
|
308
|
-
if (remoteSpan) {
|
|
309
|
-
remoteSpan.end();
|
|
310
|
-
this._spanMap.delete(span2);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
// src/trace-sender.ts
|
|
317
|
-
import { Stream } from "@dxos/codec-protobuf/stream";
|
|
318
|
-
var TraceSender = class {
|
|
319
|
-
_traceProcessor;
|
|
320
|
-
constructor(_traceProcessor) {
|
|
321
|
-
this._traceProcessor = _traceProcessor;
|
|
322
|
-
}
|
|
323
|
-
streamTrace(request) {
|
|
324
|
-
return new Stream(({ ctx, next }) => {
|
|
325
|
-
const flushEvents = (resources, spans2, logs) => {
|
|
326
|
-
const event = {
|
|
327
|
-
resourceAdded: [],
|
|
328
|
-
resourceRemoved: [],
|
|
329
|
-
spanAdded: [],
|
|
330
|
-
logAdded: []
|
|
331
|
-
};
|
|
332
|
-
if (resources) {
|
|
333
|
-
for (const id of resources) {
|
|
334
|
-
const entry = this._traceProcessor.resources.get(id);
|
|
335
|
-
if (entry) {
|
|
336
|
-
event.resourceAdded.push({
|
|
337
|
-
resource: entry.data
|
|
338
|
-
});
|
|
339
|
-
} else {
|
|
340
|
-
event.resourceRemoved.push({
|
|
341
|
-
id
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
} else {
|
|
346
|
-
for (const entry of this._traceProcessor.resources.values()) {
|
|
347
|
-
event.resourceAdded.push({
|
|
348
|
-
resource: entry.data
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
if (spans2) {
|
|
353
|
-
for (const id of spans2) {
|
|
354
|
-
const span2 = this._traceProcessor.spans.get(id);
|
|
355
|
-
if (span2) {
|
|
356
|
-
event.spanAdded.push({
|
|
357
|
-
span: span2
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
} else {
|
|
362
|
-
for (const span2 of this._traceProcessor.spans.values()) {
|
|
363
|
-
event.spanAdded.push({
|
|
364
|
-
span: span2
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
if (logs) {
|
|
369
|
-
for (const log2 of logs) {
|
|
370
|
-
event.logAdded.push({
|
|
371
|
-
log: log2
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
} else {
|
|
375
|
-
for (const log2 of this._traceProcessor.logs) {
|
|
376
|
-
event.logAdded.push({
|
|
377
|
-
log: log2
|
|
378
|
-
});
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
if (event.resourceAdded.length > 0 || event.resourceRemoved.length > 0 || event.spanAdded.length > 0) {
|
|
382
|
-
next(event);
|
|
383
|
-
}
|
|
384
|
-
};
|
|
385
|
-
const flush = () => {
|
|
386
|
-
flushEvents(subscription.dirtyResources, subscription.dirtySpans, subscription.newLogs);
|
|
387
|
-
subscription.dirtyResources.clear();
|
|
388
|
-
subscription.dirtySpans.clear();
|
|
389
|
-
subscription.newLogs.length = 0;
|
|
390
|
-
};
|
|
391
|
-
const subscription = {
|
|
392
|
-
flush,
|
|
393
|
-
dirtyResources: /* @__PURE__ */ new Set(),
|
|
394
|
-
dirtySpans: /* @__PURE__ */ new Set(),
|
|
395
|
-
newLogs: []
|
|
396
|
-
};
|
|
397
|
-
this._traceProcessor.subscriptions.add(subscription);
|
|
398
|
-
ctx.onDispose(() => {
|
|
399
|
-
this._traceProcessor.subscriptions.delete(subscription);
|
|
400
|
-
});
|
|
401
|
-
flushEvents(null, null, null);
|
|
402
|
-
});
|
|
403
|
-
}
|
|
404
|
-
};
|
|
405
|
-
|
|
406
369
|
// src/weak-ref.ts
|
|
407
370
|
var WeakRefMock = class {
|
|
408
371
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
|
@@ -437,35 +400,61 @@ var ResourceEntry = class {
|
|
|
437
400
|
}
|
|
438
401
|
};
|
|
439
402
|
var MAX_RESOURCE_RECORDS = 2e3;
|
|
440
|
-
var MAX_SPAN_RECORDS = 1e3;
|
|
441
403
|
var MAX_LOG_RECORDS = 1e3;
|
|
442
|
-
var REFRESH_INTERVAL = 1e3;
|
|
443
404
|
var MAX_INFO_OBJECT_DEPTH = 8;
|
|
444
|
-
var IS_CLOUDFLARE_WORKERS = !!globalThis?.navigator?.userAgent?.includes("Cloudflare-Workers");
|
|
445
405
|
var TraceProcessor = class {
|
|
446
406
|
diagnostics = new DiagnosticsManager();
|
|
447
407
|
diagnosticsChannel = new DiagnosticsChannel();
|
|
448
408
|
remoteMetrics = new RemoteMetrics();
|
|
449
|
-
|
|
450
|
-
|
|
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
|
+
}
|
|
451
446
|
resources = /* @__PURE__ */ new Map();
|
|
452
447
|
resourceInstanceIndex = /* @__PURE__ */ new WeakMap();
|
|
453
448
|
resourceIdList = [];
|
|
454
|
-
spans = /* @__PURE__ */ new Map();
|
|
455
|
-
spanIdList = [];
|
|
456
449
|
logs = [];
|
|
457
450
|
_instanceTag = null;
|
|
458
451
|
constructor() {
|
|
459
452
|
log.addProcessor(this._logProcessor.bind(this), void 0, {
|
|
460
453
|
F: __dxlog_file3,
|
|
461
|
-
L:
|
|
454
|
+
L: 108,
|
|
462
455
|
S: this,
|
|
463
456
|
C: (f, a) => f(...a)
|
|
464
457
|
});
|
|
465
|
-
if (!IS_CLOUDFLARE_WORKERS) {
|
|
466
|
-
const refreshInterval = setInterval(this.refresh.bind(this), REFRESH_INTERVAL);
|
|
467
|
-
unrefTimeout(refreshInterval);
|
|
468
|
-
}
|
|
469
458
|
if (DiagnosticsChannel.supported) {
|
|
470
459
|
this.diagnosticsChannel.serve(this.diagnostics);
|
|
471
460
|
}
|
|
@@ -475,10 +464,7 @@ var TraceProcessor = class {
|
|
|
475
464
|
this._instanceTag = tag;
|
|
476
465
|
this.diagnostics.setInstanceTag(tag);
|
|
477
466
|
}
|
|
478
|
-
/**
|
|
479
|
-
* @internal
|
|
480
|
-
*/
|
|
481
|
-
// TODO(burdon): Comment.
|
|
467
|
+
/** @internal */
|
|
482
468
|
createTraceResource(params) {
|
|
483
469
|
const id = this.resources.size;
|
|
484
470
|
const tracingContext = getTracingContext(Object.getPrototypeOf(params.instance));
|
|
@@ -499,24 +485,10 @@ var TraceProcessor = class {
|
|
|
499
485
|
if (this.resourceIdList.length > MAX_RESOURCE_RECORDS) {
|
|
500
486
|
this._clearResources();
|
|
501
487
|
}
|
|
502
|
-
this._markResourceDirty(id);
|
|
503
|
-
}
|
|
504
|
-
createTraceSender() {
|
|
505
|
-
return new TraceSender(this);
|
|
506
|
-
}
|
|
507
|
-
traceSpan(params) {
|
|
508
|
-
const span2 = new TracingSpan(this, params);
|
|
509
|
-
this._flushSpan(span2);
|
|
510
|
-
return span2;
|
|
511
488
|
}
|
|
512
489
|
// TODO(burdon): Not implemented.
|
|
513
490
|
addLink(parent, child, opts) {
|
|
514
491
|
}
|
|
515
|
-
//
|
|
516
|
-
// Getters
|
|
517
|
-
//
|
|
518
|
-
// TODO(burdon): Define type.
|
|
519
|
-
// TODO(burdon): Reconcile with system service.
|
|
520
492
|
getDiagnostics() {
|
|
521
493
|
this.refresh();
|
|
522
494
|
return {
|
|
@@ -524,7 +496,6 @@ var TraceProcessor = class {
|
|
|
524
496
|
`${entry.sanitizedClassName}#${entry.data.instanceId}`,
|
|
525
497
|
entry.data
|
|
526
498
|
])),
|
|
527
|
-
spans: Array.from(this.spans.values()),
|
|
528
499
|
logs: this.logs.filter((log2) => log2.level >= LogLevel.INFO)
|
|
529
500
|
};
|
|
530
501
|
}
|
|
@@ -579,43 +550,8 @@ var TraceProcessor = class {
|
|
|
579
550
|
for (const key of Object.keys(tracingContext.metricsProperties)) {
|
|
580
551
|
instance[key]._tick?.(time);
|
|
581
552
|
}
|
|
582
|
-
let _changed = false;
|
|
583
|
-
const oldInfo = resource2.data.info;
|
|
584
553
|
resource2.data.info = this.getResourceInfo(instance);
|
|
585
|
-
_changed ||= !areEqualShallow(oldInfo, resource2.data.info);
|
|
586
|
-
const oldMetrics = resource2.data.metrics;
|
|
587
554
|
resource2.data.metrics = this.getResourceMetrics(instance);
|
|
588
|
-
_changed ||= !areEqualShallow(oldMetrics, resource2.data.metrics);
|
|
589
|
-
this._markResourceDirty(resource2.data.id);
|
|
590
|
-
}
|
|
591
|
-
for (const subscription of this.subscriptions) {
|
|
592
|
-
subscription.flush();
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
//
|
|
596
|
-
// Implementation
|
|
597
|
-
//
|
|
598
|
-
/**
|
|
599
|
-
* @internal
|
|
600
|
-
*/
|
|
601
|
-
_flushSpan(runtimeSpan) {
|
|
602
|
-
const span2 = runtimeSpan.serialize();
|
|
603
|
-
this.spans.set(span2.id, span2);
|
|
604
|
-
this.spanIdList.push(span2.id);
|
|
605
|
-
if (this.spanIdList.length > MAX_SPAN_RECORDS) {
|
|
606
|
-
this._clearSpans();
|
|
607
|
-
}
|
|
608
|
-
this._markSpanDirty(span2.id);
|
|
609
|
-
this.remoteTracing.flushSpan(runtimeSpan);
|
|
610
|
-
}
|
|
611
|
-
_markResourceDirty(id) {
|
|
612
|
-
for (const subscription of this.subscriptions) {
|
|
613
|
-
subscription.dirtyResources.add(id);
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
_markSpanDirty(id) {
|
|
617
|
-
for (const subscription of this.subscriptions) {
|
|
618
|
-
subscription.dirtySpans.add(id);
|
|
619
555
|
}
|
|
620
556
|
}
|
|
621
557
|
_clearResources() {
|
|
@@ -624,20 +560,11 @@ var TraceProcessor = class {
|
|
|
624
560
|
this.resources.delete(id);
|
|
625
561
|
}
|
|
626
562
|
}
|
|
627
|
-
_clearSpans() {
|
|
628
|
-
while (this.spanIdList.length > MAX_SPAN_RECORDS) {
|
|
629
|
-
const id = this.spanIdList.shift();
|
|
630
|
-
this.spans.delete(id);
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
563
|
_pushLog(log2) {
|
|
634
564
|
this.logs.push(log2);
|
|
635
565
|
if (this.logs.length > MAX_LOG_RECORDS) {
|
|
636
566
|
this.logs.shift();
|
|
637
567
|
}
|
|
638
|
-
for (const subscription of this.subscriptions) {
|
|
639
|
-
subscription.newLogs.push(log2);
|
|
640
|
-
}
|
|
641
568
|
}
|
|
642
569
|
_logProcessor = (config, entry) => {
|
|
643
570
|
switch (entry.level) {
|
|
@@ -649,18 +576,21 @@ var TraceProcessor = class {
|
|
|
649
576
|
if (!resource2) {
|
|
650
577
|
return;
|
|
651
578
|
}
|
|
652
|
-
const context =
|
|
653
|
-
|
|
654
|
-
|
|
579
|
+
const context = {
|
|
580
|
+
...entry.computedContext
|
|
581
|
+
};
|
|
582
|
+
if (entry.computedError !== void 0) {
|
|
583
|
+
context.error = entry.computedError;
|
|
655
584
|
}
|
|
585
|
+
const { filename, line } = entry.computedMeta;
|
|
656
586
|
const entryToPush = {
|
|
657
587
|
level: entry.level,
|
|
658
|
-
message: entry.message ??
|
|
588
|
+
message: entry.message ?? entry.computedError ?? "",
|
|
659
589
|
context,
|
|
660
|
-
timestamp:
|
|
590
|
+
timestamp: new Date(entry.timestamp),
|
|
661
591
|
meta: {
|
|
662
|
-
file:
|
|
663
|
-
line:
|
|
592
|
+
file: filename ?? "",
|
|
593
|
+
line: line ?? 0,
|
|
664
594
|
resourceId: resource2.data.id
|
|
665
595
|
}
|
|
666
596
|
};
|
|
@@ -671,99 +601,6 @@ var TraceProcessor = class {
|
|
|
671
601
|
}
|
|
672
602
|
};
|
|
673
603
|
};
|
|
674
|
-
var TracingSpan = class _TracingSpan {
|
|
675
|
-
_traceProcessor;
|
|
676
|
-
static nextId = 0;
|
|
677
|
-
id;
|
|
678
|
-
parentId;
|
|
679
|
-
methodName;
|
|
680
|
-
resourceId;
|
|
681
|
-
op;
|
|
682
|
-
attributes;
|
|
683
|
-
startTs;
|
|
684
|
-
endTs;
|
|
685
|
-
error;
|
|
686
|
-
_showInBrowserTimeline;
|
|
687
|
-
_ctx;
|
|
688
|
-
constructor(_traceProcessor, params) {
|
|
689
|
-
this._traceProcessor = _traceProcessor;
|
|
690
|
-
this.parentId = null;
|
|
691
|
-
this.resourceId = null;
|
|
692
|
-
this.endTs = null;
|
|
693
|
-
this.error = null;
|
|
694
|
-
this._ctx = null;
|
|
695
|
-
this.id = _TracingSpan.nextId++;
|
|
696
|
-
this.methodName = params.methodName;
|
|
697
|
-
this.resourceId = _traceProcessor.getResourceId(params.instance);
|
|
698
|
-
this.startTs = performance.now();
|
|
699
|
-
this._showInBrowserTimeline = params.showInBrowserTimeline;
|
|
700
|
-
this.op = params.op;
|
|
701
|
-
this.attributes = params.attributes ?? {};
|
|
702
|
-
if (params.parentCtx) {
|
|
703
|
-
this._ctx = params.parentCtx.derive({
|
|
704
|
-
attributes: {
|
|
705
|
-
[TRACE_SPAN_ATTRIBUTE]: this.id
|
|
706
|
-
}
|
|
707
|
-
});
|
|
708
|
-
const parentId = params.parentCtx.getAttribute(TRACE_SPAN_ATTRIBUTE);
|
|
709
|
-
if (typeof parentId === "number") {
|
|
710
|
-
this.parentId = parentId;
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
get name() {
|
|
715
|
-
const resource2 = this._traceProcessor.resources.get(this.resourceId);
|
|
716
|
-
return resource2 ? `${resource2.sanitizedClassName}#${resource2.data.instanceId}.${this.methodName}` : this.methodName;
|
|
717
|
-
}
|
|
718
|
-
get ctx() {
|
|
719
|
-
return this._ctx;
|
|
720
|
-
}
|
|
721
|
-
markSuccess() {
|
|
722
|
-
this.endTs = performance.now();
|
|
723
|
-
this._traceProcessor._flushSpan(this);
|
|
724
|
-
if (this._showInBrowserTimeline) {
|
|
725
|
-
this._markInBrowserTimeline();
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
markError(err) {
|
|
729
|
-
this.endTs = performance.now();
|
|
730
|
-
this.error = serializeError(err);
|
|
731
|
-
this._traceProcessor._flushSpan(this);
|
|
732
|
-
if (this._showInBrowserTimeline) {
|
|
733
|
-
this._markInBrowserTimeline();
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
serialize() {
|
|
737
|
-
return {
|
|
738
|
-
id: this.id,
|
|
739
|
-
resourceId: this.resourceId ?? void 0,
|
|
740
|
-
methodName: this.methodName,
|
|
741
|
-
parentId: this.parentId ?? void 0,
|
|
742
|
-
startTs: this.startTs.toFixed(3),
|
|
743
|
-
endTs: this.endTs?.toFixed(3) ?? void 0,
|
|
744
|
-
error: this.error ?? void 0
|
|
745
|
-
};
|
|
746
|
-
}
|
|
747
|
-
_markInBrowserTimeline() {
|
|
748
|
-
if (typeof globalThis?.performance?.measure === "function") {
|
|
749
|
-
performance.measure(this.name, {
|
|
750
|
-
start: this.startTs,
|
|
751
|
-
end: this.endTs
|
|
752
|
-
});
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
};
|
|
756
|
-
var serializeError = (err) => {
|
|
757
|
-
if (err instanceof Error) {
|
|
758
|
-
return {
|
|
759
|
-
name: err.name,
|
|
760
|
-
message: err.message
|
|
761
|
-
};
|
|
762
|
-
}
|
|
763
|
-
return {
|
|
764
|
-
message: String(err)
|
|
765
|
-
};
|
|
766
|
-
};
|
|
767
604
|
var TRACE_PROCESSOR = globalThis.TRACE_PROCESSOR ??= new TraceProcessor();
|
|
768
605
|
var sanitizeValue = (value, depth, traceProcessor) => {
|
|
769
606
|
switch (typeof value) {
|
|
@@ -810,33 +647,46 @@ var sanitizeValue = (value, depth, traceProcessor) => {
|
|
|
810
647
|
return value.toString();
|
|
811
648
|
}
|
|
812
649
|
};
|
|
813
|
-
var areEqualShallow = (a, b) => {
|
|
814
|
-
for (const key in a) {
|
|
815
|
-
if (!(key in b) || a[key] !== b[key]) {
|
|
816
|
-
return false;
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
for (const key in b) {
|
|
820
|
-
if (!(key in a) || a[key] !== b[key]) {
|
|
821
|
-
return false;
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
return true;
|
|
825
|
-
};
|
|
826
650
|
var sanitizeClassName = (className) => {
|
|
651
|
+
let name = className.replace(/^_+/, "");
|
|
827
652
|
const SANITIZE_REGEX = /[^_](\d+)$/;
|
|
828
|
-
const m =
|
|
829
|
-
if (
|
|
830
|
-
|
|
831
|
-
} else {
|
|
832
|
-
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);
|
|
833
656
|
}
|
|
657
|
+
return name;
|
|
834
658
|
};
|
|
835
659
|
var isSetLike = (value) => value instanceof Set || typeof value === "object" && value !== null && Object.getPrototypeOf(value).constructor.name === "ComplexSet";
|
|
836
660
|
var isMapLike = (value) => value instanceof Map || typeof value === "object" && value !== null && Object.getPrototypeOf(value).constructor.name === "ComplexMap";
|
|
837
661
|
|
|
838
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
|
+
};
|
|
839
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
|
+
}
|
|
840
690
|
const klass = /* @__PURE__ */ (() => class extends constructor {
|
|
841
691
|
constructor(...rest) {
|
|
842
692
|
super(...rest);
|
|
@@ -847,6 +697,68 @@ var resource = (options) => (constructor) => {
|
|
|
847
697
|
});
|
|
848
698
|
}
|
|
849
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
|
+
}
|
|
850
762
|
Object.defineProperty(klass, "name", {
|
|
851
763
|
value: constructor.name
|
|
852
764
|
});
|
|
@@ -860,45 +772,117 @@ var info = (opts = {}) => (target, propertyKey, descriptor) => {
|
|
|
860
772
|
var mark = (name) => {
|
|
861
773
|
performance.mark(name);
|
|
862
774
|
};
|
|
863
|
-
var span = ({ showInBrowserTimeline = false, op, attributes } = {}) => (target, propertyKey, descriptor) => {
|
|
775
|
+
var span = ({ showInBrowserTimeline = false, showInRemoteTracing = true, op, attributes } = {}) => (target, propertyKey, descriptor) => {
|
|
864
776
|
const method = descriptor.value;
|
|
865
777
|
descriptor.value = async function(...args) {
|
|
866
778
|
const parentCtx = args[0] instanceof Context2 ? args[0] : null;
|
|
867
|
-
const
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
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
|
+
}
|
|
879
812
|
try {
|
|
880
813
|
return await method.apply(this, callArgs);
|
|
881
814
|
} catch (err) {
|
|
882
|
-
|
|
815
|
+
remoteSpan?.setError?.(err);
|
|
883
816
|
throw err;
|
|
884
817
|
} finally {
|
|
885
|
-
|
|
818
|
+
remoteSpan?.end();
|
|
819
|
+
if (showInBrowserTimeline && typeof globalThis?.performance?.measure === "function") {
|
|
820
|
+
performance.measure(spanName, {
|
|
821
|
+
start: startTs,
|
|
822
|
+
end: performance.now()
|
|
823
|
+
});
|
|
824
|
+
}
|
|
886
825
|
}
|
|
887
826
|
};
|
|
888
827
|
};
|
|
889
|
-
var
|
|
828
|
+
var manualSpans = /* @__PURE__ */ new Map();
|
|
829
|
+
var manualSpanTimestamps = /* @__PURE__ */ new Map();
|
|
890
830
|
var spanStart = (params) => {
|
|
891
|
-
if (
|
|
892
|
-
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
|
+
}
|
|
893
856
|
}
|
|
894
|
-
const
|
|
895
|
-
|
|
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;
|
|
896
872
|
};
|
|
897
873
|
var spanEnd = (id) => {
|
|
898
|
-
const
|
|
899
|
-
if (
|
|
900
|
-
|
|
901
|
-
|
|
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);
|
|
902
886
|
}
|
|
903
887
|
};
|
|
904
888
|
var metricsCounter = () => (target, propertyKey, descriptor) => {
|
|
@@ -1116,16 +1100,13 @@ export {
|
|
|
1116
1100
|
DiagnosticsManager,
|
|
1117
1101
|
MapCounter,
|
|
1118
1102
|
RemoteMetrics,
|
|
1119
|
-
RemoteTracing,
|
|
1120
1103
|
ResourceEntry,
|
|
1104
|
+
TRACE_ALL_KEY,
|
|
1121
1105
|
TRACE_PROCESSOR,
|
|
1122
|
-
TRACE_SPAN_ATTRIBUTE,
|
|
1123
1106
|
TimeSeriesCounter,
|
|
1124
1107
|
TimeUsageCounter,
|
|
1125
1108
|
TraceDiagnosticImpl,
|
|
1126
1109
|
TraceProcessor,
|
|
1127
|
-
TraceSender,
|
|
1128
|
-
TracingSpan,
|
|
1129
1110
|
UnaryCounter,
|
|
1130
1111
|
getTracingContext,
|
|
1131
1112
|
sanitizeClassName,
|