{"version":3,"file":"instrumentation.js","sourceRoot":"","sources":["../../src/instrumentation.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport * as api from '@opentelemetry/api';\nimport {\n  InstrumentationConfig,\n  InstrumentationBase,\n  InstrumentationNodeModuleDefinition,\n  InstrumentationNodeModuleFile,\n  isWrapped,\n} from '@opentelemetry/instrumentation';\nimport { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';\n\nimport * as http from 'http';\nimport type * as Router from 'router';\n\nimport * as types from './internal-types';\n/** @knipignore */\nimport { PACKAGE_NAME, PACKAGE_VERSION } from './version';\nimport {\n  RouterConstants,\n  MODULE_NAME,\n  V1_CONSTANTS,\n  V2_CONSTANTS,\n} from './constants';\nimport * as utils from './utils';\nimport AttributeNames from './enums/AttributeNames';\nimport LayerType from './enums/LayerType';\n\nconst supportedVersions = ['>=1.0.0 <3'];\n\nexport class RouterInstrumentation extends InstrumentationBase {\n  constructor(config: InstrumentationConfig = {}) {\n    super(PACKAGE_NAME, PACKAGE_VERSION, config);\n  }\n\n  private _moduleVersion?: string;\n  private _constants?: RouterConstants;\n\n  init() {\n    const module = new InstrumentationNodeModuleDefinition(\n      MODULE_NAME,\n      supportedVersions,\n      (moduleExports, moduleVersion) => {\n        this._moduleVersion = moduleVersion;\n        return moduleExports;\n      }\n    );\n\n    module.files.push(\n      new InstrumentationNodeModuleFile(\n        'router/lib/layer.js',\n        supportedVersions,\n        (moduleExports, moduleVersion) => {\n          const Layer: any = moduleExports;\n          const isV2 = moduleVersion?.startsWith('2.');\n          this._constants ??= isV2 ? V2_CONSTANTS : V1_CONSTANTS;\n          const requestHandlerName = this._constants.requestHandlerName;\n          const errorHandlerName = this._constants.errorHandlerName;\n          if (isWrapped(Layer.prototype[requestHandlerName])) {\n            this._unwrap(Layer.prototype, requestHandlerName);\n          }\n          this._wrap(\n            Layer.prototype,\n            requestHandlerName,\n            this._requestHandlerPatcher.bind(this)\n          );\n          if (isWrapped(Layer.prototype[errorHandlerName])) {\n            this._unwrap(Layer.prototype, errorHandlerName);\n          }\n          this._wrap(\n            Layer.prototype,\n            errorHandlerName,\n            this._errorHandlerPatcher.bind(this)\n          );\n          return moduleExports;\n        },\n        moduleExports => {\n          const Layer: any = moduleExports;\n          if (this._constants !== undefined) {\n            this._unwrap(Layer.prototype, this._constants.requestHandlerName);\n            this._unwrap(Layer.prototype, this._constants.errorHandlerName);\n          }\n          return moduleExports;\n        }\n      )\n    );\n\n    return module;\n  }\n\n  // Define handle_request wrapper separately to ensure the signature has the correct length\n  private _requestHandlerPatcher(original: Router.RequestHandler) {\n    const instrumentation = this;\n    return function wrapped_handle_request(\n      this: Router.Layer,\n      req: Router.RoutedRequest,\n      res: http.ServerResponse,\n      next: Router.NextFunction\n    ) {\n      // Skip creating spans if the registered handler is of invalid length, because\n      // we know router will ignore those\n      if (\n        this.handle.length > 3 ||\n        utils.isInternal(this.handle, instrumentation._constants)\n      ) {\n        return original.call(this, req, res, next);\n      }\n      const { context, wrappedNext } = instrumentation._setupSpan(\n        this,\n        req,\n        res,\n        next\n      );\n      return api.context.with(context, original, this, req, res, wrappedNext);\n    };\n  }\n\n  // Define handle_error wrapper separately to ensure the signature has the correct length\n  private _errorHandlerPatcher(original: Router.ErrorRequestHandler) {\n    const instrumentation = this;\n    return function wrapped_handle_request(\n      this: Router.Layer,\n      error: Error,\n      req: Router.RoutedRequest,\n      res: http.ServerResponse,\n      next: Router.NextFunction\n    ) {\n      // Skip creating spans if the registered handler is of invalid length, because\n      // we know router will ignore those\n      if (\n        this.handle.length !== 4 ||\n        utils.isInternal(this.handle, instrumentation._constants)\n      ) {\n        return original.call(this, error, req, res, next);\n      }\n      const { context, wrappedNext } = instrumentation._setupSpan(\n        this,\n        req,\n        res,\n        next\n      );\n      return api.context.with(\n        context,\n        original,\n        this,\n        error,\n        req,\n        res,\n        wrappedNext\n      );\n    };\n  }\n\n  private _setupSpan(\n    layer: Router.Layer,\n    req: Router.RoutedRequest,\n    res: http.ServerResponse,\n    next: Router.NextFunction\n  ) {\n    const fnName = layer.handle.name || '<anonymous>';\n    const type = layer.method\n      ? LayerType.REQUEST_HANDLER\n      : LayerType.MIDDLEWARE;\n    const route = req.baseUrl + (req.route?.path ?? '') || '/';\n    const spanName =\n      type === LayerType.REQUEST_HANDLER\n        ? `request handler - ${route}`\n        : `middleware - ${fnName}`;\n    const attributes = {\n      [AttributeNames.NAME]: fnName,\n      [AttributeNames.VERSION]: this._moduleVersion,\n      [AttributeNames.TYPE]: type,\n      [ATTR_HTTP_ROUTE]: route,\n    };\n\n    const parent = api.context.active();\n    const parentSpan = api.trace.getSpan(parent) as types.InstrumentationSpan;\n    const span = this.tracer.startSpan(\n      spanName,\n      {\n        attributes,\n      },\n      parent\n    ) as types.InstrumentationSpan;\n    const endSpan = utils.once(span.end.bind(span));\n\n    utils.renameHttpSpan(parentSpan, layer.method, route);\n    // make sure spans are ended at least when response is finished\n    res.prependOnceListener('finish', endSpan);\n\n    const wrappedNext: Router.NextFunction = err => {\n      if (err) {\n        span.recordException(err);\n      }\n      endSpan();\n      if (parent) {\n        return api.context.with(parent, next, undefined, err);\n      }\n      return next(err);\n    };\n\n    return {\n      context: api.trace.setSpan(parent, span),\n      wrappedNext,\n    };\n  }\n}\n"]}