{"version":3,"sources":["../../src/trace/trace.ts"],"sourcesContent":["import { reporter } from './report'\nimport type { SpanId, TraceEvent, TraceState } from './types'\n\nconst NUM_OF_MICROSEC_IN_NANOSEC = BigInt('1000')\nconst NUM_OF_MILLISEC_IN_NANOSEC = BigInt('1000000')\nlet count = 0\nconst getId = () => {\n count++\n return count\n}\nlet defaultParentSpanId: SpanId | undefined\nlet shouldSaveTraceEvents: boolean | undefined\nlet savedTraceEvents: TraceEvent[] = []\n\nconst RECORD_SPAN_THRESHOLD_MS = parseInt(\n process.env.NEXT_TRACE_SPAN_THRESHOLD_MS ?? '-1'\n)\n\n// eslint typescript has a bug with TS enums\nexport enum SpanStatus {\n Started = 'started',\n Stopped = 'stopped',\n}\n\ninterface Attributes {\n [key: string]: string\n}\n\nexport class Span {\n private name: string\n private id: SpanId\n private parentId?: SpanId\n private attrs: { [key: string]: any }\n private status: SpanStatus\n private now: number\n\n // Number of nanoseconds since epoch.\n private _start: bigint\n\n constructor({\n name,\n parentId,\n attrs,\n startTime,\n }: {\n name: string\n parentId?: SpanId\n startTime?: bigint\n attrs?: Attributes\n }) {\n this.name = name\n this.parentId = parentId ?? defaultParentSpanId\n this.attrs = attrs ? { ...attrs } : {}\n\n this.status = SpanStatus.Started\n this.id = getId()\n this._start = startTime || process.hrtime.bigint()\n // hrtime cannot be used to reconstruct tracing span's actual start time\n // since it does not have relation to clock time:\n // `These times are relative to an arbitrary time in the past, and not related to the time of day and therefore not subject to clock drift`\n // https://nodejs.org/api/process.html#processhrtimetime\n // Capturing current datetime as additional metadata for external reconstruction.\n this.now = Date.now()\n }\n\n // Durations are reported as microseconds. This gives 1000x the precision\n // of something like Date.now(), which reports in milliseconds.\n // Additionally, ~285 years can be safely represented as microseconds as\n // a float64 in both JSON and JavaScript.\n stop(stopTime?: bigint) {\n if (this.status === SpanStatus.Stopped) {\n // Don't report the same span twice.\n // TODO: In the future this should throw as `.stop()` shouldn't be called multiple times.\n return\n }\n const end: bigint = stopTime || process.hrtime.bigint()\n const duration = (end - this._start) / NUM_OF_MICROSEC_IN_NANOSEC\n this.status = SpanStatus.Stopped\n if (duration > Number.MAX_SAFE_INTEGER) {\n throw new Error(`Duration is too long to express as float64: ${duration}`)\n }\n const timestamp = this._start / NUM_OF_MICROSEC_IN_NANOSEC\n const traceEvent: TraceEvent = {\n name: this.name,\n duration: Number(duration),\n timestamp: Number(timestamp),\n id: this.id,\n parentId: this.parentId,\n tags: this.attrs,\n startTime: this.now,\n }\n if (duration > RECORD_SPAN_THRESHOLD_MS * 1000) {\n reporter.report(traceEvent)\n if (shouldSaveTraceEvents) {\n savedTraceEvents.push(traceEvent)\n }\n }\n }\n\n traceChild(name: string, attrs?: Attributes) {\n return new Span({ name, parentId: this.id, attrs })\n }\n\n manualTraceChild(\n name: string,\n // Start time in nanoseconds since epoch.\n startTime?: bigint,\n // Stop time in nanoseconds since epoch.\n stopTime?: bigint,\n attrs?: Attributes\n ) {\n // We need to convert the time info to the same base as hrtime since that is used usually.\n const correction =\n process.hrtime.bigint() - BigInt(Date.now()) * NUM_OF_MILLISEC_IN_NANOSEC\n const span = new Span({\n name,\n parentId: this.id,\n attrs,\n startTime: startTime ? startTime + correction : process.hrtime.bigint(),\n })\n span.stop(stopTime ? stopTime + correction : process.hrtime.bigint())\n }\n\n getId() {\n return this.id\n }\n\n setAttribute(key: string, value: string) {\n this.attrs[key] = value\n }\n\n traceFn(fn: (span: Span) => T): T {\n try {\n return fn(this)\n } finally {\n this.stop()\n }\n }\n\n async traceAsyncFn(fn: (span: Span) => T | Promise): Promise {\n try {\n return await fn(this)\n } finally {\n this.stop()\n }\n }\n}\n\nexport const trace = (\n name: string,\n parentId?: SpanId,\n attrs?: { [key: string]: string }\n) => {\n return new Span({ name, parentId, attrs })\n}\n\nexport const flushAllTraces = (opts?: { end: boolean }) =>\n reporter.flushAll(opts)\n\n// This code supports workers by serializing the state of tracers when the\n// worker is initialized, and serializing the trace events from the worker back\n// to the main process to record when the worker is complete.\nexport const exportTraceState = (): TraceState => ({\n defaultParentSpanId,\n lastId: count,\n shouldSaveTraceEvents,\n})\nexport const initializeTraceState = (state: TraceState) => {\n count = state.lastId\n defaultParentSpanId = state.defaultParentSpanId\n shouldSaveTraceEvents = state.shouldSaveTraceEvents\n}\n\nexport function getTraceEvents(): TraceEvent[] {\n return savedTraceEvents\n}\n\nexport function recordTraceEvents(events: TraceEvent[]) {\n for (const traceEvent of events) {\n reporter.report(traceEvent)\n if (traceEvent.id > count) {\n count = traceEvent.id + 1\n }\n }\n if (shouldSaveTraceEvents) {\n savedTraceEvents.push(...events)\n }\n}\n\nexport const clearTraceEvents = () => (savedTraceEvents = [])\n"],"names":["Span","SpanStatus","clearTraceEvents","exportTraceState","flushAllTraces","getTraceEvents","initializeTraceState","recordTraceEvents","trace","NUM_OF_MICROSEC_IN_NANOSEC","BigInt","NUM_OF_MILLISEC_IN_NANOSEC","count","getId","defaultParentSpanId","shouldSaveTraceEvents","savedTraceEvents","RECORD_SPAN_THRESHOLD_MS","parseInt","process","env","NEXT_TRACE_SPAN_THRESHOLD_MS","constructor","name","parentId","attrs","startTime","status","id","_start","hrtime","bigint","now","Date","stop","stopTime","end","duration","Number","MAX_SAFE_INTEGER","Error","timestamp","traceEvent","tags","reporter","report","push","traceChild","manualTraceChild","correction","span","setAttribute","key","value","traceFn","fn","traceAsyncFn","opts","flushAll","lastId","state","events"],"mappings":"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","ignoreList":[0]}