@dxos/tracing 0.5.5 → 0.5.6-main.04fedb4

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,55 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export interface MetricData {
6
+ unit?: string;
7
+ tags?: Record<string, string>;
8
+ timestamp?: number;
9
+ }
10
+
11
+ interface MetricsMethods {
12
+ /**
13
+ * Adds a value to a counter metric
14
+ */
15
+ increment(name: string, value?: number, data?: MetricData): void;
16
+ /**
17
+ * Adds a value to a distribution metric
18
+ */
19
+ distribution(name: string, value: number, data?: MetricData): void;
20
+ /**
21
+ * Adds a value to a set metric. Value must be a string or integer.
22
+ */
23
+ set(name: string, value: number | string, data?: MetricData): void;
24
+ /**
25
+ * Adds a value to a gauge metric
26
+ */
27
+ gauge(name: string, value: number, data?: MetricData): void;
28
+ }
29
+
30
+ /**
31
+ * Allows metrics to be recorded within SDK code without requiring specific consumers.
32
+ */
33
+ export class RemoteMetrics implements MetricsMethods {
34
+ private _metrics = new Set<MetricsMethods>();
35
+
36
+ async registerProcessor(processor: MetricsMethods) {
37
+ this._metrics.add(processor);
38
+ }
39
+
40
+ increment(name: string, value?: number, data?: MetricData) {
41
+ return Array.from(this._metrics.values()).map((processor) => processor.increment(name, value, data));
42
+ }
43
+
44
+ distribution(name: string, value: number, data?: MetricData) {
45
+ return Array.from(this._metrics.values()).map((processor) => processor.distribution(name, value, data));
46
+ }
47
+
48
+ set(name: string, value: number | string, data?: MetricData) {
49
+ return Array.from(this._metrics.values()).map((processor) => processor.set(name, value, data));
50
+ }
51
+
52
+ gauge(name: string, value: number, data?: MetricData) {
53
+ return Array.from(this._metrics.values()).map((processor) => processor.gauge(name, value, data));
54
+ }
55
+ }
@@ -0,0 +1,53 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { type TracingSpan } from '../trace-processor';
6
+
7
+ type RemoteSpan = {
8
+ end: () => void;
9
+ };
10
+
11
+ type StartSpanOptions = {
12
+ name: string;
13
+ op?: string;
14
+ attributes?: Record<string, any>;
15
+ };
16
+
17
+ interface TracingMethods {
18
+ startSpan: (options: StartSpanOptions) => RemoteSpan;
19
+ }
20
+
21
+ /**
22
+ * Allows traces to be recorded within SDK code without requiring specific consumers.
23
+ */
24
+ // TODO(wittjosiah): Should probably just use otel. Use `any` for now to not depend on Sentry directly.
25
+ export class RemoteTracing {
26
+ private _tracing: TracingMethods | undefined;
27
+ private _spanMap = new Map<TracingSpan, RemoteSpan>();
28
+
29
+ async registerProcessor(processor: TracingMethods) {
30
+ this._tracing = processor;
31
+ }
32
+
33
+ flushSpan(span: TracingSpan) {
34
+ if (!this._tracing) {
35
+ return;
36
+ }
37
+
38
+ if (!span.endTs) {
39
+ const remoteSpan = this._tracing.startSpan({
40
+ name: span.methodName,
41
+ op: span.op ?? 'function',
42
+ attributes: span.attributes,
43
+ });
44
+ this._spanMap.set(span, remoteSpan);
45
+ } else {
46
+ const remoteSpan = this._spanMap.get(span);
47
+ if (remoteSpan) {
48
+ remoteSpan.end();
49
+ this._spanMap.delete(span);
50
+ }
51
+ }
52
+ }
53
+ }
@@ -14,6 +14,7 @@ import type { AddLinkOptions } from './api';
14
14
  import { DiagnosticsManager } from './diagnostic';
15
15
  import { DiagnosticsChannel } from './diagnostics-channel';
16
16
  import { type BaseCounter } from './metrics';
17
+ import { RemoteMetrics, RemoteTracing } from './remote';
17
18
  import { TRACE_SPAN_ATTRIBUTE, getTracingContext } from './symbols';
18
19
  import { TraceSender } from './trace-sender';
19
20
 
@@ -31,9 +32,12 @@ export type TraceResourceConstructorParams = {
31
32
 
32
33
  export type TraceSpanParams = {
33
34
  instance: any;
35
+ // TODO(wittjosiah): Rename to `name`.
34
36
  methodName: string;
35
37
  parentCtx: Context | null;
36
38
  showInBrowserTimeline: boolean;
39
+ op?: string;
40
+ attributes?: Record<string, any>;
37
41
  };
38
42
 
39
43
  export class ResourceEntry {
@@ -76,6 +80,8 @@ const MAX_INFO_OBJECT_DEPTH = 8;
76
80
  export class TraceProcessor {
77
81
  public readonly diagnostics = new DiagnosticsManager();
78
82
  public readonly diagnosticsChannel = new DiagnosticsChannel();
83
+ public readonly remoteMetrics = new RemoteMetrics();
84
+ public readonly remoteTracing = new RemoteTracing();
79
85
 
80
86
  readonly subscriptions: Set<TraceSubscription> = new Set();
81
87
 
@@ -272,6 +278,7 @@ export class TraceProcessor {
272
278
  this._clearSpans();
273
279
  }
274
280
  this._markSpanDirty(span.id);
281
+ this.remoteTracing.flushSpan(runtimeSpan);
275
282
  }
276
283
 
277
284
  private _markResourceDirty(id: number) {
@@ -355,6 +362,8 @@ export class TracingSpan {
355
362
  readonly parentId: number | null = null;
356
363
  readonly methodName: string;
357
364
  readonly resourceId: number | null = null;
365
+ readonly op: string | undefined;
366
+ readonly attributes: Record<string, any>;
358
367
  startTs: number;
359
368
  endTs: number | null = null;
360
369
  error: SerializedError | null = null;
@@ -371,6 +380,8 @@ export class TracingSpan {
371
380
  this.resourceId = _traceProcessor.getResourceId(params.instance);
372
381
  this.startTs = performance.now();
373
382
  this._showInBrowserTimeline = params.showInBrowserTimeline;
383
+ this.op = params.op;
384
+ this.attributes = params.attributes ?? {};
374
385
 
375
386
  if (params.parentCtx) {
376
387
  this._ctx = params.parentCtx.derive({