1import type * as Tracer from "../Tracer.ts"
2import { getStackTraceLimit, setStackTraceLimit } from "./stackTraceLimit.ts"
3
4/** @internal */
5export interface ErrorWithStackTraceLimit {
6 stackTraceLimit?: number | undefined
7}
8
9/** @internal */
10export const addSpanStackTrace = <A extends Tracer.TraceOptions>(
11 options: A | undefined
12): A => {
13 if (options?.captureStackTrace === false) {
14 return options
15 } else if (options?.captureStackTrace !== undefined && typeof options.captureStackTrace !== "boolean") {
16 return options
17 }
18 const limit = getStackTraceLimit()
19 if (limit === 0 && options?.captureStackTrace !== true) {
20 return { ...options, captureStackTrace: false } as A
21 }
22 setStackTraceLimit(3)
23 const traceError = new Error()
24 setStackTraceLimit(limit)
25 return {
26 ...options,
27 captureStackTrace: spanCleaner(() => traceError.stack)
28 } as A
29}
30
31/** @internal */
32export const makeStackCleaner = (line: number) => (stack: () => string | undefined): () => string | undefined => {
33 let cache: string | undefined
34 return () => {
35 if (cache !== undefined) return cache
36 const trace = stack()
37 if (!trace) return undefined
38 const lines = trace.split("\n")
39 if (lines[line] !== undefined) {
40 cache = lines[line].trim()
41 return cache
42 }
43 }
44}
45
46const spanCleaner = makeStackCleaner(3)