@dxos/tracing 0.6.13 → 0.6.14-main.2b6a0f3

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.
@@ -0,0 +1,1091 @@
1
+ import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
+
3
+ // packages/common/tracing/src/api.ts
4
+ import { Context as Context2 } from "@dxos/context";
5
+
6
+ // packages/common/tracing/src/symbols.ts
7
+ var symbolTracingContext = Symbol("dxos.tracing.context");
8
+ var getTracingContext = (target) => {
9
+ return target[symbolTracingContext] ??= {
10
+ infoProperties: {},
11
+ metricsProperties: {}
12
+ };
13
+ };
14
+ var TRACE_SPAN_ATTRIBUTE = "dxos.trace-span";
15
+
16
+ // packages/common/tracing/src/trace-processor.ts
17
+ import { unrefTimeout } from "@dxos/async";
18
+ import { LogLevel, getContextFromEntry, log } from "@dxos/log";
19
+ import { getPrototypeSpecificInstanceId } from "@dxos/util";
20
+
21
+ // packages/common/tracing/src/diagnostic.ts
22
+ import { asyncTimeout } from "@dxos/async";
23
+ import { invariant } from "@dxos/invariant";
24
+
25
+ // packages/common/tracing/src/util.ts
26
+ var createId = () => Math.random().toString(36).slice(2);
27
+
28
+ // packages/common/tracing/src/diagnostic.ts
29
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/common/tracing/src/diagnostic.ts";
30
+ var DIAGNOSTICS_TIMEOUT = 1e4;
31
+ var TraceDiagnosticImpl = class {
32
+ constructor(id, fetch, name, _onUnregister) {
33
+ this.id = id;
34
+ this.fetch = fetch;
35
+ this.name = name;
36
+ this._onUnregister = _onUnregister;
37
+ }
38
+ unregister() {
39
+ this._onUnregister();
40
+ }
41
+ };
42
+ var DiagnosticsManager = class {
43
+ constructor() {
44
+ this.instanceId = createId();
45
+ this.registry = /* @__PURE__ */ new Map();
46
+ this._instanceTag = null;
47
+ }
48
+ get instanceTag() {
49
+ return this._instanceTag;
50
+ }
51
+ setInstanceTag(tag) {
52
+ this._instanceTag = tag;
53
+ }
54
+ registerDiagnostic(params) {
55
+ const impl = new TraceDiagnosticImpl(params.id, params.fetch, params.name ?? params.id, () => {
56
+ if (this.registry.get(params.id) === impl) {
57
+ this.registry.delete(params.id);
58
+ }
59
+ });
60
+ this.registry.set(params.id, impl);
61
+ return impl;
62
+ }
63
+ list() {
64
+ return Array.from(this.registry.values()).map((diagnostic2) => ({
65
+ id: diagnostic2.id,
66
+ instanceId: this.instanceId,
67
+ instanceTag: this._instanceTag,
68
+ name: diagnostic2.name
69
+ }));
70
+ }
71
+ async fetch(request) {
72
+ if (request.instanceId != null) {
73
+ invariant(request.instanceId === this.instanceId, "Invalid instance id", {
74
+ F: __dxlog_file,
75
+ L: 82,
76
+ S: this,
77
+ A: [
78
+ "request.instanceId === this.instanceId",
79
+ "'Invalid instance id'"
80
+ ]
81
+ });
82
+ }
83
+ const { id } = request;
84
+ const diagnostic2 = this.registry.get(id);
85
+ invariant(diagnostic2, "Diagnostic not found", {
86
+ F: __dxlog_file,
87
+ L: 86,
88
+ S: this,
89
+ A: [
90
+ "diagnostic",
91
+ "'Diagnostic not found'"
92
+ ]
93
+ });
94
+ try {
95
+ const data = await asyncTimeout(diagnostic2.fetch(), DIAGNOSTICS_TIMEOUT);
96
+ return {
97
+ id,
98
+ instanceId: this.instanceId,
99
+ data
100
+ };
101
+ } catch (err) {
102
+ return {
103
+ id,
104
+ instanceId: this.instanceId,
105
+ data: null,
106
+ error: err.stack
107
+ };
108
+ }
109
+ }
110
+ };
111
+
112
+ // packages/common/tracing/src/diagnostics-channel.ts
113
+ import { Trigger, sleep } from "@dxos/async";
114
+ import { Context } from "@dxos/context";
115
+ import { invariant as invariant2 } from "@dxos/invariant";
116
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/common/tracing/src/diagnostics-channel.ts";
117
+ var DEFAULT_CHANNEL_NAME = "dxos-diagnostics";
118
+ var DISCOVER_TIME = 500;
119
+ var DiagnosticsChannel = class _DiagnosticsChannel {
120
+ static get supported() {
121
+ return globalThis.BroadcastChannel != null;
122
+ }
123
+ constructor(_channelName = DEFAULT_CHANNEL_NAME) {
124
+ this._channelName = _channelName;
125
+ this._ctx = new Context(void 0, {
126
+ F: __dxlog_file2,
127
+ L: 46
128
+ });
129
+ this._serveChannel = void 0;
130
+ this._clientChannel = void 0;
131
+ if (_DiagnosticsChannel.supported) {
132
+ this._serveChannel = new BroadcastChannel(_channelName);
133
+ this._clientChannel = new BroadcastChannel(_channelName);
134
+ }
135
+ }
136
+ destroy() {
137
+ void this._ctx.dispose();
138
+ this._serveChannel?.close();
139
+ this._clientChannel?.close();
140
+ }
141
+ /**
142
+ * In node.js, the channel will keep the process alive.
143
+ * This method allows the process to exit.
144
+ * Noop in the browser.
145
+ */
146
+ unref() {
147
+ if (this._serveChannel && typeof this._serveChannel.unref === "function") {
148
+ this._serveChannel.unref();
149
+ this._clientChannel.unref();
150
+ }
151
+ }
152
+ serve(manager) {
153
+ invariant2(this._serveChannel, void 0, {
154
+ F: __dxlog_file2,
155
+ L: 78,
156
+ S: this,
157
+ A: [
158
+ "this._serveChannel",
159
+ ""
160
+ ]
161
+ });
162
+ const listener = async (event) => {
163
+ switch (event.data.type) {
164
+ case "DIAGNOSTICS_DISCOVER": {
165
+ const diagnostics = manager.list();
166
+ this._serveChannel.postMessage({
167
+ type: "DIAGNOSTICS_ANNOUNCE",
168
+ diagnostics
169
+ });
170
+ break;
171
+ }
172
+ case "DIAGNOSTICS_FETCH": {
173
+ const { requestId, request } = event.data;
174
+ if (request.instanceId != null && request.instanceId !== manager.instanceId) {
175
+ break;
176
+ } else if (request.instanceTag != null && request.instanceTag !== manager.instanceTag) {
177
+ break;
178
+ }
179
+ const data = await manager.fetch(request);
180
+ this._serveChannel.postMessage({
181
+ type: "DIAGNOSTICS_RESPONSE",
182
+ requestId,
183
+ data
184
+ });
185
+ break;
186
+ }
187
+ }
188
+ };
189
+ this._serveChannel.addEventListener("message", listener);
190
+ this._ctx.onDispose(() => this._serveChannel.removeEventListener("message", listener));
191
+ }
192
+ async discover() {
193
+ invariant2(this._clientChannel, void 0, {
194
+ F: __dxlog_file2,
195
+ L: 114,
196
+ S: this,
197
+ A: [
198
+ "this._clientChannel",
199
+ ""
200
+ ]
201
+ });
202
+ const diagnostics = [];
203
+ const collector = (event) => {
204
+ const data = event.data;
205
+ switch (data.type) {
206
+ case "DIAGNOSTICS_ANNOUNCE":
207
+ diagnostics.push(...data.diagnostics);
208
+ break;
209
+ }
210
+ };
211
+ try {
212
+ this._clientChannel.addEventListener("message", collector);
213
+ this._clientChannel.postMessage({
214
+ type: "DIAGNOSTICS_DISCOVER"
215
+ });
216
+ await sleep(DISCOVER_TIME);
217
+ const result = [];
218
+ for (const diagnostic2 of diagnostics) {
219
+ if (!result.some((d) => d.id === diagnostic2.id && d.instanceId === diagnostic2.instanceId)) {
220
+ result.push(diagnostic2);
221
+ }
222
+ }
223
+ return diagnostics;
224
+ } finally {
225
+ this._clientChannel.removeEventListener("message", collector);
226
+ }
227
+ }
228
+ async fetch(request) {
229
+ invariant2(this._clientChannel, void 0, {
230
+ F: __dxlog_file2,
231
+ L: 147,
232
+ S: this,
233
+ A: [
234
+ "this._clientChannel",
235
+ ""
236
+ ]
237
+ });
238
+ const requestId = createId();
239
+ const trigger = new Trigger();
240
+ const listener = (event) => {
241
+ const data = event.data;
242
+ if (data.type === "DIAGNOSTICS_RESPONSE" && data.requestId === requestId) {
243
+ trigger.wake(data.data);
244
+ }
245
+ };
246
+ try {
247
+ this._clientChannel.addEventListener("message", listener);
248
+ this._clientChannel.postMessage({
249
+ type: "DIAGNOSTICS_FETCH",
250
+ requestId,
251
+ request
252
+ });
253
+ const result = await trigger.wait({
254
+ timeout: DIAGNOSTICS_TIMEOUT
255
+ });
256
+ return result;
257
+ } finally {
258
+ this._clientChannel.removeEventListener("message", listener);
259
+ }
260
+ }
261
+ };
262
+
263
+ // packages/common/tracing/src/remote/metrics.ts
264
+ var RemoteMetrics = class {
265
+ constructor() {
266
+ this._metrics = /* @__PURE__ */ new Set();
267
+ }
268
+ registerProcessor(processor) {
269
+ this._metrics.add(processor);
270
+ }
271
+ increment(name, value, data) {
272
+ return Array.from(this._metrics.values()).map((processor) => processor.increment(name, value, data));
273
+ }
274
+ distribution(name, value, data) {
275
+ return Array.from(this._metrics.values()).map((processor) => processor.distribution(name, value, data));
276
+ }
277
+ set(name, value, data) {
278
+ return Array.from(this._metrics.values()).map((processor) => processor.set(name, value, data));
279
+ }
280
+ gauge(name, value, data) {
281
+ return Array.from(this._metrics.values()).map((processor) => processor.gauge(name, value, data));
282
+ }
283
+ };
284
+
285
+ // packages/common/tracing/src/remote/tracing.ts
286
+ var RemoteTracing = class {
287
+ constructor() {
288
+ this._spanMap = /* @__PURE__ */ new Map();
289
+ }
290
+ registerProcessor(processor) {
291
+ this._tracing = processor;
292
+ }
293
+ flushSpan(span2) {
294
+ if (!this._tracing) {
295
+ return;
296
+ }
297
+ if (!span2.endTs) {
298
+ const remoteSpan = this._tracing.startSpan({
299
+ name: span2.methodName,
300
+ op: span2.op ?? "function",
301
+ attributes: span2.attributes
302
+ });
303
+ this._spanMap.set(span2, remoteSpan);
304
+ } else {
305
+ const remoteSpan = this._spanMap.get(span2);
306
+ if (remoteSpan) {
307
+ remoteSpan.end();
308
+ this._spanMap.delete(span2);
309
+ }
310
+ }
311
+ }
312
+ };
313
+
314
+ // packages/common/tracing/src/trace-sender.ts
315
+ import { Stream } from "@dxos/codec-protobuf";
316
+ var TraceSender = class {
317
+ constructor(_traceProcessor) {
318
+ this._traceProcessor = _traceProcessor;
319
+ }
320
+ streamTrace(request) {
321
+ return new Stream(({ ctx, next }) => {
322
+ const flushEvents = (resources, spans, 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 (spans) {
350
+ for (const id of spans) {
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
+ // packages/common/tracing/src/weak-ref.ts
404
+ var WeakRefMock = class {
405
+ // eslint-disable-next-line @typescript-eslint/no-useless-constructor
406
+ constructor(target) {
407
+ }
408
+ deref() {
409
+ return void 0;
410
+ }
411
+ };
412
+ var WeakRef = globalThis.WeakRef ?? WeakRefMock;
413
+
414
+ // packages/common/tracing/src/trace-processor.ts
415
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/common/tracing/src/trace-processor.ts";
416
+ var ResourceEntry = class {
417
+ constructor(data, instance, annotation) {
418
+ this.data = data;
419
+ this.instance = instance;
420
+ this.annotation = annotation;
421
+ this.sanitizedClassName = sanitizeClassName(data.className);
422
+ }
423
+ getMetric(name) {
424
+ return this.data.metrics?.find((metric) => metric.name === name);
425
+ }
426
+ };
427
+ var MAX_RESOURCE_RECORDS = 2e3;
428
+ var MAX_SPAN_RECORDS = 1e3;
429
+ var MAX_LOG_RECORDS = 1e3;
430
+ var REFRESH_INTERVAL = 1e3;
431
+ var MAX_INFO_OBJECT_DEPTH = 8;
432
+ var IS_CLOUDFLARE_WORKERS = !!globalThis?.navigator?.userAgent?.includes("Cloudflare-Workers");
433
+ var TraceProcessor = class {
434
+ constructor() {
435
+ this.diagnostics = new DiagnosticsManager();
436
+ this.diagnosticsChannel = new DiagnosticsChannel();
437
+ this.remoteMetrics = new RemoteMetrics();
438
+ this.remoteTracing = new RemoteTracing();
439
+ this.subscriptions = /* @__PURE__ */ new Set();
440
+ this.resources = /* @__PURE__ */ new Map();
441
+ this.resourceInstanceIndex = /* @__PURE__ */ new WeakMap();
442
+ this.resourceIdList = [];
443
+ this.spans = /* @__PURE__ */ new Map();
444
+ this.spanIdList = [];
445
+ this.logs = [];
446
+ this._instanceTag = null;
447
+ this._logProcessor = (config, entry) => {
448
+ switch (entry.level) {
449
+ case LogLevel.ERROR:
450
+ case LogLevel.WARN:
451
+ case LogLevel.TRACE: {
452
+ const scope = entry.meta?.S;
453
+ const resource2 = this.resourceInstanceIndex.get(scope);
454
+ if (!resource2) {
455
+ return;
456
+ }
457
+ const context = getContextFromEntry(entry) ?? {};
458
+ for (const key of Object.keys(context)) {
459
+ context[key] = sanitizeValue(context[key], 0, this);
460
+ }
461
+ const entryToPush = {
462
+ level: entry.level,
463
+ message: entry.message,
464
+ context,
465
+ timestamp: /* @__PURE__ */ new Date(),
466
+ meta: {
467
+ file: entry.meta?.F ?? "",
468
+ line: entry.meta?.L ?? 0,
469
+ resourceId: resource2.data.id
470
+ }
471
+ };
472
+ this._pushLog(entryToPush);
473
+ break;
474
+ }
475
+ default:
476
+ }
477
+ };
478
+ log.addProcessor(this._logProcessor.bind(this), void 0, {
479
+ F: __dxlog_file3,
480
+ L: 103,
481
+ S: this,
482
+ C: (f, a) => f(...a)
483
+ });
484
+ if (!IS_CLOUDFLARE_WORKERS) {
485
+ const refreshInterval = setInterval(this.refresh.bind(this), REFRESH_INTERVAL);
486
+ unrefTimeout(refreshInterval);
487
+ }
488
+ if (DiagnosticsChannel.supported) {
489
+ this.diagnosticsChannel.serve(this.diagnostics);
490
+ }
491
+ this.diagnosticsChannel.unref();
492
+ }
493
+ setInstanceTag(tag) {
494
+ this._instanceTag = tag;
495
+ this.diagnostics.setInstanceTag(tag);
496
+ }
497
+ /**
498
+ * @internal
499
+ */
500
+ // TODO(burdon): Comment.
501
+ createTraceResource(params) {
502
+ const id = this.resources.size;
503
+ const tracingContext = getTracingContext(Object.getPrototypeOf(params.instance));
504
+ for (const key of Object.keys(tracingContext.metricsProperties)) {
505
+ params.instance[key]._assign(params.instance, key);
506
+ }
507
+ const entry = new ResourceEntry({
508
+ id,
509
+ className: params.constructor.name,
510
+ instanceId: getPrototypeSpecificInstanceId(params.instance),
511
+ info: this.getResourceInfo(params.instance),
512
+ links: [],
513
+ metrics: this.getResourceMetrics(params.instance)
514
+ }, new WeakRef(params.instance), params.annotation);
515
+ this.resources.set(id, entry);
516
+ this.resourceInstanceIndex.set(params.instance, entry);
517
+ this.resourceIdList.push(id);
518
+ if (this.resourceIdList.length > MAX_RESOURCE_RECORDS) {
519
+ this._clearResources();
520
+ }
521
+ this._markResourceDirty(id);
522
+ }
523
+ createTraceSender() {
524
+ return new TraceSender(this);
525
+ }
526
+ traceSpan(params) {
527
+ const span2 = new TracingSpan(this, params);
528
+ this._flushSpan(span2);
529
+ return span2;
530
+ }
531
+ // TODO(burdon): Not implemented.
532
+ addLink(parent, child, opts) {
533
+ }
534
+ //
535
+ // Getters
536
+ //
537
+ // TODO(burdon): Define type.
538
+ // TODO(burdon): Reconcile with system service.
539
+ getDiagnostics() {
540
+ this.refresh();
541
+ return {
542
+ resources: Object.fromEntries(Array.from(this.resources.entries()).map(([id, entry]) => [
543
+ `${entry.sanitizedClassName}#${entry.data.instanceId}`,
544
+ entry.data
545
+ ])),
546
+ spans: Array.from(this.spans.values()),
547
+ logs: this.logs.filter((log2) => log2.level >= LogLevel.INFO)
548
+ };
549
+ }
550
+ getResourceInfo(instance) {
551
+ const res = {};
552
+ const tracingContext = getTracingContext(Object.getPrototypeOf(instance));
553
+ for (const [key, { options }] of Object.entries(tracingContext.infoProperties)) {
554
+ try {
555
+ const value = typeof instance[key] === "function" ? instance[key]() : instance[key];
556
+ if (options.enum) {
557
+ res[key] = options.enum[value];
558
+ } else {
559
+ res[key] = sanitizeValue(value, options.depth === void 0 ? 1 : options.depth ?? MAX_INFO_OBJECT_DEPTH, this);
560
+ }
561
+ } catch (err) {
562
+ res[key] = err.message;
563
+ }
564
+ }
565
+ return res;
566
+ }
567
+ getResourceMetrics(instance) {
568
+ const res = [];
569
+ const tracingContext = getTracingContext(Object.getPrototypeOf(instance));
570
+ for (const [key, _opts] of Object.entries(tracingContext.metricsProperties)) {
571
+ res.push(instance[key].getData());
572
+ }
573
+ return res;
574
+ }
575
+ getResourceId(instance) {
576
+ const entry = this.resourceInstanceIndex.get(instance);
577
+ return entry ? entry.data.id : null;
578
+ }
579
+ findResourcesByClassName(className) {
580
+ return [
581
+ ...this.resources.values()
582
+ ].filter((res) => res.data.className === className || res.sanitizedClassName === className);
583
+ }
584
+ findResourcesByAnnotation(annotation) {
585
+ return [
586
+ ...this.resources.values()
587
+ ].filter((res) => res.annotation === annotation);
588
+ }
589
+ refresh() {
590
+ for (const resource2 of this.resources.values()) {
591
+ const instance = resource2.instance.deref();
592
+ if (!instance) {
593
+ continue;
594
+ }
595
+ const tracingContext = getTracingContext(Object.getPrototypeOf(instance));
596
+ const time = performance.now();
597
+ instance.tick?.(time);
598
+ for (const key of Object.keys(tracingContext.metricsProperties)) {
599
+ instance[key]._tick?.(time);
600
+ }
601
+ let _changed = false;
602
+ const oldInfo = resource2.data.info;
603
+ resource2.data.info = this.getResourceInfo(instance);
604
+ _changed ||= !areEqualShallow(oldInfo, resource2.data.info);
605
+ const oldMetrics = resource2.data.metrics;
606
+ resource2.data.metrics = this.getResourceMetrics(instance);
607
+ _changed ||= !areEqualShallow(oldMetrics, resource2.data.metrics);
608
+ this._markResourceDirty(resource2.data.id);
609
+ }
610
+ for (const subscription of this.subscriptions) {
611
+ subscription.flush();
612
+ }
613
+ }
614
+ //
615
+ // Implementation
616
+ //
617
+ /**
618
+ * @internal
619
+ */
620
+ _flushSpan(runtimeSpan) {
621
+ const span2 = runtimeSpan.serialize();
622
+ this.spans.set(span2.id, span2);
623
+ this.spanIdList.push(span2.id);
624
+ if (this.spanIdList.length > MAX_SPAN_RECORDS) {
625
+ this._clearSpans();
626
+ }
627
+ this._markSpanDirty(span2.id);
628
+ this.remoteTracing.flushSpan(runtimeSpan);
629
+ }
630
+ _markResourceDirty(id) {
631
+ for (const subscription of this.subscriptions) {
632
+ subscription.dirtyResources.add(id);
633
+ }
634
+ }
635
+ _markSpanDirty(id) {
636
+ for (const subscription of this.subscriptions) {
637
+ subscription.dirtySpans.add(id);
638
+ }
639
+ }
640
+ _clearResources() {
641
+ while (this.resourceIdList.length > MAX_RESOURCE_RECORDS) {
642
+ const id = this.resourceIdList.shift();
643
+ this.resources.delete(id);
644
+ }
645
+ }
646
+ _clearSpans() {
647
+ while (this.spanIdList.length > MAX_SPAN_RECORDS) {
648
+ const id = this.spanIdList.shift();
649
+ this.spans.delete(id);
650
+ }
651
+ }
652
+ _pushLog(log2) {
653
+ this.logs.push(log2);
654
+ if (this.logs.length > MAX_LOG_RECORDS) {
655
+ this.logs.shift();
656
+ }
657
+ for (const subscription of this.subscriptions) {
658
+ subscription.newLogs.push(log2);
659
+ }
660
+ }
661
+ };
662
+ var TracingSpan = class _TracingSpan {
663
+ static {
664
+ this.nextId = 0;
665
+ }
666
+ constructor(_traceProcessor, params) {
667
+ this._traceProcessor = _traceProcessor;
668
+ this.parentId = null;
669
+ this.resourceId = null;
670
+ this.endTs = null;
671
+ this.error = null;
672
+ this._ctx = null;
673
+ this.id = _TracingSpan.nextId++;
674
+ this.methodName = params.methodName;
675
+ this.resourceId = _traceProcessor.getResourceId(params.instance);
676
+ this.startTs = performance.now();
677
+ this._showInBrowserTimeline = params.showInBrowserTimeline;
678
+ this.op = params.op;
679
+ this.attributes = params.attributes ?? {};
680
+ if (params.parentCtx) {
681
+ this._ctx = params.parentCtx.derive({
682
+ attributes: {
683
+ [TRACE_SPAN_ATTRIBUTE]: this.id
684
+ }
685
+ });
686
+ const parentId = params.parentCtx.getAttribute(TRACE_SPAN_ATTRIBUTE);
687
+ if (typeof parentId === "number") {
688
+ this.parentId = parentId;
689
+ }
690
+ }
691
+ }
692
+ get name() {
693
+ const resource2 = this._traceProcessor.resources.get(this.resourceId);
694
+ return resource2 ? `${resource2.sanitizedClassName}#${resource2.data.instanceId}.${this.methodName}` : this.methodName;
695
+ }
696
+ get ctx() {
697
+ return this._ctx;
698
+ }
699
+ markSuccess() {
700
+ this.endTs = performance.now();
701
+ this._traceProcessor._flushSpan(this);
702
+ if (this._showInBrowserTimeline) {
703
+ this._markInBrowserTimeline();
704
+ }
705
+ }
706
+ markError(err) {
707
+ this.endTs = performance.now();
708
+ this.error = serializeError(err);
709
+ this._traceProcessor._flushSpan(this);
710
+ if (this._showInBrowserTimeline) {
711
+ this._markInBrowserTimeline();
712
+ }
713
+ }
714
+ serialize() {
715
+ return {
716
+ id: this.id,
717
+ resourceId: this.resourceId ?? void 0,
718
+ methodName: this.methodName,
719
+ parentId: this.parentId ?? void 0,
720
+ startTs: this.startTs.toFixed(3),
721
+ endTs: this.endTs?.toFixed(3) ?? void 0,
722
+ error: this.error ?? void 0
723
+ };
724
+ }
725
+ _markInBrowserTimeline() {
726
+ if (typeof globalThis?.performance?.measure === "function") {
727
+ performance.measure(this.name, {
728
+ start: this.startTs,
729
+ end: this.endTs
730
+ });
731
+ }
732
+ }
733
+ };
734
+ var serializeError = (err) => {
735
+ if (err instanceof Error) {
736
+ return {
737
+ name: err.name,
738
+ message: err.message
739
+ };
740
+ }
741
+ return {
742
+ message: String(err)
743
+ };
744
+ };
745
+ var TRACE_PROCESSOR = globalThis.TRACE_PROCESSOR ??= new TraceProcessor();
746
+ var sanitizeValue = (value, depth, traceProcessor) => {
747
+ switch (typeof value) {
748
+ case "string":
749
+ case "number":
750
+ case "boolean":
751
+ case "undefined":
752
+ return value;
753
+ case "object":
754
+ case "function":
755
+ if (value === null) {
756
+ return value;
757
+ }
758
+ {
759
+ const resourceEntry = traceProcessor.resourceInstanceIndex.get(value);
760
+ if (resourceEntry) {
761
+ return `${resourceEntry.sanitizedClassName}#${resourceEntry.data.instanceId}`;
762
+ }
763
+ }
764
+ if (typeof value.toJSON === "function") {
765
+ return sanitizeValue(value.toJSON(), depth, traceProcessor);
766
+ }
767
+ if (depth > 0) {
768
+ if (isSetLike(value)) {
769
+ return Object.fromEntries(Array.from(value.entries()).map((value2) => sanitizeValue(value2, depth - 1, traceProcessor)));
770
+ } else if (isMapLike(value)) {
771
+ return Object.fromEntries(Array.from(value.entries()).map(([key, value2]) => [
772
+ key,
773
+ sanitizeValue(value2, depth - 1, traceProcessor)
774
+ ]));
775
+ } else if (Array.isArray(value)) {
776
+ return value.map((item) => sanitizeValue(item, depth - 1, traceProcessor));
777
+ } else if (typeof value === "object") {
778
+ const res = {};
779
+ for (const key of Object.keys(value)) {
780
+ res[key] = sanitizeValue(value[key], depth - 1, traceProcessor);
781
+ }
782
+ return res;
783
+ }
784
+ }
785
+ if (typeof value.truncate === "function") {
786
+ return value.truncate();
787
+ }
788
+ return value.toString();
789
+ }
790
+ };
791
+ var areEqualShallow = (a, b) => {
792
+ for (const key in a) {
793
+ if (!(key in b) || a[key] !== b[key]) {
794
+ return false;
795
+ }
796
+ }
797
+ for (const key in b) {
798
+ if (!(key in a) || a[key] !== b[key]) {
799
+ return false;
800
+ }
801
+ }
802
+ return true;
803
+ };
804
+ var sanitizeClassName = (className) => {
805
+ const SANITIZE_REGEX = /[^_](\d+)$/;
806
+ const m = className.match(SANITIZE_REGEX);
807
+ if (!m) {
808
+ return className;
809
+ } else {
810
+ return className.slice(0, -m[1].length);
811
+ }
812
+ };
813
+ var isSetLike = (value) => value instanceof Set || typeof value === "object" && value !== null && Object.getPrototypeOf(value).constructor.name === "ComplexSet";
814
+ var isMapLike = (value) => value instanceof Map || typeof value === "object" && value !== null && Object.getPrototypeOf(value).constructor.name === "ComplexMap";
815
+
816
+ // packages/common/tracing/src/api.ts
817
+ var resource = (options) => (constructor) => {
818
+ const klass = /* @__PURE__ */ (() => class extends constructor {
819
+ constructor(...rest) {
820
+ super(...rest);
821
+ TRACE_PROCESSOR.createTraceResource({
822
+ constructor,
823
+ annotation: options?.annotation,
824
+ instance: this
825
+ });
826
+ }
827
+ })();
828
+ Object.defineProperty(klass, "name", {
829
+ value: constructor.name
830
+ });
831
+ return klass;
832
+ };
833
+ var info = (opts = {}) => (target, propertyKey, descriptor) => {
834
+ getTracingContext(target).infoProperties[propertyKey] = {
835
+ options: opts
836
+ };
837
+ };
838
+ var mark = (name) => {
839
+ performance.mark(name);
840
+ };
841
+ var span = ({ showInBrowserTimeline = false, op, attributes } = {}) => (target, propertyKey, descriptor) => {
842
+ const method = descriptor.value;
843
+ descriptor.value = async function(...args) {
844
+ const parentCtx = args[0] instanceof Context2 ? args[0] : null;
845
+ const span2 = TRACE_PROCESSOR.traceSpan({
846
+ parentCtx,
847
+ methodName: propertyKey,
848
+ instance: this,
849
+ showInBrowserTimeline,
850
+ op,
851
+ attributes
852
+ });
853
+ const callArgs = span2.ctx ? [
854
+ span2.ctx,
855
+ ...args.slice(1)
856
+ ] : args;
857
+ try {
858
+ return await method.apply(this, callArgs);
859
+ } catch (err) {
860
+ span2.markError(err);
861
+ throw err;
862
+ } finally {
863
+ span2.markSuccess();
864
+ }
865
+ };
866
+ };
867
+ var metricsCounter = () => (target, propertyKey, descriptor) => {
868
+ getTracingContext(target).metricsProperties[propertyKey] = {};
869
+ };
870
+ var addLink = (parent, child, opts = {}) => {
871
+ TRACE_PROCESSOR.addLink(parent, child, opts);
872
+ };
873
+ var diagnostic = (params) => {
874
+ return TRACE_PROCESSOR.diagnostics.registerDiagnostic(params);
875
+ };
876
+ var trace = {
877
+ addLink,
878
+ diagnostic,
879
+ info,
880
+ mark,
881
+ metricsCounter,
882
+ resource,
883
+ span,
884
+ metrics: TRACE_PROCESSOR.remoteMetrics
885
+ };
886
+
887
+ // packages/common/tracing/src/metrics/base.ts
888
+ var BaseCounter = class {
889
+ /**
890
+ * @internal
891
+ */
892
+ _assign(instance, name) {
893
+ this._instance = instance;
894
+ this.name = name;
895
+ }
896
+ _tick(time) {
897
+ }
898
+ };
899
+
900
+ // packages/common/tracing/src/metrics/unary-counter.ts
901
+ var UnaryCounter = class extends BaseCounter {
902
+ constructor({ units } = {}) {
903
+ super();
904
+ this.value = 0;
905
+ this.units = units;
906
+ }
907
+ inc(by = 1) {
908
+ this.value += by;
909
+ }
910
+ getData() {
911
+ return {
912
+ name: this.name,
913
+ counter: {
914
+ value: this.value,
915
+ units: this.units
916
+ }
917
+ };
918
+ }
919
+ };
920
+
921
+ // packages/common/tracing/src/metrics/time-series-counter.ts
922
+ var MAX_BUCKETS = 60;
923
+ var TimeSeriesCounter = class extends BaseCounter {
924
+ constructor({ units } = {}) {
925
+ super();
926
+ this._currentValue = 0;
927
+ this._totalValue = 0;
928
+ this._buckets = [];
929
+ this.units = units;
930
+ }
931
+ inc(by = 1) {
932
+ this._currentValue += by;
933
+ this._totalValue += by;
934
+ }
935
+ _tick(time) {
936
+ this._buckets.push(this._currentValue);
937
+ if (this._buckets.length > MAX_BUCKETS) {
938
+ this._buckets.shift();
939
+ }
940
+ this._currentValue = 0;
941
+ }
942
+ getData() {
943
+ return {
944
+ name: this.name,
945
+ timeSeries: {
946
+ tracks: [
947
+ {
948
+ name: this.name,
949
+ units: this.units,
950
+ points: this._buckets.map((value, index) => ({
951
+ value
952
+ })),
953
+ total: this._totalValue
954
+ }
955
+ ]
956
+ }
957
+ };
958
+ }
959
+ };
960
+
961
+ // packages/common/tracing/src/metrics/time-usage-counter.ts
962
+ var MAX_BUCKETS2 = 60;
963
+ var TimeUsageCounter = class extends BaseCounter {
964
+ constructor() {
965
+ super(...arguments);
966
+ this._currentValue = 0;
967
+ this._totalValue = 0;
968
+ this._buckets = [];
969
+ this._lastTickTime = performance.now();
970
+ }
971
+ record(time) {
972
+ this._currentValue += time;
973
+ this._totalValue += time;
974
+ }
975
+ beginRecording() {
976
+ const start = performance.now();
977
+ return {
978
+ end: () => {
979
+ const end = performance.now();
980
+ this.record(end - start);
981
+ }
982
+ };
983
+ }
984
+ _tick(time) {
985
+ const delta = time - this._lastTickTime;
986
+ this._lastTickTime = time;
987
+ const percentage = this._currentValue / delta * 100;
988
+ this._buckets.push(percentage);
989
+ if (this._buckets.length > MAX_BUCKETS2) {
990
+ this._buckets.shift();
991
+ }
992
+ this._currentValue = 0;
993
+ }
994
+ getData() {
995
+ return {
996
+ name: this.name,
997
+ timeSeries: {
998
+ tracks: [
999
+ {
1000
+ name: this.name,
1001
+ units: "%",
1002
+ points: this._buckets.map((value, index) => ({
1003
+ value
1004
+ })),
1005
+ total: this._totalValue
1006
+ }
1007
+ ]
1008
+ }
1009
+ };
1010
+ }
1011
+ };
1012
+
1013
+ // packages/common/tracing/src/metrics/map-counter.ts
1014
+ var MapCounter = class extends BaseCounter {
1015
+ constructor({ units } = {}) {
1016
+ super();
1017
+ this.values = /* @__PURE__ */ new Map();
1018
+ this.units = units;
1019
+ }
1020
+ inc(key, by = 1) {
1021
+ const prev = this.values.get(key) ?? 0;
1022
+ this.values.set(key, prev + by);
1023
+ }
1024
+ getData() {
1025
+ return {
1026
+ name: this.name,
1027
+ multiCounter: {
1028
+ records: Array.from(this.values.entries()).map(([key, value]) => ({
1029
+ key,
1030
+ value
1031
+ })),
1032
+ units: this.units
1033
+ }
1034
+ };
1035
+ }
1036
+ };
1037
+
1038
+ // packages/common/tracing/src/metrics/custom-counter.ts
1039
+ var CustomCounter = class extends BaseCounter {
1040
+ constructor(_getData) {
1041
+ super();
1042
+ this._getData = _getData;
1043
+ }
1044
+ getData() {
1045
+ return {
1046
+ name: this.name,
1047
+ custom: {
1048
+ payload: this._getData()
1049
+ }
1050
+ };
1051
+ }
1052
+ };
1053
+
1054
+ // packages/common/tracing/src/index.ts
1055
+ trace.diagnostic({
1056
+ id: "process-info",
1057
+ name: "Process Info",
1058
+ fetch: async () => {
1059
+ return {
1060
+ platform: globalThis.process?.platform,
1061
+ arch: globalThis.process?.arch,
1062
+ versions: globalThis.process?.versions,
1063
+ href: globalThis.location?.href
1064
+ };
1065
+ }
1066
+ });
1067
+ export {
1068
+ BaseCounter,
1069
+ CustomCounter,
1070
+ DIAGNOSTICS_TIMEOUT,
1071
+ DiagnosticsChannel,
1072
+ DiagnosticsManager,
1073
+ MapCounter,
1074
+ RemoteMetrics,
1075
+ RemoteTracing,
1076
+ ResourceEntry,
1077
+ TRACE_PROCESSOR,
1078
+ TRACE_SPAN_ATTRIBUTE,
1079
+ TimeSeriesCounter,
1080
+ TimeUsageCounter,
1081
+ TraceDiagnosticImpl,
1082
+ TraceProcessor,
1083
+ TraceSender,
1084
+ TracingSpan,
1085
+ UnaryCounter,
1086
+ getTracingContext,
1087
+ sanitizeClassName,
1088
+ symbolTracingContext,
1089
+ trace
1090
+ };
1091
+ //# sourceMappingURL=index.mjs.map