@dxos/tracing 0.9.1-main.c7dcc2e112 → 0.9.1-staging.ee54ba693a
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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/api.ts", "../../../src/symbols.ts", "../../../src/trace-processor.ts", "../../../src/buffering-backend.ts", "../../../src/diagnostic.ts", "../../../src/util.ts", "../../../src/diagnostics-channel.ts", "../../../src/remote/metrics.ts", "../../../src/weak-ref.ts", "../../../src/metrics/base.ts", "../../../src/metrics/unary-counter.ts", "../../../src/metrics/time-series-counter.ts", "../../../src/metrics/time-usage-counter.ts", "../../../src/metrics/map-counter.ts", "../../../src/metrics/custom-counter.ts", "../../../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { Context, LifecycleState, Resource, TRACE_SPAN_ATTRIBUTE } from '@dxos/context';\nimport { type MaybePromise } from '@dxos/util';\n\nimport { getTracingContext } from './symbols';\nimport { TRACE_PROCESSOR, sanitizeClassName } from './trace-processor';\nimport type { RemoteSpan } from './tracing-types';\n\nconst LIFECYCLE_SPAN = Symbol('dxos.tracing.lifecycle-span');\n\n/** localStorage key that switches the browser OTEL sampler from 30% to 100%. */\nexport const TRACE_ALL_KEY = 'dxos.debug.traceAll';\n\n/**\n * Reads `@trace.info({ spanAttribute: true })` properties from the instance\n * and writes them into the span attributes map.\n */\nconst collectSpanAttributes = (instance: any, spanAttributes: Record<string, any>) => {\n const proto = Object.getPrototypeOf(instance);\n if (!proto) {\n return;\n }\n const tracingContext = getTracingContext(proto);\n for (const [key, { options }] of Object.entries(tracingContext.infoProperties)) {\n if (!options.spanAttribute) {\n continue;\n }\n try {\n const value = typeof instance[key] === 'function' ? instance[key]() : instance[key];\n if (value != null) {\n const resolved = options.enum ? options.enum[value] : String(value);\n spanAttributes[`ctx.${key}`] = resolved;\n }\n } catch {\n // Skip properties that throw (e.g. uninitialized).\n }\n }\n};\n\nexport type ResourceOptions = {\n annotation?: symbol;\n /**\n * Start a lifecycle span on `open()` and end it on `close()`.\n * `this._ctx` carries the lifecycle span's trace context, so background work\n * (subscriptions, timers) becomes children of the lifecycle span.\n * Direct calls within `_open` use the `_open` span's context as usual.\n * Requires the class to extend {@link Resource}.\n */\n lifecycle?: boolean;\n};\n\n/**\n * Annotates a class as a tracked resource.\n */\nconst resource =\n (options?: ResourceOptions) =>\n <T extends { new (...args: any[]): {} }>(constructor: T) => {\n if (options?.lifecycle && !(constructor.prototype instanceof Resource)) {\n throw new Error(`@trace.resource({ lifecycle: true }) requires ${constructor.name} to extend Resource`);\n }\n\n const klass = (() =>\n class extends constructor {\n constructor(...rest: any[]) {\n super(...rest);\n TRACE_PROCESSOR.createTraceResource({ constructor, annotation: options?.annotation, instance: this });\n }\n })();\n\n if (options?.lifecycle) {\n const sanitizedName = sanitizeClassName(constructor.name);\n const proto = klass.prototype as any;\n const originalOpen = proto.open;\n const originalClose = proto.close;\n\n proto.open = async function (ctx?: Context): Promise<any> {\n const self = this as any;\n\n if (self._lifecycleState !== LifecycleState.CLOSED) {\n return originalOpen.call(this, ctx);\n }\n\n const parentSpanContext = ctx?.getAttribute(TRACE_SPAN_ATTRIBUTE);\n const resourceEntry = TRACE_PROCESSOR.resourceInstanceIndex.get(this);\n const spanAttributes: Record<string, any> = {};\n if (resourceEntry) {\n spanAttributes.entryPoint = resourceEntry.sanitizedClassName;\n }\n\n const remoteSpan = TRACE_PROCESSOR.tracingBackend?.startSpan({\n name: `${sanitizedName}.lifecycle`,\n op: 'lifecycle',\n attributes: spanAttributes,\n parentContext: parentSpanContext,\n });\n self[LIFECYCLE_SPAN] = remoteSpan;\n\n let openCtx = ctx;\n if (remoteSpan?.spanContext != null) {\n const traceAttrs = { [TRACE_SPAN_ATTRIBUTE]: remoteSpan.spanContext };\n openCtx = ctx ? ctx.derive({ attributes: traceAttrs }) : new Context({ attributes: traceAttrs });\n }\n\n try {\n return await originalOpen.call(this, openCtx);\n } catch (err) {\n remoteSpan?.setError?.(err);\n remoteSpan?.end();\n self[LIFECYCLE_SPAN] = undefined;\n throw err;\n }\n };\n\n proto.close = async function (ctx?: Context): Promise<any> {\n const self = this as any;\n const remoteSpan: RemoteSpan | undefined = self[LIFECYCLE_SPAN];\n try {\n return await originalClose.call(this, ctx);\n } catch (err) {\n remoteSpan?.setError?.(err);\n throw err;\n } finally {\n if (remoteSpan) {\n remoteSpan.end();\n self[LIFECYCLE_SPAN] = undefined;\n }\n }\n };\n }\n\n Object.defineProperty(klass, 'name', { value: constructor.name });\n return klass;\n };\n\nexport interface TimeAware {\n tick(timeMs: number): void;\n}\n\nexport type InfoOptions = {\n /**\n * Value is of enum type and should be converted to string.\n *\n * Example:\n *\n * ```ts\n * @trace.info({ enum: SpaceState })\n * get state(): SpaceState { ... }\n * ```\n */\n enum?: Record<string, any>;\n\n /**\n * Max depth of the object to be included in the resource info section.\n *\n * null means no limit (a limit of 8 nested objects is still imposed).\n *\n * Default: 0 - objects will be stringified with toString.\n */\n depth?: number | null;\n\n /** When true, the property value is also set as an OTEL span attribute on every span created by this resource. */\n spanAttribute?: boolean;\n};\n\n/**\n * Marks a property or a method to be included in the resource info section.\n */\nconst info =\n (opts: InfoOptions = {}) =>\n (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => {\n getTracingContext(target).infoProperties[propertyKey] = { options: opts };\n };\n\nconst mark = (name: string) => {\n performance.mark(name);\n};\n\nexport type SpanOptions = {\n showInBrowserTimeline?: boolean;\n /** When false the span is not exported to remote OTLP collectors. Defaults to true. */\n showInRemoteTracing?: boolean;\n op?: string;\n attributes?: Record<string, any>;\n};\n\n/**\n * Decorator that creates a span for the execution duration of the decorated method.\n * Calls the TracingBackend directly; no custom TracingSpan objects.\n */\nconst span =\n ({ showInBrowserTimeline = false, showInRemoteTracing = true, op, attributes }: SpanOptions = {}) =>\n (target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<(...args: any) => any>) => {\n const method = descriptor.value!;\n\n descriptor.value = async function (this: any, ...args: any) {\n const parentCtx = args[0] instanceof Context ? args[0] : null;\n const startTs = performance.now();\n\n const parentSpanContext = parentCtx?.getAttribute(TRACE_SPAN_ATTRIBUTE);\n\n const resourceEntry = TRACE_PROCESSOR.resourceInstanceIndex.get(this);\n const className = resourceEntry?.sanitizedClassName ?? sanitizeClassName(target.constructor?.name ?? 'unknown');\n const spanName = `${className}.${propertyKey}`;\n\n const spanAttributes: Record<string, any> = {};\n if (resourceEntry) {\n spanAttributes.entryPoint = resourceEntry.sanitizedClassName;\n }\n collectSpanAttributes(this, spanAttributes);\n if (attributes) {\n for (const [key, value] of Object.entries(attributes)) {\n spanAttributes[key.startsWith('ctx.') ? key : `ctx.${key}`] = value;\n }\n }\n\n const remoteSpan = showInRemoteTracing\n ? TRACE_PROCESSOR.tracingBackend?.startSpan({\n name: spanName,\n op: op ?? 'function',\n attributes: spanAttributes,\n parentContext: parentSpanContext,\n })\n : undefined;\n\n let callArgs = args;\n if (parentCtx) {\n const childCtx =\n remoteSpan?.spanContext != null\n ? parentCtx.derive({ attributes: { [TRACE_SPAN_ATTRIBUTE]: remoteSpan.spanContext } })\n : parentCtx.derive();\n callArgs = [childCtx, ...args.slice(1)];\n }\n\n try {\n return await method.apply(this, callArgs);\n } catch (err) {\n remoteSpan?.setError?.(err);\n throw err;\n } finally {\n remoteSpan?.end();\n if (showInBrowserTimeline && typeof globalThis?.performance?.measure === 'function') {\n performance.measure(spanName, { start: startTs, end: performance.now() });\n }\n }\n };\n };\n\nconst manualSpans = new Map<string, RemoteSpan>();\nconst manualSpanTimestamps = new Map<string, { name: string; startTs: number }>();\n\nexport type ManualSpanParams = {\n id: string;\n instance: any;\n methodName: string;\n parentCtx: Context | null;\n showInBrowserTimeline?: boolean;\n showInRemoteTracing?: boolean;\n op?: string;\n attributes?: Record<string, any>;\n};\n\n/**\n * Creates a span that must be ended manually.\n *\n * Returns a child Context that carries the new span's `TRACE_SPAN_ATTRIBUTE`.\n * Callers should use the returned ctx for downstream work so that nested\n * `@trace.span` methods and RPC calls inherit this span as their parent\n * and land in the same trace (rather than starting a new root).\n *\n * When the new span cannot be created (duplicate id, no backend, or\n * `showInRemoteTracing: false`), the parentCtx is returned unchanged.\n */\nconst spanStart = (params: ManualSpanParams): Context | null => {\n if (manualSpans.has(params.id) || manualSpanTimestamps.has(params.id)) {\n return params.parentCtx;\n }\n\n const resourceEntry = TRACE_PROCESSOR.resourceInstanceIndex.get(params.instance);\n const className = resourceEntry?.sanitizedClassName ?? 'unknown';\n const spanName = `${className}.${params.methodName}`;\n\n if (params.showInBrowserTimeline) {\n manualSpanTimestamps.set(params.id, { name: spanName, startTs: performance.now() });\n }\n\n if (params.showInRemoteTracing === false || !TRACE_PROCESSOR.tracingBackend) {\n return params.parentCtx;\n }\n\n const parentSpanContext = params.parentCtx?.getAttribute(TRACE_SPAN_ATTRIBUTE);\n\n const spanAttributes: Record<string, any> = {};\n if (resourceEntry) {\n spanAttributes.entryPoint = resourceEntry.sanitizedClassName;\n }\n collectSpanAttributes(params.instance, spanAttributes);\n if (params.attributes) {\n for (const [key, value] of Object.entries(params.attributes)) {\n spanAttributes[key.startsWith('ctx.') ? key : `ctx.${key}`] = value;\n }\n }\n\n const remoteSpan = TRACE_PROCESSOR.tracingBackend.startSpan({\n name: spanName,\n op: params.op ?? 'function',\n attributes: spanAttributes,\n parentContext: parentSpanContext,\n });\n manualSpans.set(params.id, remoteSpan);\n\n if (params.parentCtx && remoteSpan.spanContext != null) {\n return params.parentCtx.derive({ attributes: { [TRACE_SPAN_ATTRIBUTE]: remoteSpan.spanContext } });\n }\n return params.parentCtx;\n};\n\n/**\n * Ends a span that was started manually.\n */\nconst spanEnd = (id: string) => {\n const remoteSpan = manualSpans.get(id);\n if (remoteSpan) {\n remoteSpan.end();\n manualSpans.delete(id);\n }\n\n const timestamps = manualSpanTimestamps.get(id);\n if (timestamps && typeof globalThis?.performance?.measure === 'function') {\n performance.measure(timestamps.name, { start: timestamps.startTs, end: performance.now() });\n manualSpanTimestamps.delete(id);\n }\n};\n\n/**\n * Attaches metrics counter to the resource.\n */\nconst metricsCounter = () => (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => {\n getTracingContext(target).metricsProperties[propertyKey] = {};\n};\n\nexport type AddLinkOptions = {};\n\nconst addLink = (parent: any, child: any, opts: AddLinkOptions = {}) => {\n TRACE_PROCESSOR.addLink(parent, child, opts);\n};\n\nexport type TraceDiagnosticProps<T> = {\n /** Unique ID. */\n id: string;\n\n /**\n * Human-readable name.\n * @defaults Defaults to `id`\n */\n name?: string;\n\n /** Function that will be called to fetch the diagnostic data. */\n fetch: () => MaybePromise<T>;\n};\n\nexport interface TraceDiagnostic {\n id: string;\n unregister(): void;\n}\n\n/**\n * Register a diagnostic that could be queried.\n */\nconst diagnostic = <T>(params: TraceDiagnosticProps<T>): TraceDiagnostic => {\n return TRACE_PROCESSOR.diagnostics.registerDiagnostic(params);\n};\n\nexport const trace = {\n addLink,\n diagnostic,\n info,\n mark,\n metricsCounter,\n resource,\n span,\n spanStart,\n spanEnd,\n metrics: TRACE_PROCESSOR.remoteMetrics,\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type InfoOptions } from './api';\n\nexport const symbolTracingContext = Symbol('dxos.tracing.context');\n\nexport type TracingContext = {\n infoProperties: Record<\n string,\n {\n options: InfoOptions;\n }\n >;\n metricsProperties: Record<string, {}>;\n};\n\nexport const getTracingContext = (target: any): TracingContext => {\n return ((target[symbolTracingContext] as TracingContext | undefined) ??= {\n infoProperties: {},\n metricsProperties: {},\n });\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { LogLevel, type LogProcessor, log } from '@dxos/log';\nimport { type LogEntry } from '@dxos/protocols/proto/dxos/client/services';\nimport { type Metric, type Resource } from '@dxos/protocols/proto/dxos/tracing';\nimport { getPrototypeSpecificInstanceId } from '@dxos/util';\n\nimport type { AddLinkOptions, TimeAware } from './api';\nimport { BUFFERED_PREFIX, BufferingTracingBackend } from './buffering-backend';\nimport { DiagnosticsManager } from './diagnostic';\nimport { DiagnosticsChannel } from './diagnostics-channel';\nimport { type BaseCounter } from './metrics';\nimport { RemoteMetrics } from './remote/metrics';\nimport { getTracingContext } from './symbols';\nimport type { RemoteSpan, StartSpanOptions, TracingBackend } from './tracing-types';\nimport { WeakRef } from './weak-ref';\n\nexport type Diagnostics = {\n resources: Record<string, Resource>;\n logs: LogEntry[];\n};\n\nexport type TraceResourceConstructorProps = {\n constructor: { new (...args: any[]): {} };\n instance: any;\n annotation?: symbol;\n};\n\nexport class ResourceEntry {\n /**\n * Sometimes bundlers mangle class names: WebFile -> WebFile2.\n *\n * We use a heuristic to remove the suffix.\n */\n public readonly sanitizedClassName: string;\n\n constructor(\n public readonly data: Resource,\n public readonly instance: WeakRef<any>,\n public readonly annotation?: symbol,\n ) {\n this.sanitizedClassName = sanitizeClassName(data.className);\n }\n\n getMetric(name: string): Metric | undefined {\n return this.data.metrics?.find((metric) => metric.name === name);\n }\n}\n\nconst MAX_RESOURCE_RECORDS = 2_000;\nconst MAX_LOG_RECORDS = 1_000;\n\nconst MAX_INFO_OBJECT_DEPTH = 8;\n\nexport class TraceProcessor {\n public readonly diagnostics = new DiagnosticsManager();\n public readonly diagnosticsChannel = new DiagnosticsChannel();\n public readonly remoteMetrics = new RemoteMetrics();\n\n readonly #bufferingBackend = new BufferingTracingBackend();\n #activeBackend: TracingBackend = this.#bufferingBackend;\n\n /**\n * Tracing backend. Initially a buffering backend that records spans;\n * once the observability package sets a real backend, the buffer is drained\n * and a thin translating wrapper is installed that resolves stale buffered\n * parent IDs still held by in-flight {@link Context} objects.\n *\n * The wrapper only allocates when a `buffered-*` parent is actually encountered;\n * the common path is a single `startsWith` check and direct passthrough.\n */\n get tracingBackend(): TracingBackend {\n return this.#activeBackend;\n }\n\n set tracingBackend(backend: TracingBackend | undefined) {\n if (!backend || backend === this.#bufferingBackend) {\n this.#bufferingBackend.clear();\n this.#activeBackend = this.#bufferingBackend;\n return;\n }\n const idMap = this.#bufferingBackend.drain(backend);\n this.#activeBackend = {\n startSpan: (options: StartSpanOptions): RemoteSpan => {\n const parent = options.parentContext;\n if (parent?.traceparent.startsWith(BUFFERED_PREFIX)) {\n const translated = idMap.get(parent.traceparent);\n if (translated) {\n return backend.startSpan({ ...options, parentContext: translated });\n }\n }\n return backend.startSpan(options);\n },\n };\n }\n\n readonly resources = new Map<number, ResourceEntry>();\n readonly resourceInstanceIndex = new WeakMap<any, ResourceEntry>();\n readonly resourceIdList: number[] = [];\n\n readonly logs: LogEntry[] = [];\n\n private _instanceTag: string | null = null;\n\n constructor() {\n log.addProcessor(this._logProcessor.bind(this));\n\n if (DiagnosticsChannel.supported) {\n this.diagnosticsChannel.serve(this.diagnostics);\n }\n this.diagnosticsChannel.unref();\n }\n\n setInstanceTag(tag: string): void {\n this._instanceTag = tag;\n this.diagnostics.setInstanceTag(tag);\n }\n\n /** @internal */\n createTraceResource(params: TraceResourceConstructorProps): void {\n const id = this.resources.size;\n\n const tracingContext = getTracingContext(Object.getPrototypeOf(params.instance));\n for (const key of Object.keys(tracingContext.metricsProperties)) {\n (params.instance[key] as BaseCounter)._assign(params.instance, key);\n }\n\n const entry = new ResourceEntry(\n {\n id,\n className: params.constructor.name,\n instanceId: getPrototypeSpecificInstanceId(params.instance),\n info: this.getResourceInfo(params.instance),\n links: [],\n metrics: this.getResourceMetrics(params.instance),\n },\n new WeakRef(params.instance),\n params.annotation,\n );\n\n this.resources.set(id, entry);\n this.resourceInstanceIndex.set(params.instance, entry);\n this.resourceIdList.push(id);\n if (this.resourceIdList.length > MAX_RESOURCE_RECORDS) {\n this._clearResources();\n }\n }\n\n // TODO(burdon): Not implemented.\n addLink(parent: any, child: any, opts: AddLinkOptions): void {}\n\n getDiagnostics(): Diagnostics {\n this.refresh();\n\n return {\n resources: Object.fromEntries(\n Array.from(this.resources.entries()).map(([id, entry]) => [\n `${entry.sanitizedClassName}#${entry.data.instanceId}`,\n entry.data,\n ]),\n ),\n logs: this.logs.filter((log) => log.level >= LogLevel.INFO),\n };\n }\n\n getResourceInfo(instance: any): Record<string, any> {\n const res: Record<string, any> = {};\n const tracingContext = getTracingContext(Object.getPrototypeOf(instance));\n for (const [key, { options }] of Object.entries(tracingContext.infoProperties)) {\n try {\n const value = typeof instance[key] === 'function' ? instance[key]() : instance[key];\n if (options.enum) {\n res[key] = options.enum[value];\n } else {\n res[key] = sanitizeValue(\n value,\n options.depth === undefined ? 1 : (options.depth ?? MAX_INFO_OBJECT_DEPTH),\n this,\n );\n }\n } catch (err: any) {\n res[key] = err.message;\n }\n }\n\n return res;\n }\n\n getResourceMetrics(instance: any): Metric[] {\n const res: Metric[] = [];\n const tracingContext = getTracingContext(Object.getPrototypeOf(instance));\n for (const [key, _opts] of Object.entries(tracingContext.metricsProperties)) {\n res.push(instance[key].getData());\n }\n\n return res;\n }\n\n getResourceId(instance: any): number | null {\n const entry = this.resourceInstanceIndex.get(instance);\n return entry ? entry.data.id : null;\n }\n\n findResourcesByClassName(className: string): ResourceEntry[] {\n return [...this.resources.values()].filter(\n (res) => res.data.className === className || res.sanitizedClassName === className,\n );\n }\n\n findResourcesByAnnotation(annotation: symbol): ResourceEntry[] {\n return [...this.resources.values()].filter((res) => res.annotation === annotation);\n }\n\n refresh(): void {\n for (const resource of this.resources.values()) {\n const instance = resource.instance.deref();\n if (!instance) {\n continue;\n }\n\n const tracingContext = getTracingContext(Object.getPrototypeOf(instance));\n const time = performance.now();\n (instance as TimeAware).tick?.(time);\n for (const key of Object.keys(tracingContext.metricsProperties)) {\n (instance[key] as BaseCounter)._tick?.(time);\n }\n\n resource.data.info = this.getResourceInfo(instance);\n resource.data.metrics = this.getResourceMetrics(instance);\n }\n }\n\n private _clearResources(): void {\n while (this.resourceIdList.length > MAX_RESOURCE_RECORDS) {\n const id = this.resourceIdList.shift()!;\n this.resources.delete(id);\n }\n }\n\n private _pushLog(log: LogEntry): void {\n this.logs.push(log);\n if (this.logs.length > MAX_LOG_RECORDS) {\n this.logs.shift();\n }\n }\n\n private _logProcessor: LogProcessor = (config, entry) => {\n switch (entry.level) {\n case LogLevel.ERROR:\n case LogLevel.WARN:\n case LogLevel.TRACE: {\n const scope = entry.meta?.S;\n const resource = this.resourceInstanceIndex.get(scope);\n if (!resource) {\n return;\n }\n\n const context: Record<string, any> = { ...entry.computedContext };\n if (entry.computedError !== undefined) {\n context.error = entry.computedError;\n }\n\n const { filename, line } = entry.computedMeta;\n const entryToPush: LogEntry = {\n level: entry.level,\n message: entry.message ?? entry.computedError ?? '',\n context,\n timestamp: new Date(entry.timestamp),\n meta: {\n file: filename ?? '',\n line: line ?? 0,\n resourceId: resource.data.id,\n },\n };\n this._pushLog(entryToPush);\n break;\n }\n default:\n }\n };\n}\n\nexport const TRACE_PROCESSOR: TraceProcessor = ((globalThis as any).TRACE_PROCESSOR ??= new TraceProcessor());\n\nconst sanitizeValue = (value: any, depth: number, traceProcessor: TraceProcessor): any => {\n switch (typeof value) {\n case 'string':\n case 'number':\n case 'boolean':\n case 'undefined':\n return value;\n case 'object':\n case 'function':\n if (value === null) {\n return value;\n }\n\n {\n const resourceEntry = traceProcessor.resourceInstanceIndex.get(value);\n if (resourceEntry) {\n return `${resourceEntry.sanitizedClassName}#${resourceEntry.data.instanceId}`;\n }\n }\n\n if (typeof value.toJSON === 'function') {\n return sanitizeValue(value.toJSON(), depth, traceProcessor);\n }\n\n if (depth > 0) {\n if (isSetLike(value)) {\n return Object.fromEntries(\n Array.from(value.entries()).map((value) => sanitizeValue(value, depth - 1, traceProcessor)),\n );\n } else if (isMapLike(value)) {\n return Object.fromEntries(\n Array.from(value.entries()).map(([key, value]) => [key, sanitizeValue(value, depth - 1, traceProcessor)]),\n );\n } else if (Array.isArray(value)) {\n return value.map((item: any) => sanitizeValue(item, depth - 1, traceProcessor));\n } else if (typeof value === 'object') {\n const res: any = {};\n for (const key of Object.keys(value)) {\n res[key] = sanitizeValue(value[key], depth - 1, traceProcessor);\n }\n return res;\n }\n }\n\n if (typeof value.truncate === 'function') {\n return value.truncate();\n }\n\n return value.toString();\n }\n};\n\nexport const sanitizeClassName = (className: string) => {\n let name = className.replace(/^_+/, '');\n const SANITIZE_REGEX = /[^_](\\d+)$/;\n const m = name.match(SANITIZE_REGEX);\n if (m) {\n name = name.slice(0, -m[1].length);\n }\n return name;\n};\n\nconst isSetLike = (value: any): value is Set<any> =>\n value instanceof Set ||\n (typeof value === 'object' && value !== null && Object.getPrototypeOf(value).constructor.name === 'ComplexSet');\n\nconst isMapLike = (value: any): value is Map<any, any> =>\n value instanceof Map ||\n (typeof value === 'object' && value !== null && Object.getPrototypeOf(value).constructor.name === 'ComplexMap');\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { type TraceContextData } from '@dxos/context';\n\nimport type { RemoteSpan, StartSpanOptions, TracingBackend } from './tracing-types';\n\nexport const BUFFERED_PREFIX = 'buffered-';\n\n/**\n * Span handle that records operations while no real OTEL backend is available.\n * Once a real backend is registered, the buffered span is replayed and a\n * {@link delegate} is set so future calls forward to the real span.\n */\nclass BufferedSpan implements RemoteSpan {\n readonly spanContext: TraceContextData;\n readonly startTime: number;\n delegate?: RemoteSpan;\n\n #ended = false;\n #endTime?: number;\n #error?: unknown;\n #hasError = false;\n\n constructor(\n readonly options: StartSpanOptions,\n id: number,\n ) {\n this.spanContext = { traceparent: `${BUFFERED_PREFIX}${id}` };\n this.startTime = Date.now();\n }\n\n end(endTime?: number): void {\n if (this.delegate) {\n this.delegate.end(endTime);\n return;\n }\n this.#endTime = endTime ?? Date.now();\n this.#ended = true;\n }\n\n setError(err: unknown): void {\n if (this.delegate) {\n this.delegate.setError?.(err);\n return;\n }\n this.#error = err;\n this.#hasError = true;\n }\n\n replay(real: RemoteSpan): void {\n if (this.#hasError) {\n real.setError?.(this.#error);\n }\n if (this.#ended) {\n real.end(this.#endTime);\n } else {\n this.delegate = real;\n }\n }\n}\n\n/**\n * A {@link TracingBackend} that buffers span operations until a real backend\n * registers. On {@link drain}, buffered spans are replayed in FIFO order with\n * parent IDs translated from synthetic `buffered-*` traceparents to real OTEL\n * IDs, preserving the trace hierarchy.\n */\nexport class BufferingTracingBackend implements TracingBackend {\n readonly #pending: BufferedSpan[] = [];\n #counter = 0;\n\n startSpan(options: StartSpanOptions): RemoteSpan {\n const span = new BufferedSpan(options, ++this.#counter);\n this.#pending.push(span);\n return span;\n }\n\n /** Discard all buffered spans without replaying them. */\n clear(): void {\n this.#pending.length = 0;\n }\n\n /**\n * Replay all buffered spans into {@link backend}.\n *\n * @returns Map from synthetic buffered traceparent to real {@link TraceContextData},\n * used by the post-drain translating wrapper to resolve stale buffered IDs\n * still present on in-flight {@link Context} objects.\n */\n drain(backend: TracingBackend): Map<string, TraceContextData> {\n const idMap = new Map<string, TraceContextData>();\n\n for (const buffered of this.#pending) {\n let parentContext = buffered.options.parentContext;\n if (parentContext && parentContext.traceparent.startsWith(BUFFERED_PREFIX)) {\n parentContext = idMap.get(parentContext.traceparent) ?? parentContext;\n }\n\n const real = backend.startSpan({ ...buffered.options, parentContext, startTime: buffered.startTime });\n\n if (real.spanContext) {\n idMap.set(buffered.spanContext.traceparent, real.spanContext);\n }\n\n buffered.replay(real);\n }\n this.#pending.length = 0;\n return idMap;\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { asyncTimeout } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\n\nimport { type TraceDiagnostic, type TraceDiagnosticProps } from './api';\nimport { createId } from './util';\n\nexport const DIAGNOSTICS_TIMEOUT = 10_000;\n\nexport type DiagnosticMetadata = {\n id: string;\n instanceId: string;\n instanceTag: string | null;\n name: string;\n};\n\nexport type DiagnosticsRequest = {\n id: string;\n instanceId?: string;\n instanceTag?: string | null;\n};\n\nexport type DiagnosticsData = {\n id: string;\n instanceId: string;\n data: any;\n error?: string;\n};\n\nexport class TraceDiagnosticImpl implements TraceDiagnostic {\n constructor(\n public id: string,\n public fetch: () => any,\n public name: string,\n private readonly _onUnregister: () => void,\n ) {}\n\n unregister(): void {\n this._onUnregister();\n }\n}\n\nexport class DiagnosticsManager {\n readonly instanceId = createId();\n\n readonly registry = new Map<string, TraceDiagnosticImpl>();\n\n private _instanceTag: string | null = null;\n\n get instanceTag(): string | null {\n return this._instanceTag;\n }\n\n setInstanceTag(tag: string): void {\n this._instanceTag = tag;\n }\n\n registerDiagnostic(params: TraceDiagnosticProps<any>): TraceDiagnostic {\n const impl = new TraceDiagnosticImpl(params.id, params.fetch, params.name ?? params.id, () => {\n if (this.registry.get(params.id) === impl) {\n this.registry.delete(params.id);\n }\n });\n this.registry.set(params.id, impl);\n return impl;\n }\n\n list(): DiagnosticMetadata[] {\n return Array.from(this.registry.values()).map((diagnostic) => ({\n id: diagnostic.id,\n instanceId: this.instanceId,\n instanceTag: this._instanceTag,\n name: diagnostic.name,\n }));\n }\n\n async fetch(request: DiagnosticsRequest): Promise<DiagnosticsData> {\n if (request.instanceId != null) {\n invariant(request.instanceId === this.instanceId, 'Invalid instance id');\n }\n const { id } = request;\n const diagnostic = this.registry.get(id);\n invariant(diagnostic, 'Diagnostic not found');\n try {\n const data = await asyncTimeout(diagnostic.fetch(), DIAGNOSTICS_TIMEOUT);\n return {\n id,\n instanceId: this.instanceId,\n data,\n };\n } catch (err: any) {\n return {\n id,\n instanceId: this.instanceId,\n data: null,\n error: err.stack,\n };\n }\n }\n}\n", "// TODO(dmaretskyi): Use UUID.\n//\n// Copyright 2024 DXOS.org\n//\n\nexport const createId = () => Math.random().toString(36).slice(2);\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { Trigger, sleep } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\n\nimport {\n DIAGNOSTICS_TIMEOUT,\n type DiagnosticMetadata,\n type DiagnosticsData,\n type DiagnosticsManager,\n type DiagnosticsRequest,\n} from './diagnostic';\nimport { createId } from './util';\n\nconst DEFAULT_CHANNEL_NAME = 'dxos-diagnostics';\n\nconst DISCOVER_TIME = 500;\n\nexport type DiagnosticChannelMessage =\n | {\n type: 'DIAGNOSTICS_DISCOVER';\n }\n | {\n type: 'DIAGNOSTICS_ANNOUNCE';\n diagnostics: DiagnosticMetadata[];\n }\n | {\n type: 'DIAGNOSTICS_FETCH';\n requestId: string;\n request: DiagnosticsRequest;\n }\n | {\n type: 'DIAGNOSTICS_RESPONSE';\n requestId: string;\n data: DiagnosticsData;\n };\n\nexport class DiagnosticsChannel {\n static get supported() {\n return globalThis.BroadcastChannel != null;\n }\n\n private _ctx = new Context();\n\n // Separate channels becauase the client and server may be in the same process.\n private readonly _serveChannel?: BroadcastChannel = undefined;\n private readonly _clientChannel?: BroadcastChannel = undefined;\n\n constructor(private readonly _channelName: string = DEFAULT_CHANNEL_NAME) {\n if (DiagnosticsChannel.supported) {\n this._serveChannel = new BroadcastChannel(_channelName);\n this._clientChannel = new BroadcastChannel(_channelName);\n }\n }\n\n destroy(): void {\n void this._ctx.dispose();\n this._serveChannel?.close();\n this._clientChannel?.close();\n }\n\n /**\n * In node.js, the channel will keep the process alive.\n * This method allows the process to exit.\n * Noop in the browser.\n */\n unref(): void {\n if (this._serveChannel && typeof (this._serveChannel as any).unref === 'function') {\n (this._serveChannel as any).unref();\n (this._clientChannel as any).unref();\n }\n }\n\n serve(manager: DiagnosticsManager): void {\n invariant(this._serveChannel);\n const listener = async (event: MessageEvent) => {\n switch (event.data.type) {\n case 'DIAGNOSTICS_DISCOVER': {\n const diagnostics = manager.list();\n this._serveChannel!.postMessage({\n type: 'DIAGNOSTICS_ANNOUNCE',\n diagnostics,\n } satisfies DiagnosticChannelMessage);\n break;\n }\n case 'DIAGNOSTICS_FETCH': {\n const { requestId, request } = event.data;\n\n if (request.instanceId != null && request.instanceId !== manager.instanceId) {\n break;\n } else if (request.instanceTag != null && request.instanceTag !== manager.instanceTag) {\n break;\n }\n\n const data = await manager.fetch(request);\n this._serveChannel!.postMessage({\n type: 'DIAGNOSTICS_RESPONSE',\n requestId,\n data,\n } satisfies DiagnosticChannelMessage);\n break;\n }\n }\n };\n\n this._serveChannel.addEventListener('message', listener);\n this._ctx.onDispose(() => this._serveChannel!.removeEventListener('message', listener));\n }\n\n async discover(): Promise<DiagnosticMetadata[]> {\n invariant(this._clientChannel);\n const diagnostics: DiagnosticMetadata[] = [];\n\n const collector = (event: MessageEvent) => {\n const data = event.data as DiagnosticChannelMessage;\n switch (data.type) {\n case 'DIAGNOSTICS_ANNOUNCE':\n diagnostics.push(...data.diagnostics);\n break;\n }\n };\n\n try {\n this._clientChannel.addEventListener('message', collector);\n this._clientChannel.postMessage({ type: 'DIAGNOSTICS_DISCOVER' } satisfies DiagnosticChannelMessage);\n\n await sleep(DISCOVER_TIME);\n\n // Dedup.\n const result: DiagnosticMetadata[] = [];\n for (const diagnostic of diagnostics) {\n if (!result.some((d) => d.id === diagnostic.id && d.instanceId === diagnostic.instanceId)) {\n result.push(diagnostic);\n }\n }\n\n return diagnostics;\n } finally {\n this._clientChannel.removeEventListener('message', collector);\n }\n }\n\n async fetch(request: DiagnosticsRequest): Promise<DiagnosticsData> {\n invariant(this._clientChannel);\n const requestId = createId();\n\n const trigger = new Trigger<DiagnosticsData>();\n const listener = (event: MessageEvent) => {\n const data = event.data as DiagnosticChannelMessage;\n if (data.type === 'DIAGNOSTICS_RESPONSE' && data.requestId === requestId) {\n trigger.wake(data.data);\n }\n };\n\n try {\n this._clientChannel.addEventListener('message', listener);\n this._clientChannel.postMessage({\n type: 'DIAGNOSTICS_FETCH',\n requestId,\n request,\n } satisfies DiagnosticChannelMessage);\n\n // NOTE: Must have await keyword in this block.\n const result = await trigger.wait({ timeout: DIAGNOSTICS_TIMEOUT });\n\n return result;\n } finally {\n this._clientChannel.removeEventListener('message', listener);\n }\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\ntype TagType = number | string | boolean | null | undefined;\n\nexport interface MetricData {\n unit?: string;\n tags?: Record<string, TagType>;\n timestamp?: number;\n}\n\ninterface MetricsMethods {\n /**\n * Adds a value to a counter metric\n */\n increment(name: string, value?: number, data?: MetricData): void;\n /**\n * Adds a value to a distribution metric\n */\n distribution(name: string, value: number, data?: MetricData): void;\n /**\n * Adds a value to a set metric. Value must be a string or integer.\n */\n set(name: string, value: number | string, data?: MetricData): void;\n /**\n * Adds a value to a gauge metric\n */\n gauge(name: string, value: number, data?: MetricData): void;\n}\n\n/**\n * Allows metrics to be recorded within SDK code without requiring specific consumers.\n */\nexport class RemoteMetrics implements MetricsMethods {\n private _metrics = new Set<MetricsMethods>();\n\n registerProcessor(processor: MetricsMethods): void {\n this._metrics.add(processor);\n }\n\n increment(name: string, value?: number, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.increment(name, value, data));\n }\n\n distribution(name: string, value: number, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.distribution(name, value, data));\n }\n\n set(name: string, value: number | string, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.set(name, value, data));\n }\n\n gauge(name: string, value: number, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.gauge(name, value, data));\n }\n}\n", "// Workerd does not support WeakRef\n\n//\n// Copyright 2024 DXOS.org\n//\n\nclass WeakRefMock<T> {\n // eslint-disable-next-line @typescript-eslint/no-useless-constructor\n constructor(target: T) {\n // do nothing\n }\n\n deref(): T | undefined {\n return undefined;\n }\n}\n\nexport const WeakRef = globalThis.WeakRef ?? WeakRefMock;\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nexport abstract class BaseCounter {\n /**\n * @internal\n */\n _instance: any;\n\n name?: string;\n\n /**\n * @internal\n */\n _assign(instance: any, name: string): void {\n this._instance = instance;\n this.name = name;\n }\n\n abstract getData(): Metric;\n\n _tick(time: number): void {}\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nexport class UnaryCounter extends BaseCounter {\n value = 0;\n units?: string;\n\n constructor({ units }: { units?: string } = {}) {\n super();\n this.units = units;\n }\n\n inc(by = 1): void {\n this.value += by;\n }\n\n getData(): Metric {\n return {\n name: this.name!,\n counter: {\n value: this.value,\n units: this.units,\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nconst MAX_BUCKETS = 60;\n\nexport class TimeSeriesCounter extends BaseCounter {\n private _currentValue = 0;\n private _totalValue = 0;\n private _buckets: number[] = [];\n units?: string;\n\n constructor({ units }: { units?: string } = {}) {\n super();\n this.units = units;\n }\n\n inc(by = 1): void {\n this._currentValue += by;\n this._totalValue += by;\n }\n\n override _tick(time: number): void {\n this._buckets.push(this._currentValue);\n if (this._buckets.length > MAX_BUCKETS) {\n this._buckets.shift();\n }\n this._currentValue = 0;\n }\n\n override getData(): Metric {\n return {\n name: this.name!,\n timeSeries: {\n tracks: [\n {\n name: this.name!,\n units: this.units,\n points: this._buckets.map((value, index) => ({\n value,\n })),\n total: this._totalValue,\n },\n ],\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nconst MAX_BUCKETS = 60;\n\nexport class TimeUsageCounter extends BaseCounter {\n private _currentValue = 0;\n private _totalValue = 0;\n private _buckets: number[] = [];\n\n private _lastTickTime = performance.now();\n\n record(time: number): void {\n this._currentValue += time;\n this._totalValue += time;\n }\n\n beginRecording(): { end: () => void } {\n const start = performance.now();\n return {\n end: () => {\n const end = performance.now();\n this.record(end - start);\n },\n };\n }\n\n override _tick(time: number): void {\n const delta = time - this._lastTickTime;\n this._lastTickTime = time;\n\n const percentage = (this._currentValue / delta) * 100;\n this._buckets.push(percentage);\n if (this._buckets.length > MAX_BUCKETS) {\n this._buckets.shift();\n }\n this._currentValue = 0;\n }\n\n override getData(): Metric {\n return {\n name: this.name!,\n timeSeries: {\n tracks: [\n {\n name: this.name!,\n units: '%',\n points: this._buckets.map((value, index) => ({\n value,\n })),\n total: this._totalValue,\n },\n ],\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nexport class MapCounter extends BaseCounter {\n values = new Map<string, number>();\n units?: string;\n\n constructor({ units }: { units?: string } = {}) {\n super();\n this.units = units;\n }\n\n inc(key: string, by = 1): void {\n const prev = this.values.get(key) ?? 0;\n this.values.set(key, prev + by);\n }\n\n getData(): Metric {\n return {\n name: this.name!,\n multiCounter: {\n records: Array.from(this.values.entries()).map(([key, value]) => ({\n key,\n value,\n })),\n units: this.units,\n },\n };\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nexport class CustomCounter extends BaseCounter {\n constructor(private readonly _getData: () => object) {\n super();\n }\n\n override getData(): Metric {\n return {\n name: this.name!,\n custom: {\n payload: this._getData(),\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { trace } from './api';\n\nexport * from './api';\nexport * from './symbols';\nexport * from './trace-processor';\nexport * from './tracing-types';\nexport * from './metrics';\nexport * from './diagnostic';\nexport * from './diagnostics-channel';\nexport * from './remote/metrics';\n\ntrace.diagnostic({\n id: 'process-info',\n name: 'Process Info',\n fetch: async () => {\n return {\n platform: globalThis.process?.platform,\n arch: globalThis.process?.arch,\n versions: globalThis.process?.versions,\n href: globalThis.location?.href,\n };\n },\n});\n"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { Context, LifecycleState, Resource, TRACE_SPAN_ATTRIBUTE } from '@dxos/context';\nimport { type MaybePromise } from '@dxos/util';\n\nimport { getTracingContext } from './symbols';\nimport { TRACE_PROCESSOR, sanitizeClassName } from './trace-processor';\nimport type { RemoteSpan } from './tracing-types';\n\nconst LIFECYCLE_SPAN = Symbol('dxos.tracing.lifecycle-span');\n\n/** localStorage key that switches the browser OTEL sampler from 30% to 100%. */\nexport const TRACE_ALL_KEY = 'dxos.debug.traceAll';\n\n/**\n * Reads `@trace.info({ spanAttribute: true })` properties from the instance\n * and writes them into the span attributes map.\n */\nconst collectSpanAttributes = (instance: any, spanAttributes: Record<string, any>) => {\n const proto = Object.getPrototypeOf(instance);\n if (!proto) {\n return;\n }\n const tracingContext = getTracingContext(proto);\n for (const [key, { options }] of Object.entries(tracingContext.infoProperties)) {\n if (!options.spanAttribute) {\n continue;\n }\n try {\n const value = typeof instance[key] === 'function' ? instance[key]() : instance[key];\n if (value != null) {\n const resolved = options.enum ? options.enum[value] : String(value);\n spanAttributes[`ctx.${key}`] = resolved;\n }\n } catch {\n // Skip properties that throw (e.g. uninitialized).\n }\n }\n};\n\nexport type ResourceOptions = {\n annotation?: symbol;\n /**\n * Start a lifecycle span on `open()` and end it on `close()`.\n * `this._ctx` carries the lifecycle span's trace context, so background work\n * (subscriptions, timers) becomes children of the lifecycle span.\n * Direct calls within `_open` use the `_open` span's context as usual.\n * Requires the class to extend {@link Resource}.\n */\n lifecycle?: boolean;\n};\n\n/**\n * Annotates a class as a tracked resource.\n */\nconst resource =\n (options?: ResourceOptions) =>\n <T extends { new (...args: any[]): {} }>(constructor: T) => {\n if (options?.lifecycle && !(constructor.prototype instanceof Resource)) {\n throw new Error(`@trace.resource({ lifecycle: true }) requires ${constructor.name} to extend Resource`);\n }\n\n const klass = (() =>\n class extends constructor {\n constructor(...rest: any[]) {\n super(...rest);\n TRACE_PROCESSOR.createTraceResource({ constructor, annotation: options?.annotation, instance: this });\n }\n })();\n\n if (options?.lifecycle) {\n const sanitizedName = sanitizeClassName(constructor.name);\n const proto = klass.prototype as any;\n const originalOpen = proto.open;\n const originalClose = proto.close;\n\n proto.open = async function (ctx?: Context): Promise<any> {\n const self = this as any;\n\n if (self._lifecycleState !== LifecycleState.CLOSED) {\n return originalOpen.call(this, ctx);\n }\n\n const parentSpanContext = ctx?.getAttribute(TRACE_SPAN_ATTRIBUTE);\n const resourceEntry = TRACE_PROCESSOR.resourceInstanceIndex.get(this);\n const spanAttributes: Record<string, any> = {};\n if (resourceEntry) {\n spanAttributes.entryPoint = resourceEntry.sanitizedClassName;\n }\n\n const remoteSpan = TRACE_PROCESSOR.tracingBackend?.startSpan({\n name: `${sanitizedName}.lifecycle`,\n op: 'lifecycle',\n attributes: spanAttributes,\n parentContext: parentSpanContext,\n });\n self[LIFECYCLE_SPAN] = remoteSpan;\n\n let openCtx = ctx;\n if (remoteSpan?.spanContext != null) {\n const traceAttrs = { [TRACE_SPAN_ATTRIBUTE]: remoteSpan.spanContext };\n openCtx = ctx ? ctx.derive({ attributes: traceAttrs }) : new Context({ attributes: traceAttrs });\n }\n\n try {\n return await originalOpen.call(this, openCtx);\n } catch (err) {\n remoteSpan?.setError?.(err);\n remoteSpan?.end();\n self[LIFECYCLE_SPAN] = undefined;\n throw err;\n }\n };\n\n proto.close = async function (ctx?: Context): Promise<any> {\n const self = this as any;\n const remoteSpan: RemoteSpan | undefined = self[LIFECYCLE_SPAN];\n try {\n return await originalClose.call(this, ctx);\n } catch (err) {\n remoteSpan?.setError?.(err);\n throw err;\n } finally {\n if (remoteSpan) {\n remoteSpan.end();\n self[LIFECYCLE_SPAN] = undefined;\n }\n }\n };\n }\n\n Object.defineProperty(klass, 'name', { value: constructor.name });\n return klass;\n };\n\nexport interface TimeAware {\n tick(timeMs: number): void;\n}\n\nexport type InfoOptions = {\n /**\n * Value is of enum type and should be converted to string.\n *\n * Example:\n *\n * ```ts\n * @trace.info({ enum: SpaceState })\n * get state(): SpaceState { ... }\n * ```\n */\n enum?: Record<string, any>;\n\n /**\n * Max depth of the object to be included in the resource info section.\n *\n * null means no limit (a limit of 8 nested objects is still imposed).\n *\n * Default: 0 - objects will be stringified with toString.\n */\n depth?: number | null;\n\n /** When true, the property value is also set as an OTEL span attribute on every span created by this resource. */\n spanAttribute?: boolean;\n};\n\n/**\n * Marks a property or a method to be included in the resource info section.\n */\nconst info =\n (opts: InfoOptions = {}) =>\n (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => {\n getTracingContext(target).infoProperties[propertyKey] = { options: opts };\n };\n\nconst mark = (name: string) => {\n performance.mark(name);\n};\n\nexport type SpanOptions = {\n showInBrowserTimeline?: boolean;\n /** When false the span is not exported to remote OTLP collectors. Defaults to true. */\n showInRemoteTracing?: boolean;\n op?: string;\n attributes?: Record<string, any>;\n};\n\n/**\n * Decorator that creates a span for the execution duration of the decorated method.\n * Calls the TracingBackend directly; no custom TracingSpan objects.\n */\nconst span =\n ({ showInBrowserTimeline = false, showInRemoteTracing = true, op, attributes }: SpanOptions = {}) =>\n (target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<(...args: any) => any>) => {\n const method = descriptor.value!;\n\n descriptor.value = async function (this: any, ...args: any) {\n const parentCtx = args[0] instanceof Context ? args[0] : null;\n const startTs = performance.now();\n\n const parentSpanContext = parentCtx?.getAttribute(TRACE_SPAN_ATTRIBUTE);\n\n const resourceEntry = TRACE_PROCESSOR.resourceInstanceIndex.get(this);\n const className = resourceEntry?.sanitizedClassName ?? sanitizeClassName(target.constructor?.name ?? 'unknown');\n const spanName = `${className}.${propertyKey}`;\n\n const spanAttributes: Record<string, any> = {};\n if (resourceEntry) {\n spanAttributes.entryPoint = resourceEntry.sanitizedClassName;\n }\n collectSpanAttributes(this, spanAttributes);\n if (attributes) {\n for (const [key, value] of Object.entries(attributes)) {\n spanAttributes[key.startsWith('ctx.') ? key : `ctx.${key}`] = value;\n }\n }\n\n const remoteSpan = showInRemoteTracing\n ? TRACE_PROCESSOR.tracingBackend?.startSpan({\n name: spanName,\n op: op ?? 'function',\n attributes: spanAttributes,\n parentContext: parentSpanContext,\n })\n : undefined;\n\n let callArgs = args;\n if (parentCtx) {\n const childCtx =\n remoteSpan?.spanContext != null\n ? parentCtx.derive({ attributes: { [TRACE_SPAN_ATTRIBUTE]: remoteSpan.spanContext } })\n : parentCtx.derive();\n callArgs = [childCtx, ...args.slice(1)];\n }\n\n try {\n return await method.apply(this, callArgs);\n } catch (err) {\n remoteSpan?.setError?.(err);\n throw err;\n } finally {\n remoteSpan?.end();\n if (showInBrowserTimeline && typeof globalThis?.performance?.measure === 'function') {\n performance.measure(spanName, { start: startTs, end: performance.now() });\n }\n }\n };\n };\n\nconst manualSpans = new Map<string, RemoteSpan>();\nconst manualSpanTimestamps = new Map<string, { name: string; startTs: number }>();\n\nexport type ManualSpanParams = {\n id: string;\n instance: any;\n methodName: string;\n parentCtx: Context | null;\n showInBrowserTimeline?: boolean;\n showInRemoteTracing?: boolean;\n op?: string;\n attributes?: Record<string, any>;\n};\n\n/**\n * Creates a span that must be ended manually.\n *\n * Returns a child Context that carries the new span's `TRACE_SPAN_ATTRIBUTE`.\n * Callers should use the returned ctx for downstream work so that nested\n * `@trace.span` methods and RPC calls inherit this span as their parent\n * and land in the same trace (rather than starting a new root).\n *\n * When the new span cannot be created (duplicate id, no backend, or\n * `showInRemoteTracing: false`), the parentCtx is returned unchanged.\n */\nconst spanStart = (params: ManualSpanParams): Context | null => {\n if (manualSpans.has(params.id) || manualSpanTimestamps.has(params.id)) {\n return params.parentCtx;\n }\n\n const resourceEntry = TRACE_PROCESSOR.resourceInstanceIndex.get(params.instance);\n const className = resourceEntry?.sanitizedClassName ?? 'unknown';\n const spanName = `${className}.${params.methodName}`;\n\n if (params.showInBrowserTimeline) {\n manualSpanTimestamps.set(params.id, { name: spanName, startTs: performance.now() });\n }\n\n if (params.showInRemoteTracing === false || !TRACE_PROCESSOR.tracingBackend) {\n return params.parentCtx;\n }\n\n const parentSpanContext = params.parentCtx?.getAttribute(TRACE_SPAN_ATTRIBUTE);\n\n const spanAttributes: Record<string, any> = {};\n if (resourceEntry) {\n spanAttributes.entryPoint = resourceEntry.sanitizedClassName;\n }\n collectSpanAttributes(params.instance, spanAttributes);\n if (params.attributes) {\n for (const [key, value] of Object.entries(params.attributes)) {\n spanAttributes[key.startsWith('ctx.') ? key : `ctx.${key}`] = value;\n }\n }\n\n const remoteSpan = TRACE_PROCESSOR.tracingBackend.startSpan({\n name: spanName,\n op: params.op ?? 'function',\n attributes: spanAttributes,\n parentContext: parentSpanContext,\n });\n manualSpans.set(params.id, remoteSpan);\n\n if (params.parentCtx && remoteSpan.spanContext != null) {\n return params.parentCtx.derive({ attributes: { [TRACE_SPAN_ATTRIBUTE]: remoteSpan.spanContext } });\n }\n return params.parentCtx;\n};\n\n/**\n * Ends a span that was started manually.\n */\nconst spanEnd = (id: string) => {\n const remoteSpan = manualSpans.get(id);\n if (remoteSpan) {\n remoteSpan.end();\n manualSpans.delete(id);\n }\n\n const timestamps = manualSpanTimestamps.get(id);\n if (timestamps && typeof globalThis?.performance?.measure === 'function') {\n performance.measure(timestamps.name, { start: timestamps.startTs, end: performance.now() });\n manualSpanTimestamps.delete(id);\n }\n};\n\n/**\n * Attaches metrics counter to the resource.\n */\nconst metricsCounter = () => (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => {\n getTracingContext(target).metricsProperties[propertyKey] = {};\n};\n\nexport type AddLinkOptions = {};\n\nconst addLink = (parent: any, child: any, opts: AddLinkOptions = {}) => {\n TRACE_PROCESSOR.addLink(parent, child, opts);\n};\n\nexport type TraceDiagnosticProps<T> = {\n /** Unique ID. */\n id: string;\n\n /**\n * Human-readable name.\n * @defaults Defaults to `id`\n */\n name?: string;\n\n /** Function that will be called to fetch the diagnostic data. */\n fetch: () => MaybePromise<T>;\n};\n\nexport interface TraceDiagnostic {\n id: string;\n unregister(): void;\n}\n\n/**\n * Register a diagnostic that could be queried.\n */\nconst diagnostic = <T>(params: TraceDiagnosticProps<T>): TraceDiagnostic => {\n return TRACE_PROCESSOR.diagnostics.registerDiagnostic(params);\n};\n\nexport const trace = {\n addLink,\n diagnostic,\n info,\n mark,\n metricsCounter,\n resource,\n span,\n spanStart,\n spanEnd,\n metrics: TRACE_PROCESSOR.remoteMetrics,\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type InfoOptions } from './api';\n\nexport const symbolTracingContext = Symbol('dxos.tracing.context');\n\nexport type TracingContext = {\n infoProperties: Record<\n string,\n {\n options: InfoOptions;\n }\n >;\n metricsProperties: Record<string, {}>;\n};\n\nexport const getTracingContext = (target: any): TracingContext => {\n return ((target[symbolTracingContext] as TracingContext | undefined) ??= {\n infoProperties: {},\n metricsProperties: {},\n });\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { LogLevel, type LogProcessor, log } from '@dxos/log';\nimport { type LogEntry } from '@dxos/protocols/proto/dxos/client/services';\nimport { type Metric, type Resource } from '@dxos/protocols/proto/dxos/tracing';\nimport { getPrototypeSpecificInstanceId } from '@dxos/util';\n\nimport type { AddLinkOptions, TimeAware } from './api';\nimport { BUFFERED_PREFIX, BufferingTracingBackend } from './buffering-backend';\nimport { DiagnosticsManager } from './diagnostic';\nimport { DiagnosticsChannel } from './diagnostics-channel';\nimport { type BaseCounter } from './metrics';\nimport { RemoteMetrics } from './remote/metrics';\nimport { getTracingContext } from './symbols';\nimport type { RemoteSpan, StartSpanOptions, TracingBackend } from './tracing-types';\nimport { WeakRef } from './weak-ref';\n\nexport type Diagnostics = {\n resources: Record<string, Resource>;\n logs: LogEntry[];\n};\n\nexport type TraceResourceConstructorProps = {\n constructor: { new (...args: any[]): {} };\n instance: any;\n annotation?: symbol;\n};\n\nexport class ResourceEntry {\n /**\n * Sometimes bundlers mangle class names: WebFile -> WebFile2.\n *\n * We use a heuristic to remove the suffix.\n */\n public readonly sanitizedClassName: string;\n\n constructor(\n public readonly data: Resource,\n public readonly instance: WeakRef<any>,\n public readonly annotation?: symbol,\n ) {\n this.sanitizedClassName = sanitizeClassName(data.className);\n }\n\n getMetric(name: string): Metric | undefined {\n return this.data.metrics?.find((metric) => metric.name === name);\n }\n}\n\nconst MAX_RESOURCE_RECORDS = 2_000;\nconst MAX_LOG_RECORDS = 1_000;\n\nconst MAX_INFO_OBJECT_DEPTH = 8;\n\nexport class TraceProcessor {\n public readonly diagnostics = new DiagnosticsManager();\n public readonly diagnosticsChannel = new DiagnosticsChannel();\n public readonly remoteMetrics = new RemoteMetrics();\n\n readonly #bufferingBackend = new BufferingTracingBackend();\n #activeBackend: TracingBackend = this.#bufferingBackend;\n\n /**\n * Tracing backend. Initially a buffering backend that records spans;\n * once the observability package sets a real backend, the buffer is drained\n * and a thin translating wrapper is installed that resolves stale buffered\n * parent IDs still held by in-flight {@link Context} objects.\n *\n * The wrapper only allocates when a `buffered-*` parent is actually encountered;\n * the common path is a single `startsWith` check and direct passthrough.\n */\n get tracingBackend(): TracingBackend {\n return this.#activeBackend;\n }\n\n set tracingBackend(backend: TracingBackend | undefined) {\n if (!backend || backend === this.#bufferingBackend) {\n this.#bufferingBackend.clear();\n this.#activeBackend = this.#bufferingBackend;\n return;\n }\n const idMap = this.#bufferingBackend.drain(backend);\n this.#activeBackend = {\n startSpan: (options: StartSpanOptions): RemoteSpan => {\n const parent = options.parentContext;\n if (parent?.traceparent.startsWith(BUFFERED_PREFIX)) {\n const translated = idMap.get(parent.traceparent);\n if (translated) {\n return backend.startSpan({ ...options, parentContext: translated });\n }\n }\n return backend.startSpan(options);\n },\n };\n }\n\n readonly resources = new Map<number, ResourceEntry>();\n readonly resourceInstanceIndex = new WeakMap<any, ResourceEntry>();\n readonly resourceIdList: number[] = [];\n\n readonly logs: LogEntry[] = [];\n\n private _instanceTag: string | null = null;\n\n constructor() {\n log.addProcessor(this._logProcessor.bind(this));\n\n if (DiagnosticsChannel.supported) {\n this.diagnosticsChannel.serve(this.diagnostics);\n }\n this.diagnosticsChannel.unref();\n }\n\n setInstanceTag(tag: string): void {\n this._instanceTag = tag;\n this.diagnostics.setInstanceTag(tag);\n }\n\n /** @internal */\n createTraceResource(params: TraceResourceConstructorProps): void {\n const id = this.resources.size;\n\n const tracingContext = getTracingContext(Object.getPrototypeOf(params.instance));\n for (const key of Object.keys(tracingContext.metricsProperties)) {\n (params.instance[key] as BaseCounter)._assign(params.instance, key);\n }\n\n const entry = new ResourceEntry(\n {\n id,\n className: params.constructor.name,\n instanceId: getPrototypeSpecificInstanceId(params.instance),\n info: this.getResourceInfo(params.instance),\n links: [],\n metrics: this.getResourceMetrics(params.instance),\n },\n new WeakRef(params.instance),\n params.annotation,\n );\n\n this.resources.set(id, entry);\n this.resourceInstanceIndex.set(params.instance, entry);\n this.resourceIdList.push(id);\n if (this.resourceIdList.length > MAX_RESOURCE_RECORDS) {\n this._clearResources();\n }\n }\n\n // TODO(burdon): Not implemented.\n addLink(parent: any, child: any, opts: AddLinkOptions): void {}\n\n getDiagnostics(): Diagnostics {\n this.refresh();\n\n return {\n resources: Object.fromEntries(\n Array.from(this.resources.entries()).map(([id, entry]) => [\n `${entry.sanitizedClassName}#${entry.data.instanceId}`,\n entry.data,\n ]),\n ),\n logs: this.logs.filter((log) => log.level >= LogLevel.INFO),\n };\n }\n\n getResourceInfo(instance: any): Record<string, any> {\n const res: Record<string, any> = {};\n const tracingContext = getTracingContext(Object.getPrototypeOf(instance));\n for (const [key, { options }] of Object.entries(tracingContext.infoProperties)) {\n try {\n const value = typeof instance[key] === 'function' ? instance[key]() : instance[key];\n if (options.enum) {\n res[key] = options.enum[value];\n } else {\n res[key] = sanitizeValue(\n value,\n options.depth === undefined ? 1 : (options.depth ?? MAX_INFO_OBJECT_DEPTH),\n this,\n );\n }\n } catch (err: any) {\n res[key] = err.message;\n }\n }\n\n return res;\n }\n\n getResourceMetrics(instance: any): Metric[] {\n const res: Metric[] = [];\n const tracingContext = getTracingContext(Object.getPrototypeOf(instance));\n for (const [key, _opts] of Object.entries(tracingContext.metricsProperties)) {\n res.push(instance[key].getData());\n }\n\n return res;\n }\n\n getResourceId(instance: any): number | null {\n const entry = this.resourceInstanceIndex.get(instance);\n return entry ? entry.data.id : null;\n }\n\n findResourcesByClassName(className: string): ResourceEntry[] {\n return [...this.resources.values()].filter(\n (res) => res.data.className === className || res.sanitizedClassName === className,\n );\n }\n\n findResourcesByAnnotation(annotation: symbol): ResourceEntry[] {\n return [...this.resources.values()].filter((res) => res.annotation === annotation);\n }\n\n refresh(): void {\n for (const resource of this.resources.values()) {\n const instance = resource.instance.deref();\n if (!instance) {\n continue;\n }\n\n const tracingContext = getTracingContext(Object.getPrototypeOf(instance));\n const time = performance.now();\n (instance as TimeAware).tick?.(time);\n for (const key of Object.keys(tracingContext.metricsProperties)) {\n (instance[key] as BaseCounter)._tick?.(time);\n }\n\n resource.data.info = this.getResourceInfo(instance);\n resource.data.metrics = this.getResourceMetrics(instance);\n }\n }\n\n private _clearResources(): void {\n while (this.resourceIdList.length > MAX_RESOURCE_RECORDS) {\n const id = this.resourceIdList.shift()!;\n this.resources.delete(id);\n }\n }\n\n private _pushLog(log: LogEntry): void {\n this.logs.push(log);\n if (this.logs.length > MAX_LOG_RECORDS) {\n this.logs.shift();\n }\n }\n\n private _logProcessor: LogProcessor = (config, entry) => {\n switch (entry.level) {\n case LogLevel.ERROR:\n case LogLevel.WARN:\n case LogLevel.TRACE: {\n const scope = entry.meta?.S;\n const resource = this.resourceInstanceIndex.get(scope);\n if (!resource) {\n return;\n }\n\n const context: Record<string, any> = { ...entry.computedContext };\n if (entry.computedError !== undefined) {\n context.error = entry.computedError;\n }\n\n const { filename, line } = entry.computedMeta;\n const entryToPush: LogEntry = {\n level: entry.level,\n message: entry.message ?? entry.computedError ?? '',\n context,\n timestamp: new Date(entry.timestamp),\n meta: {\n file: filename ?? '',\n line: line ?? 0,\n resourceId: resource.data.id,\n },\n };\n this._pushLog(entryToPush);\n break;\n }\n default:\n }\n };\n}\n\nexport const TRACE_PROCESSOR: TraceProcessor = ((globalThis as any).TRACE_PROCESSOR ??= new TraceProcessor());\n\nconst sanitizeValue = (value: any, depth: number, traceProcessor: TraceProcessor): any => {\n switch (typeof value) {\n case 'string':\n case 'number':\n case 'boolean':\n case 'undefined':\n return value;\n case 'object':\n case 'function':\n if (value === null) {\n return value;\n }\n\n {\n const resourceEntry = traceProcessor.resourceInstanceIndex.get(value);\n if (resourceEntry) {\n return `${resourceEntry.sanitizedClassName}#${resourceEntry.data.instanceId}`;\n }\n }\n\n if (typeof value.toJSON === 'function') {\n return sanitizeValue(value.toJSON(), depth, traceProcessor);\n }\n\n if (depth > 0) {\n if (isSetLike(value)) {\n return Object.fromEntries(\n Array.from(value.entries()).map((value) => sanitizeValue(value, depth - 1, traceProcessor)),\n );\n } else if (isMapLike(value)) {\n return Object.fromEntries(\n Array.from(value.entries()).map(([key, value]) => [key, sanitizeValue(value, depth - 1, traceProcessor)]),\n );\n } else if (Array.isArray(value)) {\n return value.map((item: any) => sanitizeValue(item, depth - 1, traceProcessor));\n } else if (typeof value === 'object') {\n const res: any = {};\n for (const key of Object.keys(value)) {\n res[key] = sanitizeValue(value[key], depth - 1, traceProcessor);\n }\n return res;\n }\n }\n\n if (typeof value.truncate === 'function') {\n return value.truncate();\n }\n\n return value.toString();\n }\n};\n\nexport const sanitizeClassName = (className: string) => {\n let name = className.replace(/^_+/, '');\n const SANITIZE_REGEX = /[^_](\\d+)$/;\n const m = name.match(SANITIZE_REGEX);\n if (m) {\n name = name.slice(0, -m[1].length);\n }\n return name;\n};\n\nconst isSetLike = (value: any): value is Set<any> =>\n value instanceof Set ||\n (typeof value === 'object' && value !== null && Object.getPrototypeOf(value).constructor.name === 'ComplexSet');\n\nconst isMapLike = (value: any): value is Map<any, any> =>\n value instanceof Map ||\n (typeof value === 'object' && value !== null && Object.getPrototypeOf(value).constructor.name === 'ComplexMap');\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { type TraceContextData } from '@dxos/context';\n\nimport type { RemoteSpan, StartSpanOptions, TracingBackend } from './tracing-types';\n\nexport const BUFFERED_PREFIX = 'buffered-';\n\n/**\n * Span handle that records operations while no real OTEL backend is available.\n * Once a real backend is registered, the buffered span is replayed and a\n * {@link delegate} is set so future calls forward to the real span.\n */\nclass BufferedSpan implements RemoteSpan {\n readonly spanContext: TraceContextData;\n readonly startTime: number;\n delegate?: RemoteSpan;\n\n #ended = false;\n #endTime?: number;\n #error?: unknown;\n #hasError = false;\n\n constructor(\n readonly options: StartSpanOptions,\n id: number,\n ) {\n this.spanContext = { traceparent: `${BUFFERED_PREFIX}${id}` };\n this.startTime = Date.now();\n }\n\n end(endTime?: number): void {\n if (this.delegate) {\n this.delegate.end(endTime);\n return;\n }\n this.#endTime = endTime ?? Date.now();\n this.#ended = true;\n }\n\n setError(err: unknown): void {\n if (this.delegate) {\n this.delegate.setError?.(err);\n return;\n }\n this.#error = err;\n this.#hasError = true;\n }\n\n replay(real: RemoteSpan): void {\n if (this.#hasError) {\n real.setError?.(this.#error);\n }\n if (this.#ended) {\n real.end(this.#endTime);\n } else {\n this.delegate = real;\n }\n }\n}\n\n/**\n * A {@link TracingBackend} that buffers span operations until a real backend\n * registers. On {@link drain}, buffered spans are replayed in FIFO order with\n * parent IDs translated from synthetic `buffered-*` traceparents to real OTEL\n * IDs, preserving the trace hierarchy.\n */\nexport class BufferingTracingBackend implements TracingBackend {\n readonly #pending: BufferedSpan[] = [];\n #counter = 0;\n\n startSpan(options: StartSpanOptions): RemoteSpan {\n const span = new BufferedSpan(options, ++this.#counter);\n this.#pending.push(span);\n return span;\n }\n\n /** Discard all buffered spans without replaying them. */\n clear(): void {\n this.#pending.length = 0;\n }\n\n /**\n * Replay all buffered spans into {@link backend}.\n *\n * @returns Map from synthetic buffered traceparent to real {@link TraceContextData},\n * used by the post-drain translating wrapper to resolve stale buffered IDs\n * still present on in-flight {@link Context} objects.\n */\n drain(backend: TracingBackend): Map<string, TraceContextData> {\n const idMap = new Map<string, TraceContextData>();\n\n for (const buffered of this.#pending) {\n let parentContext = buffered.options.parentContext;\n if (parentContext && parentContext.traceparent.startsWith(BUFFERED_PREFIX)) {\n parentContext = idMap.get(parentContext.traceparent) ?? parentContext;\n }\n\n const real = backend.startSpan({ ...buffered.options, parentContext, startTime: buffered.startTime });\n\n if (real.spanContext) {\n idMap.set(buffered.spanContext.traceparent, real.spanContext);\n }\n\n buffered.replay(real);\n }\n this.#pending.length = 0;\n return idMap;\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { asyncTimeout } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\n\nimport { type TraceDiagnostic, type TraceDiagnosticProps } from './api';\nimport { createId } from './util';\n\nexport const DIAGNOSTICS_TIMEOUT = 10_000;\n\nexport type DiagnosticMetadata = {\n id: string;\n instanceId: string;\n instanceTag: string | null;\n name: string;\n};\n\nexport type DiagnosticsRequest = {\n id: string;\n instanceId?: string;\n instanceTag?: string | null;\n};\n\nexport type DiagnosticsData = {\n id: string;\n instanceId: string;\n data: any;\n error?: string;\n};\n\nexport class TraceDiagnosticImpl implements TraceDiagnostic {\n constructor(\n public id: string,\n public fetch: () => any,\n public name: string,\n private readonly _onUnregister: () => void,\n ) {}\n\n unregister(): void {\n this._onUnregister();\n }\n}\n\nexport class DiagnosticsManager {\n readonly instanceId = createId();\n\n readonly registry = new Map<string, TraceDiagnosticImpl>();\n\n private _instanceTag: string | null = null;\n\n get instanceTag(): string | null {\n return this._instanceTag;\n }\n\n setInstanceTag(tag: string): void {\n this._instanceTag = tag;\n }\n\n registerDiagnostic(params: TraceDiagnosticProps<any>): TraceDiagnostic {\n const impl = new TraceDiagnosticImpl(params.id, params.fetch, params.name ?? params.id, () => {\n if (this.registry.get(params.id) === impl) {\n this.registry.delete(params.id);\n }\n });\n this.registry.set(params.id, impl);\n return impl;\n }\n\n list(): DiagnosticMetadata[] {\n return Array.from(this.registry.values()).map((diagnostic) => ({\n id: diagnostic.id,\n instanceId: this.instanceId,\n instanceTag: this._instanceTag,\n name: diagnostic.name,\n }));\n }\n\n async fetch(request: DiagnosticsRequest): Promise<DiagnosticsData> {\n if (request.instanceId != null) {\n invariant(request.instanceId === this.instanceId, 'Invalid instance id');\n }\n const { id } = request;\n const diagnostic = this.registry.get(id);\n invariant(diagnostic, 'Diagnostic not found');\n try {\n const data = await asyncTimeout(diagnostic.fetch(), DIAGNOSTICS_TIMEOUT);\n return {\n id,\n instanceId: this.instanceId,\n data,\n };\n } catch (err: any) {\n return {\n id,\n instanceId: this.instanceId,\n data: null,\n error: err.stack,\n };\n }\n }\n}\n", "// TODO(dmaretskyi): Use UUID.\n//\n// Copyright 2024 DXOS.org\n//\n\nexport const createId = () => Math.random().toString(36).slice(2);\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { Trigger, sleep } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\n\nimport {\n type DiagnosticMetadata,\n DIAGNOSTICS_TIMEOUT,\n type DiagnosticsData,\n type DiagnosticsManager,\n type DiagnosticsRequest,\n} from './diagnostic';\nimport { createId } from './util';\n\nconst DEFAULT_CHANNEL_NAME = 'dxos-diagnostics';\n\nconst DISCOVER_TIME = 500;\n\nexport type DiagnosticChannelMessage =\n | {\n type: 'DIAGNOSTICS_DISCOVER';\n }\n | {\n type: 'DIAGNOSTICS_ANNOUNCE';\n diagnostics: DiagnosticMetadata[];\n }\n | {\n type: 'DIAGNOSTICS_FETCH';\n requestId: string;\n request: DiagnosticsRequest;\n }\n | {\n type: 'DIAGNOSTICS_RESPONSE';\n requestId: string;\n data: DiagnosticsData;\n };\n\nexport class DiagnosticsChannel {\n static get supported() {\n return globalThis.BroadcastChannel != null;\n }\n\n private _ctx = new Context();\n\n // Separate channels becauase the client and server may be in the same process.\n private readonly _serveChannel?: BroadcastChannel = undefined;\n private readonly _clientChannel?: BroadcastChannel = undefined;\n\n constructor(private readonly _channelName: string = DEFAULT_CHANNEL_NAME) {\n if (DiagnosticsChannel.supported) {\n this._serveChannel = new BroadcastChannel(_channelName);\n this._clientChannel = new BroadcastChannel(_channelName);\n }\n }\n\n destroy(): void {\n void this._ctx.dispose();\n this._serveChannel?.close();\n this._clientChannel?.close();\n }\n\n /**\n * In node.js, the channel will keep the process alive.\n * This method allows the process to exit.\n * Noop in the browser.\n */\n unref(): void {\n if (this._serveChannel && typeof (this._serveChannel as any).unref === 'function') {\n (this._serveChannel as any).unref();\n (this._clientChannel as any).unref();\n }\n }\n\n serve(manager: DiagnosticsManager): void {\n invariant(this._serveChannel);\n const listener = async (event: MessageEvent) => {\n switch (event.data.type) {\n case 'DIAGNOSTICS_DISCOVER': {\n const diagnostics = manager.list();\n this._serveChannel!.postMessage({\n type: 'DIAGNOSTICS_ANNOUNCE',\n diagnostics,\n } satisfies DiagnosticChannelMessage);\n break;\n }\n case 'DIAGNOSTICS_FETCH': {\n const { requestId, request } = event.data;\n\n if (request.instanceId != null && request.instanceId !== manager.instanceId) {\n break;\n } else if (request.instanceTag != null && request.instanceTag !== manager.instanceTag) {\n break;\n }\n\n const data = await manager.fetch(request);\n this._serveChannel!.postMessage({\n type: 'DIAGNOSTICS_RESPONSE',\n requestId,\n data,\n } satisfies DiagnosticChannelMessage);\n break;\n }\n }\n };\n\n this._serveChannel.addEventListener('message', listener);\n this._ctx.onDispose(() => this._serveChannel!.removeEventListener('message', listener));\n }\n\n async discover(): Promise<DiagnosticMetadata[]> {\n invariant(this._clientChannel);\n const diagnostics: DiagnosticMetadata[] = [];\n\n const collector = (event: MessageEvent) => {\n const data = event.data as DiagnosticChannelMessage;\n switch (data.type) {\n case 'DIAGNOSTICS_ANNOUNCE':\n diagnostics.push(...data.diagnostics);\n break;\n }\n };\n\n try {\n this._clientChannel.addEventListener('message', collector);\n this._clientChannel.postMessage({ type: 'DIAGNOSTICS_DISCOVER' } satisfies DiagnosticChannelMessage);\n\n await sleep(DISCOVER_TIME);\n\n // Dedup.\n const result: DiagnosticMetadata[] = [];\n for (const diagnostic of diagnostics) {\n if (!result.some((d) => d.id === diagnostic.id && d.instanceId === diagnostic.instanceId)) {\n result.push(diagnostic);\n }\n }\n\n return diagnostics;\n } finally {\n this._clientChannel.removeEventListener('message', collector);\n }\n }\n\n async fetch(request: DiagnosticsRequest): Promise<DiagnosticsData> {\n invariant(this._clientChannel);\n const requestId = createId();\n\n const trigger = new Trigger<DiagnosticsData>();\n const listener = (event: MessageEvent) => {\n const data = event.data as DiagnosticChannelMessage;\n if (data.type === 'DIAGNOSTICS_RESPONSE' && data.requestId === requestId) {\n trigger.wake(data.data);\n }\n };\n\n try {\n this._clientChannel.addEventListener('message', listener);\n this._clientChannel.postMessage({\n type: 'DIAGNOSTICS_FETCH',\n requestId,\n request,\n } satisfies DiagnosticChannelMessage);\n\n // NOTE: Must have await keyword in this block.\n const result = await trigger.wait({ timeout: DIAGNOSTICS_TIMEOUT });\n\n return result;\n } finally {\n this._clientChannel.removeEventListener('message', listener);\n }\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\ntype TagType = number | string | boolean | null | undefined;\n\nexport interface MetricData {\n unit?: string;\n tags?: Record<string, TagType>;\n timestamp?: number;\n}\n\ninterface MetricsMethods {\n /**\n * Adds a value to a counter metric\n */\n increment(name: string, value?: number, data?: MetricData): void;\n /**\n * Adds a value to a distribution metric\n */\n distribution(name: string, value: number, data?: MetricData): void;\n /**\n * Adds a value to a set metric. Value must be a string or integer.\n */\n set(name: string, value: number | string, data?: MetricData): void;\n /**\n * Adds a value to a gauge metric\n */\n gauge(name: string, value: number, data?: MetricData): void;\n}\n\n/**\n * Allows metrics to be recorded within SDK code without requiring specific consumers.\n */\nexport class RemoteMetrics implements MetricsMethods {\n private _metrics = new Set<MetricsMethods>();\n\n registerProcessor(processor: MetricsMethods): void {\n this._metrics.add(processor);\n }\n\n increment(name: string, value?: number, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.increment(name, value, data));\n }\n\n distribution(name: string, value: number, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.distribution(name, value, data));\n }\n\n set(name: string, value: number | string, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.set(name, value, data));\n }\n\n gauge(name: string, value: number, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.gauge(name, value, data));\n }\n}\n", "// Workerd does not support WeakRef\n\n//\n// Copyright 2024 DXOS.org\n//\n\nclass WeakRefMock<T> {\n // eslint-disable-next-line @typescript-eslint/no-useless-constructor\n constructor(target: T) {\n // do nothing\n }\n\n deref(): T | undefined {\n return undefined;\n }\n}\n\nexport const WeakRef = globalThis.WeakRef ?? WeakRefMock;\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nexport abstract class BaseCounter {\n /**\n * @internal\n */\n _instance: any;\n\n name?: string;\n\n /**\n * @internal\n */\n _assign(instance: any, name: string): void {\n this._instance = instance;\n this.name = name;\n }\n\n abstract getData(): Metric;\n\n _tick(time: number): void {}\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nexport class UnaryCounter extends BaseCounter {\n value = 0;\n units?: string;\n\n constructor({ units }: { units?: string } = {}) {\n super();\n this.units = units;\n }\n\n inc(by = 1): void {\n this.value += by;\n }\n\n getData(): Metric {\n return {\n name: this.name!,\n counter: {\n value: this.value,\n units: this.units,\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nconst MAX_BUCKETS = 60;\n\nexport class TimeSeriesCounter extends BaseCounter {\n private _currentValue = 0;\n private _totalValue = 0;\n private _buckets: number[] = [];\n units?: string;\n\n constructor({ units }: { units?: string } = {}) {\n super();\n this.units = units;\n }\n\n inc(by = 1): void {\n this._currentValue += by;\n this._totalValue += by;\n }\n\n override _tick(time: number): void {\n this._buckets.push(this._currentValue);\n if (this._buckets.length > MAX_BUCKETS) {\n this._buckets.shift();\n }\n this._currentValue = 0;\n }\n\n override getData(): Metric {\n return {\n name: this.name!,\n timeSeries: {\n tracks: [\n {\n name: this.name!,\n units: this.units,\n points: this._buckets.map((value, index) => ({\n value,\n })),\n total: this._totalValue,\n },\n ],\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nconst MAX_BUCKETS = 60;\n\nexport class TimeUsageCounter extends BaseCounter {\n private _currentValue = 0;\n private _totalValue = 0;\n private _buckets: number[] = [];\n\n private _lastTickTime = performance.now();\n\n record(time: number): void {\n this._currentValue += time;\n this._totalValue += time;\n }\n\n beginRecording(): { end: () => void } {\n const start = performance.now();\n return {\n end: () => {\n const end = performance.now();\n this.record(end - start);\n },\n };\n }\n\n override _tick(time: number): void {\n const delta = time - this._lastTickTime;\n this._lastTickTime = time;\n\n const percentage = (this._currentValue / delta) * 100;\n this._buckets.push(percentage);\n if (this._buckets.length > MAX_BUCKETS) {\n this._buckets.shift();\n }\n this._currentValue = 0;\n }\n\n override getData(): Metric {\n return {\n name: this.name!,\n timeSeries: {\n tracks: [\n {\n name: this.name!,\n units: '%',\n points: this._buckets.map((value, index) => ({\n value,\n })),\n total: this._totalValue,\n },\n ],\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nexport class MapCounter extends BaseCounter {\n values = new Map<string, number>();\n units?: string;\n\n constructor({ units }: { units?: string } = {}) {\n super();\n this.units = units;\n }\n\n inc(key: string, by = 1): void {\n const prev = this.values.get(key) ?? 0;\n this.values.set(key, prev + by);\n }\n\n getData(): Metric {\n return {\n name: this.name!,\n multiCounter: {\n records: Array.from(this.values.entries()).map(([key, value]) => ({\n key,\n value,\n })),\n units: this.units,\n },\n };\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nexport class CustomCounter extends BaseCounter {\n constructor(private readonly _getData: () => object) {\n super();\n }\n\n override getData(): Metric {\n return {\n name: this.name!,\n custom: {\n payload: this._getData(),\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { trace } from './api';\n\nexport * from './api';\nexport * from './symbols';\nexport * from './trace-processor';\nexport * from './tracing-types';\nexport * from './metrics';\nexport * from './diagnostic';\nexport * from './diagnostics-channel';\nexport * from './remote/metrics';\n\ntrace.diagnostic({\n id: 'process-info',\n name: 'Process Info',\n fetch: async () => {\n return {\n platform: globalThis.process?.platform,\n arch: globalThis.process?.arch,\n versions: globalThis.process?.versions,\n href: globalThis.location?.href,\n };\n },\n});\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["Context", "LifecycleState", "Resource", "TRACE_SPAN_ATTRIBUTE", "symbolTracingContext", "Symbol", "getTracingContext", "target", "infoProperties", "metricsProperties", "LogLevel", "log", "getPrototypeSpecificInstanceId", "BUFFERED_PREFIX", "BufferedSpan", "spanContext", "startTime", "delegate", "options", "id", "traceparent", "Date", "now", "end", "endTime", "setError", "err", "replay", "real", "BufferingTracingBackend", "startSpan", "span", "push", "clear", "length", "drain", "backend", "idMap", "Map", "buffered", "parentContext", "startsWith", "get", "set", "asyncTimeout", "invariant", "createId", "Math", "random", "toString", "slice", "DIAGNOSTICS_TIMEOUT", "fetch", "name", "_onUnregister", "unregister", "registry", "_instanceTag", "instanceTag", "setInstanceTag", "tag", "registerDiagnostic", "params", "get", "id", "list", "instanceId", "diagnostic", "invariant", "request", "data", "error", "stack", "Trigger", "sleep", "Context", "invariant", "__dxlog_file", "DEFAULT_CHANNEL_NAME", "DiagnosticsChannel", "_ctx", "Context", "_serveChannel", "undefined", "_channelName", "supported", "BroadcastChannel", "destroy", "_clientChannel", "close", "unref", "serve", "listener", "event", "type", "diagnostics", "request", "instanceTag", "requestId", "data", "discover", "invariant", "collector", "sleep", "result", "some", "diagnostic", "trigger", "Trigger", "wake", "RemoteMetrics", "_metrics", "Set", "registerProcessor", "processor", "add", "increment", "name", "value", "data", "Array", "from", "values", "map", "distribution", "set", "gauge", "WeakRefMock", "target", "deref", "undefined", "WeakRef", "globalThis", "__dxlog_file", "ResourceEntry", "instance", "annotation", "sanitizedClassName", "getMetric", "MAX_INFO_OBJECT_DEPTH", "TraceProcessor", "diagnostics", "DiagnosticsManager", "diagnosticsChannel", "remoteMetrics", "BufferingTracingBackend", "tracingBackend", "startSpan", "options", "parent", "traceparent", "translated", "idMap", "parentContext", "resources", "resourceInstanceIndex", "resourceIdList", "logs", "_instanceTag", "addProcessor", "DiagnosticsChannel", "unref", "setInstanceTag", "createTraceResource", "params", "tracingContext", "getTracingContext", "Object", "key", "keys", "entry", "className", "instanceId", "info", "getResourceInfo", "links", "metrics", "getResourceMetrics", "WeakRef", "push", "id", "length", "MAX_RESOURCE_RECORDS", "_clearResources", "addLink", "log", "value", "res", "sanitizeValue", "err", "getResourceId", "findResourcesByClassName", "filter", "findResourcesByAnnotation", "values", "refresh", "resource", "time", "_tick", "_pushLog", "shift", "_logProcessor", "LogLevel", "ERROR", "WARN", "TRACE", "scope", "computedError", "filename", "line", "level", "message", "context", "timestamp", "Date", "meta", "resourceId", "resourceEntry", "depth", "isMapLike", "fromEntries", "Array", "from", "entries", "map", "traceProcessor", "toString", "SANITIZE_REGEX", "name", "m", "isSetLike", "__dxlog_file", "LIFECYCLE_SPAN", "proto", "spanAttribute", "resolved", "options", "enum", "value", "String", "spanAttributes", "Error", "klass", "constructor", "rest", "TRACE_PROCESSOR", "createTraceResource", "annotation", "instance", "prototype", "originalOpen", "originalClose", "open", "_lifecycleState", "LifecycleState", "parentSpanContext", "ctx", "getAttribute", "resourceEntry", "entryPoint", "tracingBackend", "op", "attributes", "parentContext", "remoteSpan", "spanContext", "traceAttrs", "TRACE_SPAN_ATTRIBUTE", "openCtx", "derive", "Context", "setError", "err", "self", "undefined", "Object", "opts", "mark", "performance", "descriptor", "parentCtx", "startTs", "className", "sanitizedClassName", "sanitizeClassName", "spanName", "propertyKey", "collectSpanAttributes", "entries", "callArgs", "args", "childCtx", "measure", "manualSpans", "params", "showInBrowserTimeline", "manualSpanTimestamps", "name", "now", "key", "delete", "timestamps", "addLink", "child", "diagnostic", "info", "metricsCounter", "resource", "span", "spanStart", "spanEnd", "metrics", "BaseCounter", "_instance", "name", "_assign", "instance", "_tick", "time", "UnaryCounter", "BaseCounter", "value", "units", "inc", "by", "getData", "name", "counter", "MAX_BUCKETS", "TimeSeriesCounter", "BaseCounter", "_currentValue", "_totalValue", "_buckets", "units", "inc", "by", "_tick", "time", "push", "length", "shift", "getData", "name", "timeSeries", "tracks", "points", "map", "value", "index", "total", "MAX_BUCKETS", "TimeUsageCounter", "BaseCounter", "_currentValue", "_totalValue", "_buckets", "_lastTickTime", "performance", "now", "record", "time", "beginRecording", "start", "end", "_tick", "delta", "percentage", "push", "length", "shift", "getData", "name", "timeSeries", "tracks", "units", "points", "map", "value", "index", "total", "MapCounter", "BaseCounter", "values", "Map", "units", "inc", "key", "by", "prev", "get", "set", "getData", "name", "multiCounter", "records", "Array", "from", "entries", "map", "value", "CustomCounter", "BaseCounter", "_getData", "getData", "name", "custom", "payload", "trace", "diagnostic", "id", "name", "fetch", "platform", "globalThis", "process", "arch", "versions", "href", "location"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/api.ts", "../../../src/symbols.ts", "../../../src/trace-processor.ts", "../../../src/buffering-backend.ts", "../../../src/diagnostic.ts", "../../../src/util.ts", "../../../src/diagnostics-channel.ts", "../../../src/remote/metrics.ts", "../../../src/weak-ref.ts", "../../../src/metrics/base.ts", "../../../src/metrics/unary-counter.ts", "../../../src/metrics/time-series-counter.ts", "../../../src/metrics/time-usage-counter.ts", "../../../src/metrics/map-counter.ts", "../../../src/metrics/custom-counter.ts", "../../../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { Context, LifecycleState, Resource, TRACE_SPAN_ATTRIBUTE } from '@dxos/context';\nimport { type MaybePromise } from '@dxos/util';\n\nimport { getTracingContext } from './symbols';\nimport { TRACE_PROCESSOR, sanitizeClassName } from './trace-processor';\nimport type { RemoteSpan } from './tracing-types';\n\nconst LIFECYCLE_SPAN = Symbol('dxos.tracing.lifecycle-span');\n\n/** localStorage key that switches the browser OTEL sampler from 30% to 100%. */\nexport const TRACE_ALL_KEY = 'dxos.debug.traceAll';\n\n/**\n * Reads `@trace.info({ spanAttribute: true })` properties from the instance\n * and writes them into the span attributes map.\n */\nconst collectSpanAttributes = (instance: any, spanAttributes: Record<string, any>) => {\n const proto = Object.getPrototypeOf(instance);\n if (!proto) {\n return;\n }\n const tracingContext = getTracingContext(proto);\n for (const [key, { options }] of Object.entries(tracingContext.infoProperties)) {\n if (!options.spanAttribute) {\n continue;\n }\n try {\n const value = typeof instance[key] === 'function' ? instance[key]() : instance[key];\n if (value != null) {\n const resolved = options.enum ? options.enum[value] : String(value);\n spanAttributes[`ctx.${key}`] = resolved;\n }\n } catch {\n // Skip properties that throw (e.g. uninitialized).\n }\n }\n};\n\nexport type ResourceOptions = {\n annotation?: symbol;\n /**\n * Start a lifecycle span on `open()` and end it on `close()`.\n * `this._ctx` carries the lifecycle span's trace context, so background work\n * (subscriptions, timers) becomes children of the lifecycle span.\n * Direct calls within `_open` use the `_open` span's context as usual.\n * Requires the class to extend {@link Resource}.\n */\n lifecycle?: boolean;\n};\n\n/**\n * Annotates a class as a tracked resource.\n */\nconst resource =\n (options?: ResourceOptions) =>\n <T extends { new (...args: any[]): {} }>(constructor: T) => {\n if (options?.lifecycle && !(constructor.prototype instanceof Resource)) {\n throw new Error(`@trace.resource({ lifecycle: true }) requires ${constructor.name} to extend Resource`);\n }\n\n const klass = (() =>\n class extends constructor {\n constructor(...rest: any[]) {\n super(...rest);\n TRACE_PROCESSOR.createTraceResource({ constructor, annotation: options?.annotation, instance: this });\n }\n })();\n\n if (options?.lifecycle) {\n const sanitizedName = sanitizeClassName(constructor.name);\n const proto = klass.prototype as any;\n const originalOpen = proto.open;\n const originalClose = proto.close;\n\n proto.open = async function (ctx?: Context): Promise<any> {\n const self = this as any;\n\n if (self._lifecycleState !== LifecycleState.CLOSED) {\n return originalOpen.call(this, ctx);\n }\n\n const parentSpanContext = ctx?.getAttribute(TRACE_SPAN_ATTRIBUTE);\n const resourceEntry = TRACE_PROCESSOR.resourceInstanceIndex.get(this);\n const spanAttributes: Record<string, any> = {};\n if (resourceEntry) {\n spanAttributes.entryPoint = resourceEntry.sanitizedClassName;\n }\n\n const remoteSpan = TRACE_PROCESSOR.tracingBackend?.startSpan({\n name: `${sanitizedName}.lifecycle`,\n op: 'lifecycle',\n attributes: spanAttributes,\n parentContext: parentSpanContext,\n });\n self[LIFECYCLE_SPAN] = remoteSpan;\n\n let openCtx = ctx;\n if (remoteSpan?.spanContext != null) {\n const traceAttrs = { [TRACE_SPAN_ATTRIBUTE]: remoteSpan.spanContext };\n openCtx = ctx ? ctx.derive({ attributes: traceAttrs }) : new Context({ attributes: traceAttrs });\n }\n\n try {\n return await originalOpen.call(this, openCtx);\n } catch (err) {\n remoteSpan?.setError?.(err);\n remoteSpan?.end();\n self[LIFECYCLE_SPAN] = undefined;\n throw err;\n }\n };\n\n proto.close = async function (ctx?: Context): Promise<any> {\n const self = this as any;\n const remoteSpan: RemoteSpan | undefined = self[LIFECYCLE_SPAN];\n try {\n return await originalClose.call(this, ctx);\n } catch (err) {\n remoteSpan?.setError?.(err);\n throw err;\n } finally {\n if (remoteSpan) {\n remoteSpan.end();\n self[LIFECYCLE_SPAN] = undefined;\n }\n }\n };\n }\n\n Object.defineProperty(klass, 'name', { value: constructor.name });\n return klass;\n };\n\nexport interface TimeAware {\n tick(timeMs: number): void;\n}\n\nexport type InfoOptions = {\n /**\n * Value is of enum type and should be converted to string.\n *\n * Example:\n *\n * ```ts\n * @trace.info({ enum: SpaceState })\n * get state(): SpaceState { ... }\n * ```\n */\n enum?: Record<string, any>;\n\n /**\n * Max depth of the object to be included in the resource info section.\n *\n * null means no limit (a limit of 8 nested objects is still imposed).\n *\n * Default: 0 - objects will be stringified with toString.\n */\n depth?: number | null;\n\n /** When true, the property value is also set as an OTEL span attribute on every span created by this resource. */\n spanAttribute?: boolean;\n};\n\n/**\n * Marks a property or a method to be included in the resource info section.\n */\nconst info =\n (opts: InfoOptions = {}) =>\n (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => {\n getTracingContext(target).infoProperties[propertyKey] = { options: opts };\n };\n\nconst mark = (name: string) => {\n performance.mark(name);\n};\n\nexport type SpanOptions = {\n showInBrowserTimeline?: boolean;\n /** When false the span is not exported to remote OTLP collectors. Defaults to true. */\n showInRemoteTracing?: boolean;\n op?: string;\n attributes?: Record<string, any>;\n};\n\n/**\n * Decorator that creates a span for the execution duration of the decorated method.\n * Calls the TracingBackend directly; no custom TracingSpan objects.\n */\nconst span =\n ({ showInBrowserTimeline = false, showInRemoteTracing = true, op, attributes }: SpanOptions = {}) =>\n (target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<(...args: any) => any>) => {\n const method = descriptor.value!;\n\n descriptor.value = async function (this: any, ...args: any) {\n const parentCtx = args[0] instanceof Context ? args[0] : null;\n const startTs = performance.now();\n\n const parentSpanContext = parentCtx?.getAttribute(TRACE_SPAN_ATTRIBUTE);\n\n const resourceEntry = TRACE_PROCESSOR.resourceInstanceIndex.get(this);\n const className = resourceEntry?.sanitizedClassName ?? sanitizeClassName(target.constructor?.name ?? 'unknown');\n const spanName = `${className}.${propertyKey}`;\n\n const spanAttributes: Record<string, any> = {};\n if (resourceEntry) {\n spanAttributes.entryPoint = resourceEntry.sanitizedClassName;\n }\n collectSpanAttributes(this, spanAttributes);\n if (attributes) {\n for (const [key, value] of Object.entries(attributes)) {\n spanAttributes[key.startsWith('ctx.') ? key : `ctx.${key}`] = value;\n }\n }\n\n const remoteSpan = showInRemoteTracing\n ? TRACE_PROCESSOR.tracingBackend?.startSpan({\n name: spanName,\n op: op ?? 'function',\n attributes: spanAttributes,\n parentContext: parentSpanContext,\n })\n : undefined;\n\n let callArgs = args;\n if (parentCtx) {\n const childCtx =\n remoteSpan?.spanContext != null\n ? parentCtx.derive({ attributes: { [TRACE_SPAN_ATTRIBUTE]: remoteSpan.spanContext } })\n : parentCtx.derive();\n callArgs = [childCtx, ...args.slice(1)];\n }\n\n try {\n return await method.apply(this, callArgs);\n } catch (err) {\n remoteSpan?.setError?.(err);\n throw err;\n } finally {\n remoteSpan?.end();\n if (showInBrowserTimeline && typeof globalThis?.performance?.measure === 'function') {\n performance.measure(spanName, { start: startTs, end: performance.now() });\n }\n }\n };\n };\n\nconst manualSpans = new Map<string, RemoteSpan>();\nconst manualSpanTimestamps = new Map<string, { name: string; startTs: number }>();\n\nexport type ManualSpanParams = {\n id: string;\n instance: any;\n methodName: string;\n parentCtx: Context | null;\n showInBrowserTimeline?: boolean;\n showInRemoteTracing?: boolean;\n op?: string;\n attributes?: Record<string, any>;\n};\n\n/**\n * Creates a span that must be ended manually.\n *\n * Returns a child Context that carries the new span's `TRACE_SPAN_ATTRIBUTE`.\n * Callers should use the returned ctx for downstream work so that nested\n * `@trace.span` methods and RPC calls inherit this span as their parent\n * and land in the same trace (rather than starting a new root).\n *\n * When the new span cannot be created (duplicate id, no backend, or\n * `showInRemoteTracing: false`), the parentCtx is returned unchanged.\n */\nconst spanStart = (params: ManualSpanParams): Context | null => {\n if (manualSpans.has(params.id) || manualSpanTimestamps.has(params.id)) {\n return params.parentCtx;\n }\n\n const resourceEntry = TRACE_PROCESSOR.resourceInstanceIndex.get(params.instance);\n const className = resourceEntry?.sanitizedClassName ?? 'unknown';\n const spanName = `${className}.${params.methodName}`;\n\n if (params.showInBrowserTimeline) {\n manualSpanTimestamps.set(params.id, { name: spanName, startTs: performance.now() });\n }\n\n if (params.showInRemoteTracing === false || !TRACE_PROCESSOR.tracingBackend) {\n return params.parentCtx;\n }\n\n const parentSpanContext = params.parentCtx?.getAttribute(TRACE_SPAN_ATTRIBUTE);\n\n const spanAttributes: Record<string, any> = {};\n if (resourceEntry) {\n spanAttributes.entryPoint = resourceEntry.sanitizedClassName;\n }\n collectSpanAttributes(params.instance, spanAttributes);\n if (params.attributes) {\n for (const [key, value] of Object.entries(params.attributes)) {\n spanAttributes[key.startsWith('ctx.') ? key : `ctx.${key}`] = value;\n }\n }\n\n const remoteSpan = TRACE_PROCESSOR.tracingBackend.startSpan({\n name: spanName,\n op: params.op ?? 'function',\n attributes: spanAttributes,\n parentContext: parentSpanContext,\n });\n manualSpans.set(params.id, remoteSpan);\n\n if (params.parentCtx && remoteSpan.spanContext != null) {\n return params.parentCtx.derive({ attributes: { [TRACE_SPAN_ATTRIBUTE]: remoteSpan.spanContext } });\n }\n return params.parentCtx;\n};\n\n/**\n * Ends a span that was started manually.\n */\nconst spanEnd = (id: string) => {\n const remoteSpan = manualSpans.get(id);\n if (remoteSpan) {\n remoteSpan.end();\n manualSpans.delete(id);\n }\n\n const timestamps = manualSpanTimestamps.get(id);\n if (timestamps && typeof globalThis?.performance?.measure === 'function') {\n performance.measure(timestamps.name, { start: timestamps.startTs, end: performance.now() });\n manualSpanTimestamps.delete(id);\n }\n};\n\n/**\n * Attaches metrics counter to the resource.\n */\nconst metricsCounter = () => (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => {\n getTracingContext(target).metricsProperties[propertyKey] = {};\n};\n\nexport type AddLinkOptions = {};\n\nconst addLink = (parent: any, child: any, opts: AddLinkOptions = {}) => {\n TRACE_PROCESSOR.addLink(parent, child, opts);\n};\n\nexport type TraceDiagnosticProps<T> = {\n /** Unique ID. */\n id: string;\n\n /**\n * Human-readable name.\n * @defaults Defaults to `id`\n */\n name?: string;\n\n /** Function that will be called to fetch the diagnostic data. */\n fetch: () => MaybePromise<T>;\n};\n\nexport interface TraceDiagnostic {\n id: string;\n unregister(): void;\n}\n\n/**\n * Register a diagnostic that could be queried.\n */\nconst diagnostic = <T>(params: TraceDiagnosticProps<T>): TraceDiagnostic => {\n return TRACE_PROCESSOR.diagnostics.registerDiagnostic(params);\n};\n\nexport const trace = {\n addLink,\n diagnostic,\n info,\n mark,\n metricsCounter,\n resource,\n span,\n spanStart,\n spanEnd,\n metrics: TRACE_PROCESSOR.remoteMetrics,\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type InfoOptions } from './api';\n\nexport const symbolTracingContext = Symbol('dxos.tracing.context');\n\nexport type TracingContext = {\n infoProperties: Record<\n string,\n {\n options: InfoOptions;\n }\n >;\n metricsProperties: Record<string, {}>;\n};\n\nexport const getTracingContext = (target: any): TracingContext => {\n return ((target[symbolTracingContext] as TracingContext | undefined) ??= {\n infoProperties: {},\n metricsProperties: {},\n });\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { LogLevel, type LogProcessor, log } from '@dxos/log';\nimport { type LogEntry } from '@dxos/protocols/proto/dxos/client/services';\nimport { type Metric, type Resource } from '@dxos/protocols/proto/dxos/tracing';\nimport { getPrototypeSpecificInstanceId } from '@dxos/util';\n\nimport type { AddLinkOptions, TimeAware } from './api';\nimport { BUFFERED_PREFIX, BufferingTracingBackend } from './buffering-backend';\nimport { DiagnosticsManager } from './diagnostic';\nimport { DiagnosticsChannel } from './diagnostics-channel';\nimport { type BaseCounter } from './metrics';\nimport { RemoteMetrics } from './remote/metrics';\nimport { getTracingContext } from './symbols';\nimport type { RemoteSpan, StartSpanOptions, TracingBackend } from './tracing-types';\nimport { WeakRef } from './weak-ref';\n\nexport type Diagnostics = {\n resources: Record<string, Resource>;\n logs: LogEntry[];\n};\n\nexport type TraceResourceConstructorProps = {\n constructor: { new (...args: any[]): {} };\n instance: any;\n annotation?: symbol;\n};\n\nexport class ResourceEntry {\n /**\n * Sometimes bundlers mangle class names: WebFile -> WebFile2.\n *\n * We use a heuristic to remove the suffix.\n */\n public readonly sanitizedClassName: string;\n\n constructor(\n public readonly data: Resource,\n public readonly instance: WeakRef<any>,\n public readonly annotation?: symbol,\n ) {\n this.sanitizedClassName = sanitizeClassName(data.className);\n }\n\n getMetric(name: string): Metric | undefined {\n return this.data.metrics?.find((metric) => metric.name === name);\n }\n}\n\nconst MAX_RESOURCE_RECORDS = 2_000;\nconst MAX_LOG_RECORDS = 1_000;\n\nconst MAX_INFO_OBJECT_DEPTH = 8;\n\nexport class TraceProcessor {\n public readonly diagnostics = new DiagnosticsManager();\n public readonly diagnosticsChannel = new DiagnosticsChannel();\n public readonly remoteMetrics = new RemoteMetrics();\n\n readonly #bufferingBackend = new BufferingTracingBackend();\n #activeBackend: TracingBackend = this.#bufferingBackend;\n\n /**\n * Tracing backend. Initially a buffering backend that records spans;\n * once the observability package sets a real backend, the buffer is drained\n * and a thin translating wrapper is installed that resolves stale buffered\n * parent IDs still held by in-flight {@link Context} objects.\n *\n * The wrapper only allocates when a `buffered-*` parent is actually encountered;\n * the common path is a single `startsWith` check and direct passthrough.\n */\n get tracingBackend(): TracingBackend {\n return this.#activeBackend;\n }\n\n set tracingBackend(backend: TracingBackend | undefined) {\n if (!backend || backend === this.#bufferingBackend) {\n this.#bufferingBackend.clear();\n this.#activeBackend = this.#bufferingBackend;\n return;\n }\n const idMap = this.#bufferingBackend.drain(backend);\n this.#activeBackend = {\n startSpan: (options: StartSpanOptions): RemoteSpan => {\n const parent = options.parentContext;\n if (parent?.traceparent.startsWith(BUFFERED_PREFIX)) {\n const translated = idMap.get(parent.traceparent);\n if (translated) {\n return backend.startSpan({ ...options, parentContext: translated });\n }\n }\n return backend.startSpan(options);\n },\n };\n }\n\n readonly resources = new Map<number, ResourceEntry>();\n readonly resourceInstanceIndex = new WeakMap<any, ResourceEntry>();\n readonly resourceIdList: number[] = [];\n\n readonly logs: LogEntry[] = [];\n\n private _instanceTag: string | null = null;\n\n constructor() {\n log.addProcessor(this._logProcessor.bind(this));\n\n if (DiagnosticsChannel.supported) {\n this.diagnosticsChannel.serve(this.diagnostics);\n }\n this.diagnosticsChannel.unref();\n }\n\n setInstanceTag(tag: string): void {\n this._instanceTag = tag;\n this.diagnostics.setInstanceTag(tag);\n }\n\n /** @internal */\n createTraceResource(params: TraceResourceConstructorProps): void {\n const id = this.resources.size;\n\n const tracingContext = getTracingContext(Object.getPrototypeOf(params.instance));\n for (const key of Object.keys(tracingContext.metricsProperties)) {\n (params.instance[key] as BaseCounter)._assign(params.instance, key);\n }\n\n const entry = new ResourceEntry(\n {\n id,\n className: params.constructor.name,\n instanceId: getPrototypeSpecificInstanceId(params.instance),\n info: this.getResourceInfo(params.instance),\n links: [],\n metrics: this.getResourceMetrics(params.instance),\n },\n new WeakRef(params.instance),\n params.annotation,\n );\n\n this.resources.set(id, entry);\n this.resourceInstanceIndex.set(params.instance, entry);\n this.resourceIdList.push(id);\n if (this.resourceIdList.length > MAX_RESOURCE_RECORDS) {\n this._clearResources();\n }\n }\n\n // TODO(burdon): Not implemented.\n addLink(parent: any, child: any, opts: AddLinkOptions): void {}\n\n getDiagnostics(): Diagnostics {\n this.refresh();\n\n return {\n resources: Object.fromEntries(\n Array.from(this.resources.entries()).map(([id, entry]) => [\n `${entry.sanitizedClassName}#${entry.data.instanceId}`,\n entry.data,\n ]),\n ),\n logs: this.logs.filter((log) => log.level >= LogLevel.INFO),\n };\n }\n\n getResourceInfo(instance: any): Record<string, any> {\n const res: Record<string, any> = {};\n const tracingContext = getTracingContext(Object.getPrototypeOf(instance));\n for (const [key, { options }] of Object.entries(tracingContext.infoProperties)) {\n try {\n const value = typeof instance[key] === 'function' ? instance[key]() : instance[key];\n if (options.enum) {\n res[key] = options.enum[value];\n } else {\n res[key] = sanitizeValue(\n value,\n options.depth === undefined ? 1 : (options.depth ?? MAX_INFO_OBJECT_DEPTH),\n this,\n );\n }\n } catch (err: any) {\n res[key] = err.message;\n }\n }\n\n return res;\n }\n\n getResourceMetrics(instance: any): Metric[] {\n const res: Metric[] = [];\n const tracingContext = getTracingContext(Object.getPrototypeOf(instance));\n for (const [key, _opts] of Object.entries(tracingContext.metricsProperties)) {\n res.push(instance[key].getData());\n }\n\n return res;\n }\n\n getResourceId(instance: any): number | null {\n const entry = this.resourceInstanceIndex.get(instance);\n return entry ? entry.data.id : null;\n }\n\n findResourcesByClassName(className: string): ResourceEntry[] {\n return [...this.resources.values()].filter(\n (res) => res.data.className === className || res.sanitizedClassName === className,\n );\n }\n\n findResourcesByAnnotation(annotation: symbol): ResourceEntry[] {\n return [...this.resources.values()].filter((res) => res.annotation === annotation);\n }\n\n refresh(): void {\n for (const resource of this.resources.values()) {\n const instance = resource.instance.deref();\n if (!instance) {\n continue;\n }\n\n const tracingContext = getTracingContext(Object.getPrototypeOf(instance));\n const time = performance.now();\n (instance as TimeAware).tick?.(time);\n for (const key of Object.keys(tracingContext.metricsProperties)) {\n (instance[key] as BaseCounter)._tick?.(time);\n }\n\n resource.data.info = this.getResourceInfo(instance);\n resource.data.metrics = this.getResourceMetrics(instance);\n }\n }\n\n private _clearResources(): void {\n while (this.resourceIdList.length > MAX_RESOURCE_RECORDS) {\n const id = this.resourceIdList.shift()!;\n this.resources.delete(id);\n }\n }\n\n private _pushLog(log: LogEntry): void {\n this.logs.push(log);\n if (this.logs.length > MAX_LOG_RECORDS) {\n this.logs.shift();\n }\n }\n\n private _logProcessor: LogProcessor = (config, entry) => {\n switch (entry.level) {\n case LogLevel.ERROR:\n case LogLevel.WARN:\n case LogLevel.TRACE: {\n const scope = entry.meta?.S;\n const resource = this.resourceInstanceIndex.get(scope);\n if (!resource) {\n return;\n }\n\n const context: Record<string, any> = { ...entry.computedContext };\n if (entry.computedError !== undefined) {\n context.error = entry.computedError;\n }\n\n const { filename, line } = entry.computedMeta;\n const entryToPush: LogEntry = {\n level: entry.level,\n message: entry.message ?? entry.computedError ?? '',\n context,\n timestamp: new Date(entry.timestamp),\n meta: {\n file: filename ?? '',\n line: line ?? 0,\n resourceId: resource.data.id,\n },\n };\n this._pushLog(entryToPush);\n break;\n }\n default:\n }\n };\n}\n\nexport const TRACE_PROCESSOR: TraceProcessor = ((globalThis as any).TRACE_PROCESSOR ??= new TraceProcessor());\n\nconst sanitizeValue = (value: any, depth: number, traceProcessor: TraceProcessor): any => {\n switch (typeof value) {\n case 'string':\n case 'number':\n case 'boolean':\n case 'undefined':\n return value;\n case 'object':\n case 'function':\n if (value === null) {\n return value;\n }\n\n {\n const resourceEntry = traceProcessor.resourceInstanceIndex.get(value);\n if (resourceEntry) {\n return `${resourceEntry.sanitizedClassName}#${resourceEntry.data.instanceId}`;\n }\n }\n\n if (typeof value.toJSON === 'function') {\n return sanitizeValue(value.toJSON(), depth, traceProcessor);\n }\n\n if (depth > 0) {\n if (isSetLike(value)) {\n return Object.fromEntries(\n Array.from(value.entries()).map((value) => sanitizeValue(value, depth - 1, traceProcessor)),\n );\n } else if (isMapLike(value)) {\n return Object.fromEntries(\n Array.from(value.entries()).map(([key, value]) => [key, sanitizeValue(value, depth - 1, traceProcessor)]),\n );\n } else if (Array.isArray(value)) {\n return value.map((item: any) => sanitizeValue(item, depth - 1, traceProcessor));\n } else if (typeof value === 'object') {\n const res: any = {};\n for (const key of Object.keys(value)) {\n res[key] = sanitizeValue(value[key], depth - 1, traceProcessor);\n }\n return res;\n }\n }\n\n if (typeof value.truncate === 'function') {\n return value.truncate();\n }\n\n return value.toString();\n }\n};\n\nexport const sanitizeClassName = (className: string) => {\n let name = className.replace(/^_+/, '');\n const SANITIZE_REGEX = /[^_](\\d+)$/;\n const m = name.match(SANITIZE_REGEX);\n if (m) {\n name = name.slice(0, -m[1].length);\n }\n return name;\n};\n\nconst isSetLike = (value: any): value is Set<any> =>\n value instanceof Set ||\n (typeof value === 'object' && value !== null && Object.getPrototypeOf(value).constructor.name === 'ComplexSet');\n\nconst isMapLike = (value: any): value is Map<any, any> =>\n value instanceof Map ||\n (typeof value === 'object' && value !== null && Object.getPrototypeOf(value).constructor.name === 'ComplexMap');\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { type TraceContextData } from '@dxos/context';\n\nimport type { RemoteSpan, StartSpanOptions, TracingBackend } from './tracing-types';\n\nexport const BUFFERED_PREFIX = 'buffered-';\n\n/**\n * Span handle that records operations while no real OTEL backend is available.\n * Once a real backend is registered, the buffered span is replayed and a\n * {@link delegate} is set so future calls forward to the real span.\n */\nclass BufferedSpan implements RemoteSpan {\n readonly spanContext: TraceContextData;\n readonly startTime: number;\n delegate?: RemoteSpan;\n\n #ended = false;\n #endTime?: number;\n #error?: unknown;\n #hasError = false;\n\n constructor(\n readonly options: StartSpanOptions,\n id: number,\n ) {\n this.spanContext = { traceparent: `${BUFFERED_PREFIX}${id}` };\n this.startTime = Date.now();\n }\n\n end(endTime?: number): void {\n if (this.delegate) {\n this.delegate.end(endTime);\n return;\n }\n this.#endTime = endTime ?? Date.now();\n this.#ended = true;\n }\n\n setError(err: unknown): void {\n if (this.delegate) {\n this.delegate.setError?.(err);\n return;\n }\n this.#error = err;\n this.#hasError = true;\n }\n\n replay(real: RemoteSpan): void {\n if (this.#hasError) {\n real.setError?.(this.#error);\n }\n if (this.#ended) {\n real.end(this.#endTime);\n } else {\n this.delegate = real;\n }\n }\n}\n\n/**\n * A {@link TracingBackend} that buffers span operations until a real backend\n * registers. On {@link drain}, buffered spans are replayed in FIFO order with\n * parent IDs translated from synthetic `buffered-*` traceparents to real OTEL\n * IDs, preserving the trace hierarchy.\n */\nexport class BufferingTracingBackend implements TracingBackend {\n readonly #pending: BufferedSpan[] = [];\n #counter = 0;\n\n startSpan(options: StartSpanOptions): RemoteSpan {\n const span = new BufferedSpan(options, ++this.#counter);\n this.#pending.push(span);\n return span;\n }\n\n /** Discard all buffered spans without replaying them. */\n clear(): void {\n this.#pending.length = 0;\n }\n\n /**\n * Replay all buffered spans into {@link backend}.\n *\n * @returns Map from synthetic buffered traceparent to real {@link TraceContextData},\n * used by the post-drain translating wrapper to resolve stale buffered IDs\n * still present on in-flight {@link Context} objects.\n */\n drain(backend: TracingBackend): Map<string, TraceContextData> {\n const idMap = new Map<string, TraceContextData>();\n\n for (const buffered of this.#pending) {\n let parentContext = buffered.options.parentContext;\n if (parentContext && parentContext.traceparent.startsWith(BUFFERED_PREFIX)) {\n parentContext = idMap.get(parentContext.traceparent) ?? parentContext;\n }\n\n const real = backend.startSpan({ ...buffered.options, parentContext, startTime: buffered.startTime });\n\n if (real.spanContext) {\n idMap.set(buffered.spanContext.traceparent, real.spanContext);\n }\n\n buffered.replay(real);\n }\n this.#pending.length = 0;\n return idMap;\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { asyncTimeout } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\n\nimport { type TraceDiagnostic, type TraceDiagnosticProps } from './api';\nimport { createId } from './util';\n\nexport const DIAGNOSTICS_TIMEOUT = 10_000;\n\nexport type DiagnosticMetadata = {\n id: string;\n instanceId: string;\n instanceTag: string | null;\n name: string;\n};\n\nexport type DiagnosticsRequest = {\n id: string;\n instanceId?: string;\n instanceTag?: string | null;\n};\n\nexport type DiagnosticsData = {\n id: string;\n instanceId: string;\n data: any;\n error?: string;\n};\n\nexport class TraceDiagnosticImpl implements TraceDiagnostic {\n constructor(\n public id: string,\n public fetch: () => any,\n public name: string,\n private readonly _onUnregister: () => void,\n ) {}\n\n unregister(): void {\n this._onUnregister();\n }\n}\n\nexport class DiagnosticsManager {\n readonly instanceId = createId();\n\n readonly registry = new Map<string, TraceDiagnosticImpl>();\n\n private _instanceTag: string | null = null;\n\n get instanceTag(): string | null {\n return this._instanceTag;\n }\n\n setInstanceTag(tag: string): void {\n this._instanceTag = tag;\n }\n\n registerDiagnostic(params: TraceDiagnosticProps<any>): TraceDiagnostic {\n const impl = new TraceDiagnosticImpl(params.id, params.fetch, params.name ?? params.id, () => {\n if (this.registry.get(params.id) === impl) {\n this.registry.delete(params.id);\n }\n });\n this.registry.set(params.id, impl);\n return impl;\n }\n\n list(): DiagnosticMetadata[] {\n return Array.from(this.registry.values()).map((diagnostic) => ({\n id: diagnostic.id,\n instanceId: this.instanceId,\n instanceTag: this._instanceTag,\n name: diagnostic.name,\n }));\n }\n\n async fetch(request: DiagnosticsRequest): Promise<DiagnosticsData> {\n if (request.instanceId != null) {\n invariant(request.instanceId === this.instanceId, 'Invalid instance id');\n }\n const { id } = request;\n const diagnostic = this.registry.get(id);\n invariant(diagnostic, 'Diagnostic not found');\n try {\n const data = await asyncTimeout(diagnostic.fetch(), DIAGNOSTICS_TIMEOUT);\n return {\n id,\n instanceId: this.instanceId,\n data,\n };\n } catch (err: any) {\n return {\n id,\n instanceId: this.instanceId,\n data: null,\n error: err.stack,\n };\n }\n }\n}\n", "// TODO(dmaretskyi): Use UUID.\n//\n// Copyright 2024 DXOS.org\n//\n\nexport const createId = () => Math.random().toString(36).slice(2);\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { Trigger, sleep } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\n\nimport {\n DIAGNOSTICS_TIMEOUT,\n type DiagnosticMetadata,\n type DiagnosticsData,\n type DiagnosticsManager,\n type DiagnosticsRequest,\n} from './diagnostic';\nimport { createId } from './util';\n\nconst DEFAULT_CHANNEL_NAME = 'dxos-diagnostics';\n\nconst DISCOVER_TIME = 500;\n\nexport type DiagnosticChannelMessage =\n | {\n type: 'DIAGNOSTICS_DISCOVER';\n }\n | {\n type: 'DIAGNOSTICS_ANNOUNCE';\n diagnostics: DiagnosticMetadata[];\n }\n | {\n type: 'DIAGNOSTICS_FETCH';\n requestId: string;\n request: DiagnosticsRequest;\n }\n | {\n type: 'DIAGNOSTICS_RESPONSE';\n requestId: string;\n data: DiagnosticsData;\n };\n\nexport class DiagnosticsChannel {\n static get supported() {\n return globalThis.BroadcastChannel != null;\n }\n\n private _ctx = new Context();\n\n // Separate channels becauase the client and server may be in the same process.\n private readonly _serveChannel?: BroadcastChannel = undefined;\n private readonly _clientChannel?: BroadcastChannel = undefined;\n\n constructor(private readonly _channelName: string = DEFAULT_CHANNEL_NAME) {\n if (DiagnosticsChannel.supported) {\n this._serveChannel = new BroadcastChannel(_channelName);\n this._clientChannel = new BroadcastChannel(_channelName);\n }\n }\n\n destroy(): void {\n void this._ctx.dispose();\n this._serveChannel?.close();\n this._clientChannel?.close();\n }\n\n /**\n * In node.js, the channel will keep the process alive.\n * This method allows the process to exit.\n * Noop in the browser.\n */\n unref(): void {\n if (this._serveChannel && typeof (this._serveChannel as any).unref === 'function') {\n (this._serveChannel as any).unref();\n (this._clientChannel as any).unref();\n }\n }\n\n serve(manager: DiagnosticsManager): void {\n invariant(this._serveChannel);\n const listener = async (event: MessageEvent) => {\n switch (event.data.type) {\n case 'DIAGNOSTICS_DISCOVER': {\n const diagnostics = manager.list();\n this._serveChannel!.postMessage({\n type: 'DIAGNOSTICS_ANNOUNCE',\n diagnostics,\n } satisfies DiagnosticChannelMessage);\n break;\n }\n case 'DIAGNOSTICS_FETCH': {\n const { requestId, request } = event.data;\n\n if (request.instanceId != null && request.instanceId !== manager.instanceId) {\n break;\n } else if (request.instanceTag != null && request.instanceTag !== manager.instanceTag) {\n break;\n }\n\n const data = await manager.fetch(request);\n this._serveChannel!.postMessage({\n type: 'DIAGNOSTICS_RESPONSE',\n requestId,\n data,\n } satisfies DiagnosticChannelMessage);\n break;\n }\n }\n };\n\n this._serveChannel.addEventListener('message', listener);\n this._ctx.onDispose(() => this._serveChannel!.removeEventListener('message', listener));\n }\n\n async discover(): Promise<DiagnosticMetadata[]> {\n invariant(this._clientChannel);\n const diagnostics: DiagnosticMetadata[] = [];\n\n const collector = (event: MessageEvent) => {\n const data = event.data as DiagnosticChannelMessage;\n switch (data.type) {\n case 'DIAGNOSTICS_ANNOUNCE':\n diagnostics.push(...data.diagnostics);\n break;\n }\n };\n\n try {\n this._clientChannel.addEventListener('message', collector);\n this._clientChannel.postMessage({ type: 'DIAGNOSTICS_DISCOVER' } satisfies DiagnosticChannelMessage);\n\n await sleep(DISCOVER_TIME);\n\n // Dedup.\n const result: DiagnosticMetadata[] = [];\n for (const diagnostic of diagnostics) {\n if (!result.some((d) => d.id === diagnostic.id && d.instanceId === diagnostic.instanceId)) {\n result.push(diagnostic);\n }\n }\n\n return diagnostics;\n } finally {\n this._clientChannel.removeEventListener('message', collector);\n }\n }\n\n async fetch(request: DiagnosticsRequest): Promise<DiagnosticsData> {\n invariant(this._clientChannel);\n const requestId = createId();\n\n const trigger = new Trigger<DiagnosticsData>();\n const listener = (event: MessageEvent) => {\n const data = event.data as DiagnosticChannelMessage;\n if (data.type === 'DIAGNOSTICS_RESPONSE' && data.requestId === requestId) {\n trigger.wake(data.data);\n }\n };\n\n try {\n this._clientChannel.addEventListener('message', listener);\n this._clientChannel.postMessage({\n type: 'DIAGNOSTICS_FETCH',\n requestId,\n request,\n } satisfies DiagnosticChannelMessage);\n\n // NOTE: Must have await keyword in this block.\n const result = await trigger.wait({ timeout: DIAGNOSTICS_TIMEOUT });\n\n return result;\n } finally {\n this._clientChannel.removeEventListener('message', listener);\n }\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\ntype TagType = number | string | boolean | null | undefined;\n\nexport interface MetricData {\n unit?: string;\n tags?: Record<string, TagType>;\n timestamp?: number;\n}\n\ninterface MetricsMethods {\n /**\n * Adds a value to a counter metric\n */\n increment(name: string, value?: number, data?: MetricData): void;\n /**\n * Adds a value to a distribution metric\n */\n distribution(name: string, value: number, data?: MetricData): void;\n /**\n * Adds a value to a set metric. Value must be a string or integer.\n */\n set(name: string, value: number | string, data?: MetricData): void;\n /**\n * Adds a value to a gauge metric\n */\n gauge(name: string, value: number, data?: MetricData): void;\n}\n\n/**\n * Allows metrics to be recorded within SDK code without requiring specific consumers.\n */\nexport class RemoteMetrics implements MetricsMethods {\n private _metrics = new Set<MetricsMethods>();\n\n registerProcessor(processor: MetricsMethods): void {\n this._metrics.add(processor);\n }\n\n increment(name: string, value?: number, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.increment(name, value, data));\n }\n\n distribution(name: string, value: number, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.distribution(name, value, data));\n }\n\n set(name: string, value: number | string, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.set(name, value, data));\n }\n\n gauge(name: string, value: number, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.gauge(name, value, data));\n }\n}\n", "// Workerd does not support WeakRef\n\n//\n// Copyright 2024 DXOS.org\n//\n\nclass WeakRefMock<T> {\n // eslint-disable-next-line @typescript-eslint/no-useless-constructor\n constructor(target: T) {\n // do nothing\n }\n\n deref(): T | undefined {\n return undefined;\n }\n}\n\nexport const WeakRef = globalThis.WeakRef ?? WeakRefMock;\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nexport abstract class BaseCounter {\n /**\n * @internal\n */\n _instance: any;\n\n name?: string;\n\n /**\n * @internal\n */\n _assign(instance: any, name: string): void {\n this._instance = instance;\n this.name = name;\n }\n\n abstract getData(): Metric;\n\n _tick(time: number): void {}\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nexport class UnaryCounter extends BaseCounter {\n value = 0;\n units?: string;\n\n constructor({ units }: { units?: string } = {}) {\n super();\n this.units = units;\n }\n\n inc(by = 1): void {\n this.value += by;\n }\n\n getData(): Metric {\n return {\n name: this.name!,\n counter: {\n value: this.value,\n units: this.units,\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nconst MAX_BUCKETS = 60;\n\nexport class TimeSeriesCounter extends BaseCounter {\n private _currentValue = 0;\n private _totalValue = 0;\n private _buckets: number[] = [];\n units?: string;\n\n constructor({ units }: { units?: string } = {}) {\n super();\n this.units = units;\n }\n\n inc(by = 1): void {\n this._currentValue += by;\n this._totalValue += by;\n }\n\n override _tick(time: number): void {\n this._buckets.push(this._currentValue);\n if (this._buckets.length > MAX_BUCKETS) {\n this._buckets.shift();\n }\n this._currentValue = 0;\n }\n\n override getData(): Metric {\n return {\n name: this.name!,\n timeSeries: {\n tracks: [\n {\n name: this.name!,\n units: this.units,\n points: this._buckets.map((value, index) => ({\n value,\n })),\n total: this._totalValue,\n },\n ],\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nconst MAX_BUCKETS = 60;\n\nexport class TimeUsageCounter extends BaseCounter {\n private _currentValue = 0;\n private _totalValue = 0;\n private _buckets: number[] = [];\n\n private _lastTickTime = performance.now();\n\n record(time: number): void {\n this._currentValue += time;\n this._totalValue += time;\n }\n\n beginRecording(): { end: () => void } {\n const start = performance.now();\n return {\n end: () => {\n const end = performance.now();\n this.record(end - start);\n },\n };\n }\n\n override _tick(time: number): void {\n const delta = time - this._lastTickTime;\n this._lastTickTime = time;\n\n const percentage = (this._currentValue / delta) * 100;\n this._buckets.push(percentage);\n if (this._buckets.length > MAX_BUCKETS) {\n this._buckets.shift();\n }\n this._currentValue = 0;\n }\n\n override getData(): Metric {\n return {\n name: this.name!,\n timeSeries: {\n tracks: [\n {\n name: this.name!,\n units: '%',\n points: this._buckets.map((value, index) => ({\n value,\n })),\n total: this._totalValue,\n },\n ],\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nexport class MapCounter extends BaseCounter {\n values = new Map<string, number>();\n units?: string;\n\n constructor({ units }: { units?: string } = {}) {\n super();\n this.units = units;\n }\n\n inc(key: string, by = 1): void {\n const prev = this.values.get(key) ?? 0;\n this.values.set(key, prev + by);\n }\n\n getData(): Metric {\n return {\n name: this.name!,\n multiCounter: {\n records: Array.from(this.values.entries()).map(([key, value]) => ({\n key,\n value,\n })),\n units: this.units,\n },\n };\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nexport class CustomCounter extends BaseCounter {\n constructor(private readonly _getData: () => object) {\n super();\n }\n\n override getData(): Metric {\n return {\n name: this.name!,\n custom: {\n payload: this._getData(),\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { trace } from './api';\n\nexport * from './api';\nexport * from './symbols';\nexport * from './trace-processor';\nexport * from './tracing-types';\nexport * from './metrics';\nexport * from './diagnostic';\nexport * from './diagnostics-channel';\nexport * from './remote/metrics';\n\ntrace.diagnostic({\n id: 'process-info',\n name: 'Process Info',\n fetch: async () => {\n return {\n platform: globalThis.process?.platform,\n arch: globalThis.process?.arch,\n versions: globalThis.process?.versions,\n href: globalThis.location?.href,\n };\n },\n});\n"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { Context, LifecycleState, Resource, TRACE_SPAN_ATTRIBUTE } from '@dxos/context';\nimport { type MaybePromise } from '@dxos/util';\n\nimport { getTracingContext } from './symbols';\nimport { TRACE_PROCESSOR, sanitizeClassName } from './trace-processor';\nimport type { RemoteSpan } from './tracing-types';\n\nconst LIFECYCLE_SPAN = Symbol('dxos.tracing.lifecycle-span');\n\n/** localStorage key that switches the browser OTEL sampler from 30% to 100%. */\nexport const TRACE_ALL_KEY = 'dxos.debug.traceAll';\n\n/**\n * Reads `@trace.info({ spanAttribute: true })` properties from the instance\n * and writes them into the span attributes map.\n */\nconst collectSpanAttributes = (instance: any, spanAttributes: Record<string, any>) => {\n const proto = Object.getPrototypeOf(instance);\n if (!proto) {\n return;\n }\n const tracingContext = getTracingContext(proto);\n for (const [key, { options }] of Object.entries(tracingContext.infoProperties)) {\n if (!options.spanAttribute) {\n continue;\n }\n try {\n const value = typeof instance[key] === 'function' ? instance[key]() : instance[key];\n if (value != null) {\n const resolved = options.enum ? options.enum[value] : String(value);\n spanAttributes[`ctx.${key}`] = resolved;\n }\n } catch {\n // Skip properties that throw (e.g. uninitialized).\n }\n }\n};\n\nexport type ResourceOptions = {\n annotation?: symbol;\n /**\n * Start a lifecycle span on `open()` and end it on `close()`.\n * `this._ctx` carries the lifecycle span's trace context, so background work\n * (subscriptions, timers) becomes children of the lifecycle span.\n * Direct calls within `_open` use the `_open` span's context as usual.\n * Requires the class to extend {@link Resource}.\n */\n lifecycle?: boolean;\n};\n\n/**\n * Annotates a class as a tracked resource.\n */\nconst resource =\n (options?: ResourceOptions) =>\n <T extends { new (...args: any[]): {} }>(constructor: T) => {\n if (options?.lifecycle && !(constructor.prototype instanceof Resource)) {\n throw new Error(`@trace.resource({ lifecycle: true }) requires ${constructor.name} to extend Resource`);\n }\n\n const klass = (() =>\n class extends constructor {\n constructor(...rest: any[]) {\n super(...rest);\n TRACE_PROCESSOR.createTraceResource({ constructor, annotation: options?.annotation, instance: this });\n }\n })();\n\n if (options?.lifecycle) {\n const sanitizedName = sanitizeClassName(constructor.name);\n const proto = klass.prototype as any;\n const originalOpen = proto.open;\n const originalClose = proto.close;\n\n proto.open = async function (ctx?: Context): Promise<any> {\n const self = this as any;\n\n if (self._lifecycleState !== LifecycleState.CLOSED) {\n return originalOpen.call(this, ctx);\n }\n\n const parentSpanContext = ctx?.getAttribute(TRACE_SPAN_ATTRIBUTE);\n const resourceEntry = TRACE_PROCESSOR.resourceInstanceIndex.get(this);\n const spanAttributes: Record<string, any> = {};\n if (resourceEntry) {\n spanAttributes.entryPoint = resourceEntry.sanitizedClassName;\n }\n\n const remoteSpan = TRACE_PROCESSOR.tracingBackend?.startSpan({\n name: `${sanitizedName}.lifecycle`,\n op: 'lifecycle',\n attributes: spanAttributes,\n parentContext: parentSpanContext,\n });\n self[LIFECYCLE_SPAN] = remoteSpan;\n\n let openCtx = ctx;\n if (remoteSpan?.spanContext != null) {\n const traceAttrs = { [TRACE_SPAN_ATTRIBUTE]: remoteSpan.spanContext };\n openCtx = ctx ? ctx.derive({ attributes: traceAttrs }) : new Context({ attributes: traceAttrs });\n }\n\n try {\n return await originalOpen.call(this, openCtx);\n } catch (err) {\n remoteSpan?.setError?.(err);\n remoteSpan?.end();\n self[LIFECYCLE_SPAN] = undefined;\n throw err;\n }\n };\n\n proto.close = async function (ctx?: Context): Promise<any> {\n const self = this as any;\n const remoteSpan: RemoteSpan | undefined = self[LIFECYCLE_SPAN];\n try {\n return await originalClose.call(this, ctx);\n } catch (err) {\n remoteSpan?.setError?.(err);\n throw err;\n } finally {\n if (remoteSpan) {\n remoteSpan.end();\n self[LIFECYCLE_SPAN] = undefined;\n }\n }\n };\n }\n\n Object.defineProperty(klass, 'name', { value: constructor.name });\n return klass;\n };\n\nexport interface TimeAware {\n tick(timeMs: number): void;\n}\n\nexport type InfoOptions = {\n /**\n * Value is of enum type and should be converted to string.\n *\n * Example:\n *\n * ```ts\n * @trace.info({ enum: SpaceState })\n * get state(): SpaceState { ... }\n * ```\n */\n enum?: Record<string, any>;\n\n /**\n * Max depth of the object to be included in the resource info section.\n *\n * null means no limit (a limit of 8 nested objects is still imposed).\n *\n * Default: 0 - objects will be stringified with toString.\n */\n depth?: number | null;\n\n /** When true, the property value is also set as an OTEL span attribute on every span created by this resource. */\n spanAttribute?: boolean;\n};\n\n/**\n * Marks a property or a method to be included in the resource info section.\n */\nconst info =\n (opts: InfoOptions = {}) =>\n (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => {\n getTracingContext(target).infoProperties[propertyKey] = { options: opts };\n };\n\nconst mark = (name: string) => {\n performance.mark(name);\n};\n\nexport type SpanOptions = {\n showInBrowserTimeline?: boolean;\n /** When false the span is not exported to remote OTLP collectors. Defaults to true. */\n showInRemoteTracing?: boolean;\n op?: string;\n attributes?: Record<string, any>;\n};\n\n/**\n * Decorator that creates a span for the execution duration of the decorated method.\n * Calls the TracingBackend directly; no custom TracingSpan objects.\n */\nconst span =\n ({ showInBrowserTimeline = false, showInRemoteTracing = true, op, attributes }: SpanOptions = {}) =>\n (target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<(...args: any) => any>) => {\n const method = descriptor.value!;\n\n descriptor.value = async function (this: any, ...args: any) {\n const parentCtx = args[0] instanceof Context ? args[0] : null;\n const startTs = performance.now();\n\n const parentSpanContext = parentCtx?.getAttribute(TRACE_SPAN_ATTRIBUTE);\n\n const resourceEntry = TRACE_PROCESSOR.resourceInstanceIndex.get(this);\n const className = resourceEntry?.sanitizedClassName ?? sanitizeClassName(target.constructor?.name ?? 'unknown');\n const spanName = `${className}.${propertyKey}`;\n\n const spanAttributes: Record<string, any> = {};\n if (resourceEntry) {\n spanAttributes.entryPoint = resourceEntry.sanitizedClassName;\n }\n collectSpanAttributes(this, spanAttributes);\n if (attributes) {\n for (const [key, value] of Object.entries(attributes)) {\n spanAttributes[key.startsWith('ctx.') ? key : `ctx.${key}`] = value;\n }\n }\n\n const remoteSpan = showInRemoteTracing\n ? TRACE_PROCESSOR.tracingBackend?.startSpan({\n name: spanName,\n op: op ?? 'function',\n attributes: spanAttributes,\n parentContext: parentSpanContext,\n })\n : undefined;\n\n let callArgs = args;\n if (parentCtx) {\n const childCtx =\n remoteSpan?.spanContext != null\n ? parentCtx.derive({ attributes: { [TRACE_SPAN_ATTRIBUTE]: remoteSpan.spanContext } })\n : parentCtx.derive();\n callArgs = [childCtx, ...args.slice(1)];\n }\n\n try {\n return await method.apply(this, callArgs);\n } catch (err) {\n remoteSpan?.setError?.(err);\n throw err;\n } finally {\n remoteSpan?.end();\n if (showInBrowserTimeline && typeof globalThis?.performance?.measure === 'function') {\n performance.measure(spanName, { start: startTs, end: performance.now() });\n }\n }\n };\n };\n\nconst manualSpans = new Map<string, RemoteSpan>();\nconst manualSpanTimestamps = new Map<string, { name: string; startTs: number }>();\n\nexport type ManualSpanParams = {\n id: string;\n instance: any;\n methodName: string;\n parentCtx: Context | null;\n showInBrowserTimeline?: boolean;\n showInRemoteTracing?: boolean;\n op?: string;\n attributes?: Record<string, any>;\n};\n\n/**\n * Creates a span that must be ended manually.\n *\n * Returns a child Context that carries the new span's `TRACE_SPAN_ATTRIBUTE`.\n * Callers should use the returned ctx for downstream work so that nested\n * `@trace.span` methods and RPC calls inherit this span as their parent\n * and land in the same trace (rather than starting a new root).\n *\n * When the new span cannot be created (duplicate id, no backend, or\n * `showInRemoteTracing: false`), the parentCtx is returned unchanged.\n */\nconst spanStart = (params: ManualSpanParams): Context | null => {\n if (manualSpans.has(params.id) || manualSpanTimestamps.has(params.id)) {\n return params.parentCtx;\n }\n\n const resourceEntry = TRACE_PROCESSOR.resourceInstanceIndex.get(params.instance);\n const className = resourceEntry?.sanitizedClassName ?? 'unknown';\n const spanName = `${className}.${params.methodName}`;\n\n if (params.showInBrowserTimeline) {\n manualSpanTimestamps.set(params.id, { name: spanName, startTs: performance.now() });\n }\n\n if (params.showInRemoteTracing === false || !TRACE_PROCESSOR.tracingBackend) {\n return params.parentCtx;\n }\n\n const parentSpanContext = params.parentCtx?.getAttribute(TRACE_SPAN_ATTRIBUTE);\n\n const spanAttributes: Record<string, any> = {};\n if (resourceEntry) {\n spanAttributes.entryPoint = resourceEntry.sanitizedClassName;\n }\n collectSpanAttributes(params.instance, spanAttributes);\n if (params.attributes) {\n for (const [key, value] of Object.entries(params.attributes)) {\n spanAttributes[key.startsWith('ctx.') ? key : `ctx.${key}`] = value;\n }\n }\n\n const remoteSpan = TRACE_PROCESSOR.tracingBackend.startSpan({\n name: spanName,\n op: params.op ?? 'function',\n attributes: spanAttributes,\n parentContext: parentSpanContext,\n });\n manualSpans.set(params.id, remoteSpan);\n\n if (params.parentCtx && remoteSpan.spanContext != null) {\n return params.parentCtx.derive({ attributes: { [TRACE_SPAN_ATTRIBUTE]: remoteSpan.spanContext } });\n }\n return params.parentCtx;\n};\n\n/**\n * Ends a span that was started manually.\n */\nconst spanEnd = (id: string) => {\n const remoteSpan = manualSpans.get(id);\n if (remoteSpan) {\n remoteSpan.end();\n manualSpans.delete(id);\n }\n\n const timestamps = manualSpanTimestamps.get(id);\n if (timestamps && typeof globalThis?.performance?.measure === 'function') {\n performance.measure(timestamps.name, { start: timestamps.startTs, end: performance.now() });\n manualSpanTimestamps.delete(id);\n }\n};\n\n/**\n * Attaches metrics counter to the resource.\n */\nconst metricsCounter = () => (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => {\n getTracingContext(target).metricsProperties[propertyKey] = {};\n};\n\nexport type AddLinkOptions = {};\n\nconst addLink = (parent: any, child: any, opts: AddLinkOptions = {}) => {\n TRACE_PROCESSOR.addLink(parent, child, opts);\n};\n\nexport type TraceDiagnosticProps<T> = {\n /** Unique ID. */\n id: string;\n\n /**\n * Human-readable name.\n * @defaults Defaults to `id`\n */\n name?: string;\n\n /** Function that will be called to fetch the diagnostic data. */\n fetch: () => MaybePromise<T>;\n};\n\nexport interface TraceDiagnostic {\n id: string;\n unregister(): void;\n}\n\n/**\n * Register a diagnostic that could be queried.\n */\nconst diagnostic = <T>(params: TraceDiagnosticProps<T>): TraceDiagnostic => {\n return TRACE_PROCESSOR.diagnostics.registerDiagnostic(params);\n};\n\nexport const trace = {\n addLink,\n diagnostic,\n info,\n mark,\n metricsCounter,\n resource,\n span,\n spanStart,\n spanEnd,\n metrics: TRACE_PROCESSOR.remoteMetrics,\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type InfoOptions } from './api';\n\nexport const symbolTracingContext = Symbol('dxos.tracing.context');\n\nexport type TracingContext = {\n infoProperties: Record<\n string,\n {\n options: InfoOptions;\n }\n >;\n metricsProperties: Record<string, {}>;\n};\n\nexport const getTracingContext = (target: any): TracingContext => {\n return ((target[symbolTracingContext] as TracingContext | undefined) ??= {\n infoProperties: {},\n metricsProperties: {},\n });\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { LogLevel, type LogProcessor, log } from '@dxos/log';\nimport { type LogEntry } from '@dxos/protocols/proto/dxos/client/services';\nimport { type Metric, type Resource } from '@dxos/protocols/proto/dxos/tracing';\nimport { getPrototypeSpecificInstanceId } from '@dxos/util';\n\nimport type { AddLinkOptions, TimeAware } from './api';\nimport { BUFFERED_PREFIX, BufferingTracingBackend } from './buffering-backend';\nimport { DiagnosticsManager } from './diagnostic';\nimport { DiagnosticsChannel } from './diagnostics-channel';\nimport { type BaseCounter } from './metrics';\nimport { RemoteMetrics } from './remote/metrics';\nimport { getTracingContext } from './symbols';\nimport type { RemoteSpan, StartSpanOptions, TracingBackend } from './tracing-types';\nimport { WeakRef } from './weak-ref';\n\nexport type Diagnostics = {\n resources: Record<string, Resource>;\n logs: LogEntry[];\n};\n\nexport type TraceResourceConstructorProps = {\n constructor: { new (...args: any[]): {} };\n instance: any;\n annotation?: symbol;\n};\n\nexport class ResourceEntry {\n /**\n * Sometimes bundlers mangle class names: WebFile -> WebFile2.\n *\n * We use a heuristic to remove the suffix.\n */\n public readonly sanitizedClassName: string;\n\n constructor(\n public readonly data: Resource,\n public readonly instance: WeakRef<any>,\n public readonly annotation?: symbol,\n ) {\n this.sanitizedClassName = sanitizeClassName(data.className);\n }\n\n getMetric(name: string): Metric | undefined {\n return this.data.metrics?.find((metric) => metric.name === name);\n }\n}\n\nconst MAX_RESOURCE_RECORDS = 2_000;\nconst MAX_LOG_RECORDS = 1_000;\n\nconst MAX_INFO_OBJECT_DEPTH = 8;\n\nexport class TraceProcessor {\n public readonly diagnostics = new DiagnosticsManager();\n public readonly diagnosticsChannel = new DiagnosticsChannel();\n public readonly remoteMetrics = new RemoteMetrics();\n\n readonly #bufferingBackend = new BufferingTracingBackend();\n #activeBackend: TracingBackend = this.#bufferingBackend;\n\n /**\n * Tracing backend. Initially a buffering backend that records spans;\n * once the observability package sets a real backend, the buffer is drained\n * and a thin translating wrapper is installed that resolves stale buffered\n * parent IDs still held by in-flight {@link Context} objects.\n *\n * The wrapper only allocates when a `buffered-*` parent is actually encountered;\n * the common path is a single `startsWith` check and direct passthrough.\n */\n get tracingBackend(): TracingBackend {\n return this.#activeBackend;\n }\n\n set tracingBackend(backend: TracingBackend | undefined) {\n if (!backend || backend === this.#bufferingBackend) {\n this.#bufferingBackend.clear();\n this.#activeBackend = this.#bufferingBackend;\n return;\n }\n const idMap = this.#bufferingBackend.drain(backend);\n this.#activeBackend = {\n startSpan: (options: StartSpanOptions): RemoteSpan => {\n const parent = options.parentContext;\n if (parent?.traceparent.startsWith(BUFFERED_PREFIX)) {\n const translated = idMap.get(parent.traceparent);\n if (translated) {\n return backend.startSpan({ ...options, parentContext: translated });\n }\n }\n return backend.startSpan(options);\n },\n };\n }\n\n readonly resources = new Map<number, ResourceEntry>();\n readonly resourceInstanceIndex = new WeakMap<any, ResourceEntry>();\n readonly resourceIdList: number[] = [];\n\n readonly logs: LogEntry[] = [];\n\n private _instanceTag: string | null = null;\n\n constructor() {\n log.addProcessor(this._logProcessor.bind(this));\n\n if (DiagnosticsChannel.supported) {\n this.diagnosticsChannel.serve(this.diagnostics);\n }\n this.diagnosticsChannel.unref();\n }\n\n setInstanceTag(tag: string): void {\n this._instanceTag = tag;\n this.diagnostics.setInstanceTag(tag);\n }\n\n /** @internal */\n createTraceResource(params: TraceResourceConstructorProps): void {\n const id = this.resources.size;\n\n const tracingContext = getTracingContext(Object.getPrototypeOf(params.instance));\n for (const key of Object.keys(tracingContext.metricsProperties)) {\n (params.instance[key] as BaseCounter)._assign(params.instance, key);\n }\n\n const entry = new ResourceEntry(\n {\n id,\n className: params.constructor.name,\n instanceId: getPrototypeSpecificInstanceId(params.instance),\n info: this.getResourceInfo(params.instance),\n links: [],\n metrics: this.getResourceMetrics(params.instance),\n },\n new WeakRef(params.instance),\n params.annotation,\n );\n\n this.resources.set(id, entry);\n this.resourceInstanceIndex.set(params.instance, entry);\n this.resourceIdList.push(id);\n if (this.resourceIdList.length > MAX_RESOURCE_RECORDS) {\n this._clearResources();\n }\n }\n\n // TODO(burdon): Not implemented.\n addLink(parent: any, child: any, opts: AddLinkOptions): void {}\n\n getDiagnostics(): Diagnostics {\n this.refresh();\n\n return {\n resources: Object.fromEntries(\n Array.from(this.resources.entries()).map(([id, entry]) => [\n `${entry.sanitizedClassName}#${entry.data.instanceId}`,\n entry.data,\n ]),\n ),\n logs: this.logs.filter((log) => log.level >= LogLevel.INFO),\n };\n }\n\n getResourceInfo(instance: any): Record<string, any> {\n const res: Record<string, any> = {};\n const tracingContext = getTracingContext(Object.getPrototypeOf(instance));\n for (const [key, { options }] of Object.entries(tracingContext.infoProperties)) {\n try {\n const value = typeof instance[key] === 'function' ? instance[key]() : instance[key];\n if (options.enum) {\n res[key] = options.enum[value];\n } else {\n res[key] = sanitizeValue(\n value,\n options.depth === undefined ? 1 : (options.depth ?? MAX_INFO_OBJECT_DEPTH),\n this,\n );\n }\n } catch (err: any) {\n res[key] = err.message;\n }\n }\n\n return res;\n }\n\n getResourceMetrics(instance: any): Metric[] {\n const res: Metric[] = [];\n const tracingContext = getTracingContext(Object.getPrototypeOf(instance));\n for (const [key, _opts] of Object.entries(tracingContext.metricsProperties)) {\n res.push(instance[key].getData());\n }\n\n return res;\n }\n\n getResourceId(instance: any): number | null {\n const entry = this.resourceInstanceIndex.get(instance);\n return entry ? entry.data.id : null;\n }\n\n findResourcesByClassName(className: string): ResourceEntry[] {\n return [...this.resources.values()].filter(\n (res) => res.data.className === className || res.sanitizedClassName === className,\n );\n }\n\n findResourcesByAnnotation(annotation: symbol): ResourceEntry[] {\n return [...this.resources.values()].filter((res) => res.annotation === annotation);\n }\n\n refresh(): void {\n for (const resource of this.resources.values()) {\n const instance = resource.instance.deref();\n if (!instance) {\n continue;\n }\n\n const tracingContext = getTracingContext(Object.getPrototypeOf(instance));\n const time = performance.now();\n (instance as TimeAware).tick?.(time);\n for (const key of Object.keys(tracingContext.metricsProperties)) {\n (instance[key] as BaseCounter)._tick?.(time);\n }\n\n resource.data.info = this.getResourceInfo(instance);\n resource.data.metrics = this.getResourceMetrics(instance);\n }\n }\n\n private _clearResources(): void {\n while (this.resourceIdList.length > MAX_RESOURCE_RECORDS) {\n const id = this.resourceIdList.shift()!;\n this.resources.delete(id);\n }\n }\n\n private _pushLog(log: LogEntry): void {\n this.logs.push(log);\n if (this.logs.length > MAX_LOG_RECORDS) {\n this.logs.shift();\n }\n }\n\n private _logProcessor: LogProcessor = (config, entry) => {\n switch (entry.level) {\n case LogLevel.ERROR:\n case LogLevel.WARN:\n case LogLevel.TRACE: {\n const scope = entry.meta?.S;\n const resource = this.resourceInstanceIndex.get(scope);\n if (!resource) {\n return;\n }\n\n const context: Record<string, any> = { ...entry.computedContext };\n if (entry.computedError !== undefined) {\n context.error = entry.computedError;\n }\n\n const { filename, line } = entry.computedMeta;\n const entryToPush: LogEntry = {\n level: entry.level,\n message: entry.message ?? entry.computedError ?? '',\n context,\n timestamp: new Date(entry.timestamp),\n meta: {\n file: filename ?? '',\n line: line ?? 0,\n resourceId: resource.data.id,\n },\n };\n this._pushLog(entryToPush);\n break;\n }\n default:\n }\n };\n}\n\nexport const TRACE_PROCESSOR: TraceProcessor = ((globalThis as any).TRACE_PROCESSOR ??= new TraceProcessor());\n\nconst sanitizeValue = (value: any, depth: number, traceProcessor: TraceProcessor): any => {\n switch (typeof value) {\n case 'string':\n case 'number':\n case 'boolean':\n case 'undefined':\n return value;\n case 'object':\n case 'function':\n if (value === null) {\n return value;\n }\n\n {\n const resourceEntry = traceProcessor.resourceInstanceIndex.get(value);\n if (resourceEntry) {\n return `${resourceEntry.sanitizedClassName}#${resourceEntry.data.instanceId}`;\n }\n }\n\n if (typeof value.toJSON === 'function') {\n return sanitizeValue(value.toJSON(), depth, traceProcessor);\n }\n\n if (depth > 0) {\n if (isSetLike(value)) {\n return Object.fromEntries(\n Array.from(value.entries()).map((value) => sanitizeValue(value, depth - 1, traceProcessor)),\n );\n } else if (isMapLike(value)) {\n return Object.fromEntries(\n Array.from(value.entries()).map(([key, value]) => [key, sanitizeValue(value, depth - 1, traceProcessor)]),\n );\n } else if (Array.isArray(value)) {\n return value.map((item: any) => sanitizeValue(item, depth - 1, traceProcessor));\n } else if (typeof value === 'object') {\n const res: any = {};\n for (const key of Object.keys(value)) {\n res[key] = sanitizeValue(value[key], depth - 1, traceProcessor);\n }\n return res;\n }\n }\n\n if (typeof value.truncate === 'function') {\n return value.truncate();\n }\n\n return value.toString();\n }\n};\n\nexport const sanitizeClassName = (className: string) => {\n let name = className.replace(/^_+/, '');\n const SANITIZE_REGEX = /[^_](\\d+)$/;\n const m = name.match(SANITIZE_REGEX);\n if (m) {\n name = name.slice(0, -m[1].length);\n }\n return name;\n};\n\nconst isSetLike = (value: any): value is Set<any> =>\n value instanceof Set ||\n (typeof value === 'object' && value !== null && Object.getPrototypeOf(value).constructor.name === 'ComplexSet');\n\nconst isMapLike = (value: any): value is Map<any, any> =>\n value instanceof Map ||\n (typeof value === 'object' && value !== null && Object.getPrototypeOf(value).constructor.name === 'ComplexMap');\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { type TraceContextData } from '@dxos/context';\n\nimport type { RemoteSpan, StartSpanOptions, TracingBackend } from './tracing-types';\n\nexport const BUFFERED_PREFIX = 'buffered-';\n\n/**\n * Span handle that records operations while no real OTEL backend is available.\n * Once a real backend is registered, the buffered span is replayed and a\n * {@link delegate} is set so future calls forward to the real span.\n */\nclass BufferedSpan implements RemoteSpan {\n readonly spanContext: TraceContextData;\n readonly startTime: number;\n delegate?: RemoteSpan;\n\n #ended = false;\n #endTime?: number;\n #error?: unknown;\n #hasError = false;\n\n constructor(\n readonly options: StartSpanOptions,\n id: number,\n ) {\n this.spanContext = { traceparent: `${BUFFERED_PREFIX}${id}` };\n this.startTime = Date.now();\n }\n\n end(endTime?: number): void {\n if (this.delegate) {\n this.delegate.end(endTime);\n return;\n }\n this.#endTime = endTime ?? Date.now();\n this.#ended = true;\n }\n\n setError(err: unknown): void {\n if (this.delegate) {\n this.delegate.setError?.(err);\n return;\n }\n this.#error = err;\n this.#hasError = true;\n }\n\n replay(real: RemoteSpan): void {\n if (this.#hasError) {\n real.setError?.(this.#error);\n }\n if (this.#ended) {\n real.end(this.#endTime);\n } else {\n this.delegate = real;\n }\n }\n}\n\n/**\n * A {@link TracingBackend} that buffers span operations until a real backend\n * registers. On {@link drain}, buffered spans are replayed in FIFO order with\n * parent IDs translated from synthetic `buffered-*` traceparents to real OTEL\n * IDs, preserving the trace hierarchy.\n */\nexport class BufferingTracingBackend implements TracingBackend {\n readonly #pending: BufferedSpan[] = [];\n #counter = 0;\n\n startSpan(options: StartSpanOptions): RemoteSpan {\n const span = new BufferedSpan(options, ++this.#counter);\n this.#pending.push(span);\n return span;\n }\n\n /** Discard all buffered spans without replaying them. */\n clear(): void {\n this.#pending.length = 0;\n }\n\n /**\n * Replay all buffered spans into {@link backend}.\n *\n * @returns Map from synthetic buffered traceparent to real {@link TraceContextData},\n * used by the post-drain translating wrapper to resolve stale buffered IDs\n * still present on in-flight {@link Context} objects.\n */\n drain(backend: TracingBackend): Map<string, TraceContextData> {\n const idMap = new Map<string, TraceContextData>();\n\n for (const buffered of this.#pending) {\n let parentContext = buffered.options.parentContext;\n if (parentContext && parentContext.traceparent.startsWith(BUFFERED_PREFIX)) {\n parentContext = idMap.get(parentContext.traceparent) ?? parentContext;\n }\n\n const real = backend.startSpan({ ...buffered.options, parentContext, startTime: buffered.startTime });\n\n if (real.spanContext) {\n idMap.set(buffered.spanContext.traceparent, real.spanContext);\n }\n\n buffered.replay(real);\n }\n this.#pending.length = 0;\n return idMap;\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { asyncTimeout } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\n\nimport { type TraceDiagnostic, type TraceDiagnosticProps } from './api';\nimport { createId } from './util';\n\nexport const DIAGNOSTICS_TIMEOUT = 10_000;\n\nexport type DiagnosticMetadata = {\n id: string;\n instanceId: string;\n instanceTag: string | null;\n name: string;\n};\n\nexport type DiagnosticsRequest = {\n id: string;\n instanceId?: string;\n instanceTag?: string | null;\n};\n\nexport type DiagnosticsData = {\n id: string;\n instanceId: string;\n data: any;\n error?: string;\n};\n\nexport class TraceDiagnosticImpl implements TraceDiagnostic {\n constructor(\n public id: string,\n public fetch: () => any,\n public name: string,\n private readonly _onUnregister: () => void,\n ) {}\n\n unregister(): void {\n this._onUnregister();\n }\n}\n\nexport class DiagnosticsManager {\n readonly instanceId = createId();\n\n readonly registry = new Map<string, TraceDiagnosticImpl>();\n\n private _instanceTag: string | null = null;\n\n get instanceTag(): string | null {\n return this._instanceTag;\n }\n\n setInstanceTag(tag: string): void {\n this._instanceTag = tag;\n }\n\n registerDiagnostic(params: TraceDiagnosticProps<any>): TraceDiagnostic {\n const impl = new TraceDiagnosticImpl(params.id, params.fetch, params.name ?? params.id, () => {\n if (this.registry.get(params.id) === impl) {\n this.registry.delete(params.id);\n }\n });\n this.registry.set(params.id, impl);\n return impl;\n }\n\n list(): DiagnosticMetadata[] {\n return Array.from(this.registry.values()).map((diagnostic) => ({\n id: diagnostic.id,\n instanceId: this.instanceId,\n instanceTag: this._instanceTag,\n name: diagnostic.name,\n }));\n }\n\n async fetch(request: DiagnosticsRequest): Promise<DiagnosticsData> {\n if (request.instanceId != null) {\n invariant(request.instanceId === this.instanceId, 'Invalid instance id');\n }\n const { id } = request;\n const diagnostic = this.registry.get(id);\n invariant(diagnostic, 'Diagnostic not found');\n try {\n const data = await asyncTimeout(diagnostic.fetch(), DIAGNOSTICS_TIMEOUT);\n return {\n id,\n instanceId: this.instanceId,\n data,\n };\n } catch (err: any) {\n return {\n id,\n instanceId: this.instanceId,\n data: null,\n error: err.stack,\n };\n }\n }\n}\n", "// TODO(dmaretskyi): Use UUID.\n//\n// Copyright 2024 DXOS.org\n//\n\nexport const createId = () => Math.random().toString(36).slice(2);\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { Trigger, sleep } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\n\nimport {\n type DiagnosticMetadata,\n DIAGNOSTICS_TIMEOUT,\n type DiagnosticsData,\n type DiagnosticsManager,\n type DiagnosticsRequest,\n} from './diagnostic';\nimport { createId } from './util';\n\nconst DEFAULT_CHANNEL_NAME = 'dxos-diagnostics';\n\nconst DISCOVER_TIME = 500;\n\nexport type DiagnosticChannelMessage =\n | {\n type: 'DIAGNOSTICS_DISCOVER';\n }\n | {\n type: 'DIAGNOSTICS_ANNOUNCE';\n diagnostics: DiagnosticMetadata[];\n }\n | {\n type: 'DIAGNOSTICS_FETCH';\n requestId: string;\n request: DiagnosticsRequest;\n }\n | {\n type: 'DIAGNOSTICS_RESPONSE';\n requestId: string;\n data: DiagnosticsData;\n };\n\nexport class DiagnosticsChannel {\n static get supported() {\n return globalThis.BroadcastChannel != null;\n }\n\n private _ctx = new Context();\n\n // Separate channels becauase the client and server may be in the same process.\n private readonly _serveChannel?: BroadcastChannel = undefined;\n private readonly _clientChannel?: BroadcastChannel = undefined;\n\n constructor(private readonly _channelName: string = DEFAULT_CHANNEL_NAME) {\n if (DiagnosticsChannel.supported) {\n this._serveChannel = new BroadcastChannel(_channelName);\n this._clientChannel = new BroadcastChannel(_channelName);\n }\n }\n\n destroy(): void {\n void this._ctx.dispose();\n this._serveChannel?.close();\n this._clientChannel?.close();\n }\n\n /**\n * In node.js, the channel will keep the process alive.\n * This method allows the process to exit.\n * Noop in the browser.\n */\n unref(): void {\n if (this._serveChannel && typeof (this._serveChannel as any).unref === 'function') {\n (this._serveChannel as any).unref();\n (this._clientChannel as any).unref();\n }\n }\n\n serve(manager: DiagnosticsManager): void {\n invariant(this._serveChannel);\n const listener = async (event: MessageEvent) => {\n switch (event.data.type) {\n case 'DIAGNOSTICS_DISCOVER': {\n const diagnostics = manager.list();\n this._serveChannel!.postMessage({\n type: 'DIAGNOSTICS_ANNOUNCE',\n diagnostics,\n } satisfies DiagnosticChannelMessage);\n break;\n }\n case 'DIAGNOSTICS_FETCH': {\n const { requestId, request } = event.data;\n\n if (request.instanceId != null && request.instanceId !== manager.instanceId) {\n break;\n } else if (request.instanceTag != null && request.instanceTag !== manager.instanceTag) {\n break;\n }\n\n const data = await manager.fetch(request);\n this._serveChannel!.postMessage({\n type: 'DIAGNOSTICS_RESPONSE',\n requestId,\n data,\n } satisfies DiagnosticChannelMessage);\n break;\n }\n }\n };\n\n this._serveChannel.addEventListener('message', listener);\n this._ctx.onDispose(() => this._serveChannel!.removeEventListener('message', listener));\n }\n\n async discover(): Promise<DiagnosticMetadata[]> {\n invariant(this._clientChannel);\n const diagnostics: DiagnosticMetadata[] = [];\n\n const collector = (event: MessageEvent) => {\n const data = event.data as DiagnosticChannelMessage;\n switch (data.type) {\n case 'DIAGNOSTICS_ANNOUNCE':\n diagnostics.push(...data.diagnostics);\n break;\n }\n };\n\n try {\n this._clientChannel.addEventListener('message', collector);\n this._clientChannel.postMessage({ type: 'DIAGNOSTICS_DISCOVER' } satisfies DiagnosticChannelMessage);\n\n await sleep(DISCOVER_TIME);\n\n // Dedup.\n const result: DiagnosticMetadata[] = [];\n for (const diagnostic of diagnostics) {\n if (!result.some((d) => d.id === diagnostic.id && d.instanceId === diagnostic.instanceId)) {\n result.push(diagnostic);\n }\n }\n\n return diagnostics;\n } finally {\n this._clientChannel.removeEventListener('message', collector);\n }\n }\n\n async fetch(request: DiagnosticsRequest): Promise<DiagnosticsData> {\n invariant(this._clientChannel);\n const requestId = createId();\n\n const trigger = new Trigger<DiagnosticsData>();\n const listener = (event: MessageEvent) => {\n const data = event.data as DiagnosticChannelMessage;\n if (data.type === 'DIAGNOSTICS_RESPONSE' && data.requestId === requestId) {\n trigger.wake(data.data);\n }\n };\n\n try {\n this._clientChannel.addEventListener('message', listener);\n this._clientChannel.postMessage({\n type: 'DIAGNOSTICS_FETCH',\n requestId,\n request,\n } satisfies DiagnosticChannelMessage);\n\n // NOTE: Must have await keyword in this block.\n const result = await trigger.wait({ timeout: DIAGNOSTICS_TIMEOUT });\n\n return result;\n } finally {\n this._clientChannel.removeEventListener('message', listener);\n }\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\ntype TagType = number | string | boolean | null | undefined;\n\nexport interface MetricData {\n unit?: string;\n tags?: Record<string, TagType>;\n timestamp?: number;\n}\n\ninterface MetricsMethods {\n /**\n * Adds a value to a counter metric\n */\n increment(name: string, value?: number, data?: MetricData): void;\n /**\n * Adds a value to a distribution metric\n */\n distribution(name: string, value: number, data?: MetricData): void;\n /**\n * Adds a value to a set metric. Value must be a string or integer.\n */\n set(name: string, value: number | string, data?: MetricData): void;\n /**\n * Adds a value to a gauge metric\n */\n gauge(name: string, value: number, data?: MetricData): void;\n}\n\n/**\n * Allows metrics to be recorded within SDK code without requiring specific consumers.\n */\nexport class RemoteMetrics implements MetricsMethods {\n private _metrics = new Set<MetricsMethods>();\n\n registerProcessor(processor: MetricsMethods): void {\n this._metrics.add(processor);\n }\n\n increment(name: string, value?: number, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.increment(name, value, data));\n }\n\n distribution(name: string, value: number, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.distribution(name, value, data));\n }\n\n set(name: string, value: number | string, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.set(name, value, data));\n }\n\n gauge(name: string, value: number, data?: MetricData): void[] {\n return Array.from(this._metrics.values()).map((processor) => processor.gauge(name, value, data));\n }\n}\n", "// Workerd does not support WeakRef\n\n//\n// Copyright 2024 DXOS.org\n//\n\nclass WeakRefMock<T> {\n // eslint-disable-next-line @typescript-eslint/no-useless-constructor\n constructor(target: T) {\n // do nothing\n }\n\n deref(): T | undefined {\n return undefined;\n }\n}\n\nexport const WeakRef = globalThis.WeakRef ?? WeakRefMock;\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nexport abstract class BaseCounter {\n /**\n * @internal\n */\n _instance: any;\n\n name?: string;\n\n /**\n * @internal\n */\n _assign(instance: any, name: string): void {\n this._instance = instance;\n this.name = name;\n }\n\n abstract getData(): Metric;\n\n _tick(time: number): void {}\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nexport class UnaryCounter extends BaseCounter {\n value = 0;\n units?: string;\n\n constructor({ units }: { units?: string } = {}) {\n super();\n this.units = units;\n }\n\n inc(by = 1): void {\n this.value += by;\n }\n\n getData(): Metric {\n return {\n name: this.name!,\n counter: {\n value: this.value,\n units: this.units,\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nconst MAX_BUCKETS = 60;\n\nexport class TimeSeriesCounter extends BaseCounter {\n private _currentValue = 0;\n private _totalValue = 0;\n private _buckets: number[] = [];\n units?: string;\n\n constructor({ units }: { units?: string } = {}) {\n super();\n this.units = units;\n }\n\n inc(by = 1): void {\n this._currentValue += by;\n this._totalValue += by;\n }\n\n override _tick(time: number): void {\n this._buckets.push(this._currentValue);\n if (this._buckets.length > MAX_BUCKETS) {\n this._buckets.shift();\n }\n this._currentValue = 0;\n }\n\n override getData(): Metric {\n return {\n name: this.name!,\n timeSeries: {\n tracks: [\n {\n name: this.name!,\n units: this.units,\n points: this._buckets.map((value, index) => ({\n value,\n })),\n total: this._totalValue,\n },\n ],\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nconst MAX_BUCKETS = 60;\n\nexport class TimeUsageCounter extends BaseCounter {\n private _currentValue = 0;\n private _totalValue = 0;\n private _buckets: number[] = [];\n\n private _lastTickTime = performance.now();\n\n record(time: number): void {\n this._currentValue += time;\n this._totalValue += time;\n }\n\n beginRecording(): { end: () => void } {\n const start = performance.now();\n return {\n end: () => {\n const end = performance.now();\n this.record(end - start);\n },\n };\n }\n\n override _tick(time: number): void {\n const delta = time - this._lastTickTime;\n this._lastTickTime = time;\n\n const percentage = (this._currentValue / delta) * 100;\n this._buckets.push(percentage);\n if (this._buckets.length > MAX_BUCKETS) {\n this._buckets.shift();\n }\n this._currentValue = 0;\n }\n\n override getData(): Metric {\n return {\n name: this.name!,\n timeSeries: {\n tracks: [\n {\n name: this.name!,\n units: '%',\n points: this._buckets.map((value, index) => ({\n value,\n })),\n total: this._totalValue,\n },\n ],\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nexport class MapCounter extends BaseCounter {\n values = new Map<string, number>();\n units?: string;\n\n constructor({ units }: { units?: string } = {}) {\n super();\n this.units = units;\n }\n\n inc(key: string, by = 1): void {\n const prev = this.values.get(key) ?? 0;\n this.values.set(key, prev + by);\n }\n\n getData(): Metric {\n return {\n name: this.name!,\n multiCounter: {\n records: Array.from(this.values.entries()).map(([key, value]) => ({\n key,\n value,\n })),\n units: this.units,\n },\n };\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { type Metric } from '@dxos/protocols/proto/dxos/tracing';\n\nimport { BaseCounter } from './base';\n\nexport class CustomCounter extends BaseCounter {\n constructor(private readonly _getData: () => object) {\n super();\n }\n\n override getData(): Metric {\n return {\n name: this.name!,\n custom: {\n payload: this._getData(),\n },\n };\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { trace } from './api';\n\nexport * from './api';\nexport * from './symbols';\nexport * from './trace-processor';\nexport * from './tracing-types';\nexport * from './metrics';\nexport * from './diagnostic';\nexport * from './diagnostics-channel';\nexport * from './remote/metrics';\n\ntrace.diagnostic({\n id: 'process-info',\n name: 'Process Info',\n fetch: async () => {\n return {\n platform: globalThis.process?.platform,\n arch: globalThis.process?.arch,\n versions: globalThis.process?.versions,\n href: globalThis.location?.href,\n };\n },\n});\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["Context", "LifecycleState", "Resource", "TRACE_SPAN_ATTRIBUTE", "symbolTracingContext", "Symbol", "getTracingContext", "target", "infoProperties", "metricsProperties", "LogLevel", "log", "getPrototypeSpecificInstanceId", "BUFFERED_PREFIX", "BufferedSpan", "spanContext", "startTime", "delegate", "options", "id", "traceparent", "Date", "now", "end", "endTime", "setError", "err", "replay", "real", "BufferingTracingBackend", "startSpan", "span", "push", "clear", "length", "drain", "backend", "idMap", "Map", "buffered", "parentContext", "startsWith", "get", "set", "asyncTimeout", "invariant", "createId", "Math", "random", "toString", "slice", "DIAGNOSTICS_TIMEOUT", "fetch", "name", "_onUnregister", "unregister", "registry", "_instanceTag", "instanceTag", "setInstanceTag", "tag", "registerDiagnostic", "params", "get", "id", "list", "instanceId", "diagnostic", "invariant", "request", "data", "error", "stack", "Trigger", "sleep", "Context", "invariant", "__dxlog_file", "DEFAULT_CHANNEL_NAME", "DiagnosticsChannel", "_ctx", "Context", "_serveChannel", "undefined", "_channelName", "supported", "BroadcastChannel", "destroy", "_clientChannel", "close", "unref", "serve", "listener", "event", "type", "diagnostics", "request", "instanceTag", "requestId", "data", "discover", "invariant", "collector", "sleep", "result", "some", "diagnostic", "trigger", "Trigger", "wake", "RemoteMetrics", "_metrics", "Set", "registerProcessor", "processor", "add", "increment", "name", "value", "data", "Array", "from", "values", "map", "distribution", "set", "gauge", "WeakRefMock", "target", "deref", "undefined", "WeakRef", "globalThis", "__dxlog_file", "ResourceEntry", "instance", "annotation", "sanitizedClassName", "getMetric", "MAX_INFO_OBJECT_DEPTH", "TraceProcessor", "diagnostics", "DiagnosticsManager", "diagnosticsChannel", "remoteMetrics", "BufferingTracingBackend", "tracingBackend", "startSpan", "options", "parent", "traceparent", "translated", "idMap", "parentContext", "resources", "resourceInstanceIndex", "resourceIdList", "logs", "_instanceTag", "addProcessor", "DiagnosticsChannel", "unref", "setInstanceTag", "createTraceResource", "params", "tracingContext", "getTracingContext", "Object", "key", "keys", "entry", "className", "instanceId", "info", "getResourceInfo", "links", "metrics", "getResourceMetrics", "WeakRef", "push", "id", "length", "MAX_RESOURCE_RECORDS", "_clearResources", "addLink", "log", "value", "res", "sanitizeValue", "err", "getResourceId", "findResourcesByClassName", "filter", "findResourcesByAnnotation", "values", "refresh", "resource", "time", "_tick", "_pushLog", "shift", "_logProcessor", "LogLevel", "ERROR", "WARN", "TRACE", "scope", "computedError", "filename", "line", "level", "message", "context", "timestamp", "Date", "meta", "resourceId", "resourceEntry", "depth", "isMapLike", "fromEntries", "Array", "from", "entries", "map", "traceProcessor", "toString", "SANITIZE_REGEX", "name", "m", "isSetLike", "__dxlog_file", "LIFECYCLE_SPAN", "proto", "spanAttribute", "resolved", "options", "enum", "value", "String", "spanAttributes", "Error", "klass", "constructor", "rest", "TRACE_PROCESSOR", "createTraceResource", "annotation", "instance", "prototype", "originalOpen", "originalClose", "open", "_lifecycleState", "LifecycleState", "parentSpanContext", "ctx", "getAttribute", "resourceEntry", "entryPoint", "tracingBackend", "op", "attributes", "parentContext", "remoteSpan", "spanContext", "traceAttrs", "TRACE_SPAN_ATTRIBUTE", "openCtx", "derive", "Context", "setError", "err", "self", "undefined", "Object", "opts", "mark", "performance", "descriptor", "parentCtx", "startTs", "className", "sanitizedClassName", "sanitizeClassName", "spanName", "propertyKey", "collectSpanAttributes", "entries", "callArgs", "args", "childCtx", "measure", "manualSpans", "params", "showInBrowserTimeline", "manualSpanTimestamps", "name", "now", "key", "delete", "timestamps", "addLink", "child", "diagnostic", "info", "metricsCounter", "resource", "span", "spanStart", "spanEnd", "metrics", "BaseCounter", "_instance", "name", "_assign", "instance", "_tick", "time", "UnaryCounter", "BaseCounter", "value", "units", "inc", "by", "getData", "name", "counter", "MAX_BUCKETS", "TimeSeriesCounter", "BaseCounter", "_currentValue", "_totalValue", "_buckets", "units", "inc", "by", "_tick", "time", "push", "length", "shift", "getData", "name", "timeSeries", "tracks", "points", "map", "value", "index", "total", "MAX_BUCKETS", "TimeUsageCounter", "BaseCounter", "_currentValue", "_totalValue", "_buckets", "_lastTickTime", "performance", "now", "record", "time", "beginRecording", "start", "end", "_tick", "delta", "percentage", "push", "length", "shift", "getData", "name", "timeSeries", "tracks", "units", "points", "map", "value", "index", "total", "MapCounter", "BaseCounter", "values", "Map", "units", "inc", "key", "by", "prev", "get", "set", "getData", "name", "multiCounter", "records", "Array", "from", "entries", "map", "value", "CustomCounter", "BaseCounter", "_getData", "getData", "name", "custom", "payload", "trace", "diagnostic", "id", "name", "fetch", "platform", "globalThis", "process", "arch", "versions", "href", "location"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics-channel.d.ts","sourceRoot":"","sources":["../../../src/diagnostics-channel.ts"],"names":[],"mappings":"AAQA,OAAO,
|
|
1
|
+
{"version":3,"file":"diagnostics-channel.d.ts","sourceRoot":"","sources":["../../../src/diagnostics-channel.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,KAAK,kBAAkB,EAEvB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACxB,MAAM,cAAc,CAAC;AAOtB,MAAM,MAAM,wBAAwB,GAChC;IACE,IAAI,EAAE,sBAAsB,CAAC;CAC9B,GACD;IACE,IAAI,EAAE,sBAAsB,CAAC;IAC7B,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC,GACD;IACE,IAAI,EAAE,mBAAmB,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,kBAAkB,CAAC;CAC7B,GACD;IACE,IAAI,EAAE,sBAAsB,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,eAAe,CAAC;CACvB,CAAC;AAEN,qBAAa,kBAAkB;IAWjB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAVzC,MAAM,KAAK,SAAS,YAEnB;IAED,OAAO,CAAC,IAAI,CAAiB;IAG7B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAA+B;IAC9D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAA+B;IAE/D,YAA6B,YAAY,GAAE,MAA6B,EAKvE;IAED,OAAO,IAAI,IAAI,CAId;IAED;;;;OAIG;IACH,KAAK,IAAI,IAAI,CAKZ;IAED,KAAK,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAkCvC;IAEK,QAAQ,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC,CA+B9C;IAEK,KAAK,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,eAAe,CAAC,CA2BjE;CACF"}
|