{"version":3,"file":"instrument.js","sources":["../../../src/otel/instrument.ts"],"sourcesContent":["import { type Instrumentation, registerInstrumentations } from '@opentelemetry/instrumentation';\n\n/** Exported only for tests. */\nexport const INSTRUMENTED: Record<string, Instrumentation> = {};\n\nexport function generateInstrumentOnce<\n  Options,\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  InstrumentationClass extends new (...args: any[]) => Instrumentation,\n>(\n  name: string,\n  instrumentationClass: InstrumentationClass,\n  optionsCallback: (options: Options) => ConstructorParameters<InstrumentationClass>[0],\n): ((options: Options) => InstanceType<InstrumentationClass>) & { id: string };\nexport function generateInstrumentOnce<\n  Options = unknown,\n  InstrumentationInstance extends Instrumentation = Instrumentation,\n>(\n  name: string,\n  creator: (options?: Options) => InstrumentationInstance,\n): ((options?: Options) => InstrumentationInstance) & { id: string };\n/**\n * Instrument an OpenTelemetry instrumentation once.\n * This will skip running instrumentation again if it was already instrumented.\n */\nexport function generateInstrumentOnce<Options>(\n  name: string,\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  creatorOrClass: (new (...args: any[]) => Instrumentation) | ((options?: Options) => Instrumentation),\n  optionsCallback?: (options: Options) => unknown,\n): ((options: Options) => Instrumentation) & { id: string } {\n  if (optionsCallback) {\n    return _generateInstrumentOnceWithOptions(\n      name,\n      creatorOrClass as new (...args: unknown[]) => Instrumentation,\n      optionsCallback,\n    );\n  }\n\n  return _generateInstrumentOnce(name, creatorOrClass as (options?: Options) => Instrumentation);\n}\n\n// The plain version without handling of options\n// Should not be used with custom options that are mutated in the creator!\nfunction _generateInstrumentOnce<Options = unknown, InstrumentationInstance extends Instrumentation = Instrumentation>(\n  name: string,\n  creator: (options?: Options) => InstrumentationInstance,\n): ((options?: Options) => InstrumentationInstance) & { id: string } {\n  return Object.assign(\n    (options?: Options) => {\n      const instrumented = INSTRUMENTED[name] as InstrumentationInstance | undefined;\n      if (instrumented) {\n        // If options are provided, ensure we update them\n        if (options) {\n          instrumented.setConfig(options);\n        }\n        return instrumented;\n      }\n\n      const instrumentation = creator(options);\n      INSTRUMENTED[name] = instrumentation;\n\n      registerInstrumentations({\n        instrumentations: [instrumentation],\n      });\n\n      return instrumentation;\n    },\n    { id: name },\n  );\n}\n\n// This version handles options properly\nfunction _generateInstrumentOnceWithOptions<\n  Options,\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  InstrumentationClass extends new (...args: any[]) => Instrumentation,\n>(\n  name: string,\n  instrumentationClass: InstrumentationClass,\n  optionsCallback: (options: Options) => ConstructorParameters<InstrumentationClass>[0],\n): ((options: Options) => InstanceType<InstrumentationClass>) & { id: string } {\n  return Object.assign(\n    (_options: Options) => {\n      const options = optionsCallback(_options);\n\n      const instrumented = INSTRUMENTED[name] as InstanceType<InstrumentationClass> | undefined;\n      if (instrumented) {\n        // Ensure we update options\n        instrumented.setConfig(options);\n        return instrumented;\n      }\n\n      const instrumentation = new instrumentationClass(options) as InstanceType<InstrumentationClass>;\n      INSTRUMENTED[name] = instrumentation;\n\n      registerInstrumentations({\n        instrumentations: [instrumentation],\n      });\n\n      return instrumentation;\n    },\n    { id: name },\n  );\n}\n\n/**\n * Ensure a given callback is called when the instrumentation is actually wrapping something.\n * This can be used to ensure some logic is only called when the instrumentation is actually active.\n *\n * This function returns a function that can be invoked with a callback.\n * This callback will either be invoked immediately\n * (e.g. if the instrumentation was already wrapped, or if _wrap could not be patched),\n * or once the instrumentation is actually wrapping something.\n *\n * Make sure to call this function right after adding the instrumentation, otherwise it may be too late!\n * The returned callback can be used any time, and also multiple times.\n */\nexport function instrumentWhenWrapped<T extends Instrumentation>(instrumentation: T): (callback: () => void) => void {\n  let isWrapped = false;\n  let callbacks: (() => void)[] = [];\n\n  if (!hasWrap(instrumentation)) {\n    isWrapped = true;\n  } else {\n    const originalWrap = instrumentation['_wrap'];\n\n    instrumentation['_wrap'] = (...args: Parameters<typeof originalWrap>) => {\n      isWrapped = true;\n      callbacks.forEach(callback => callback());\n      callbacks = [];\n      return originalWrap(...args);\n    };\n  }\n\n  const registerCallback = (callback: () => void): void => {\n    if (isWrapped) {\n      callback();\n    } else {\n      callbacks.push(callback);\n    }\n  };\n\n  return registerCallback;\n}\n\nfunction hasWrap<T extends Instrumentation>(\n  instrumentation: T,\n): instrumentation is T & { _wrap: (...args: unknown[]) => unknown } {\n  return typeof (instrumentation as T & { _wrap?: (...args: unknown[]) => unknown })['_wrap'] === 'function';\n}\n"],"names":["instrumentation","registerInstrumentations"],"mappings":"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"}