{"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  isWrapped,\n  InstrumentationBase,\n  InstrumentationNodeModuleDefinition,\n  SemconvStability,\n  semconvStabilityFromStr,\n} from '@opentelemetry/instrumentation';\nimport type * as Memcached from 'memcached';\nimport {\n  DB_SYSTEM_NAME_VALUE_MEMCACHED,\n  DB_SYSTEM_VALUE_MEMCACHED,\n  ATTR_DB_OPERATION,\n  ATTR_DB_STATEMENT,\n  ATTR_DB_SYSTEM,\n} from './semconv';\nimport {\n  ATTR_DB_OPERATION_NAME,\n  ATTR_DB_QUERY_TEXT,\n  ATTR_DB_SYSTEM_NAME,\n} from '@opentelemetry/semantic-conventions';\n\nimport * as utils from './utils';\nimport { InstrumentationConfig } from './types';\n/** @knipignore */\nimport { PACKAGE_NAME, PACKAGE_VERSION } from './version';\n\nexport class MemcachedInstrumentation extends InstrumentationBase<InstrumentationConfig> {\n  static readonly COMPONENT = 'memcached';\n  static readonly DEFAULT_CONFIG: InstrumentationConfig = {\n    enhancedDatabaseReporting: false,\n  };\n\n  private _netSemconvStability!: SemconvStability;\n  private _dbSemconvStability!: SemconvStability;\n\n  constructor(config: InstrumentationConfig = {}) {\n    super(PACKAGE_NAME, PACKAGE_VERSION, {\n      ...MemcachedInstrumentation.DEFAULT_CONFIG,\n      ...config,\n    });\n    this._setSemconvStabilityFromEnv();\n  }\n\n  // Used for testing.\n  private _setSemconvStabilityFromEnv() {\n    this._netSemconvStability = semconvStabilityFromStr(\n      'http',\n      process.env.OTEL_SEMCONV_STABILITY_OPT_IN\n    );\n    this._dbSemconvStability = semconvStabilityFromStr(\n      'database',\n      process.env.OTEL_SEMCONV_STABILITY_OPT_IN\n    );\n  }\n\n  override setConfig(config: InstrumentationConfig = {}) {\n    super.setConfig({ ...MemcachedInstrumentation.DEFAULT_CONFIG, ...config });\n  }\n\n  init() {\n    return [\n      new InstrumentationNodeModuleDefinition(\n        'memcached',\n        ['>=2.2.0 <3'],\n        (moduleExports: typeof Memcached, moduleVersion) => {\n          this.ensureWrapped(\n            moduleExports.prototype,\n            'command',\n            this.wrapCommand.bind(this, moduleVersion)\n          );\n          return moduleExports;\n        },\n        (moduleExports: typeof Memcached) => {\n          if (moduleExports === undefined) return;\n          // `command` is documented API missing from the types\n          this._unwrap(moduleExports.prototype, 'command' as keyof Memcached);\n        }\n      ),\n    ];\n  }\n\n  wrapCommand(\n    moduleVersion: undefined | string,\n    original: (\n      queryCompiler: () => Memcached.CommandData,\n      server?: string\n    ) => any\n  ) {\n    const instrumentation = this;\n    return function (\n      this: Memcached,\n      queryCompiler: () => Memcached.CommandData,\n      server?: string\n    ) {\n      if (typeof queryCompiler !== 'function') {\n        return original.apply(this, arguments as any);\n      }\n\n      const attributes: api.Attributes = {\n        'memcached.version': moduleVersion,\n      };\n\n      if (instrumentation._dbSemconvStability & SemconvStability.OLD) {\n        attributes[ATTR_DB_SYSTEM] = DB_SYSTEM_VALUE_MEMCACHED;\n      }\n      if (instrumentation._dbSemconvStability & SemconvStability.STABLE) {\n        attributes[ATTR_DB_SYSTEM_NAME] = DB_SYSTEM_NAME_VALUE_MEMCACHED;\n      }\n\n      // The name will be overwritten later\n      const span = instrumentation.tracer.startSpan(\n        'unknown memcached command',\n        {\n          kind: api.SpanKind.CLIENT,\n          attributes,\n        }\n      );\n      const parentContext = api.context.active();\n      const context = api.trace.setSpan(parentContext, span);\n\n      return api.context.with(\n        context,\n        original,\n        this,\n        instrumentation.wrapQueryCompiler.call(\n          instrumentation,\n          queryCompiler,\n          this,\n          server,\n          parentContext,\n          span\n        ),\n        server\n      );\n    };\n  }\n\n  wrapQueryCompiler(\n    original: () => Memcached.CommandData,\n    client: Memcached,\n    server: undefined | string,\n    callbackContext: api.Context,\n    span: api.Span\n  ) {\n    const instrumentation = this;\n    return function (this: Memcached) {\n      const query = original.apply(this, arguments as any);\n      const callback = query.callback;\n\n      span.updateName(`memcached ${query.type}`);\n\n      const attributes: api.Attributes = {\n        'db.memcached.key': query.key,\n        'db.memcached.lifetime': query.lifetime,\n        ...utils.getPeerAttributes(\n          client,\n          server,\n          query,\n          instrumentation._netSemconvStability\n        ),\n      };\n\n      if (instrumentation._dbSemconvStability & SemconvStability.OLD) {\n        attributes[ATTR_DB_OPERATION] = query.type;\n      }\n      if (instrumentation._dbSemconvStability & SemconvStability.STABLE) {\n        attributes[ATTR_DB_OPERATION_NAME] = query.type;\n      }\n\n      if (instrumentation.getConfig().enhancedDatabaseReporting) {\n        if (instrumentation._dbSemconvStability & SemconvStability.OLD) {\n          attributes[ATTR_DB_STATEMENT] = query.command;\n        }\n        if (instrumentation._dbSemconvStability & SemconvStability.STABLE) {\n          attributes[ATTR_DB_QUERY_TEXT] = query.command;\n        }\n      }\n\n      span.setAttributes(attributes);\n\n      query.callback = api.context.bind(\n        callbackContext,\n        function (this: Memcached.CommandData, err: any) {\n          if (err) {\n            span.recordException(err);\n            span.setStatus({\n              code: api.SpanStatusCode.ERROR,\n              message: err.message,\n            });\n          }\n\n          span.end();\n\n          if (typeof callback === 'function') {\n            return callback.apply(this, arguments as any);\n          }\n        }\n      );\n\n      return query;\n    };\n  }\n\n  private ensureWrapped(\n    obj: any,\n    methodName: string,\n    wrapper: (original: any) => any\n  ) {\n    if (isWrapped(obj[methodName])) {\n      this._unwrap(obj, methodName);\n    }\n    this._wrap(obj, methodName, wrapper);\n  }\n}\n"]}