{"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  InstrumentationBase,\n  InstrumentationNodeModuleDefinition,\n  InstrumentationNodeModuleFile,\n  isWrapped,\n  safeExecuteInTheMiddle,\n  SemconvStability,\n  semconvStabilityFromStr,\n} from '@opentelemetry/instrumentation';\nimport {\n  DB_SYSTEM_VALUE_MYSQL,\n  ATTR_DB_STATEMENT,\n  ATTR_DB_SYSTEM,\n} from './semconv';\nimport { addSqlCommenterComment } from '@opentelemetry/sql-common';\nimport type * as mysqlTypes from 'mysql2';\nimport { MySQL2InstrumentationConfig } from './types';\nimport {\n  getConnectionAttributes,\n  getConnectionPrototypeToInstrument,\n  getQueryText,\n  getSpanName,\n  once,\n} from './utils';\n/** @knipignore */\nimport { PACKAGE_NAME, PACKAGE_VERSION } from './version';\nimport {\n  ATTR_DB_QUERY_TEXT,\n  ATTR_DB_SYSTEM_NAME,\n  DB_SYSTEM_NAME_VALUE_MYSQL,\n} from '@opentelemetry/semantic-conventions';\n\ntype formatType = typeof mysqlTypes.format;\n\nconst supportedVersions = ['>=1.4.2 <4'];\n\nexport class MySQL2Instrumentation extends InstrumentationBase<MySQL2InstrumentationConfig> {\n  private _netSemconvStability!: SemconvStability;\n  private _dbSemconvStability!: SemconvStability;\n\n  constructor(config: MySQL2InstrumentationConfig = {}) {\n    super(PACKAGE_NAME, PACKAGE_VERSION, config);\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  protected init() {\n    let format: formatType | undefined;\n    function setFormatFunction(moduleExports: any) {\n      if (!format && moduleExports.format) {\n        format = moduleExports.format;\n      }\n    }\n    const patch = (ConnectionPrototype: mysqlTypes.Connection) => {\n      if (isWrapped(ConnectionPrototype.query)) {\n        this._unwrap(ConnectionPrototype, 'query');\n      }\n      this._wrap(\n        ConnectionPrototype,\n        'query',\n        this._patchQuery(format, false) as any\n      );\n      if (isWrapped(ConnectionPrototype.execute)) {\n        this._unwrap(ConnectionPrototype, 'execute');\n      }\n      this._wrap(\n        ConnectionPrototype,\n        'execute',\n        this._patchQuery(format, true) as any\n      );\n    };\n    const unpatch = (ConnectionPrototype: mysqlTypes.Connection) => {\n      this._unwrap(ConnectionPrototype, 'query');\n      this._unwrap(ConnectionPrototype, 'execute');\n    };\n    return [\n      new InstrumentationNodeModuleDefinition(\n        'mysql2',\n        supportedVersions,\n        (moduleExports: any) => {\n          setFormatFunction(moduleExports);\n          return moduleExports;\n        },\n        () => {},\n        [\n          new InstrumentationNodeModuleFile(\n            'mysql2/promise.js',\n            supportedVersions,\n            (moduleExports: any) => {\n              setFormatFunction(moduleExports);\n              return moduleExports;\n            },\n            () => {}\n          ),\n          new InstrumentationNodeModuleFile(\n            'mysql2/lib/connection.js',\n            supportedVersions,\n            (moduleExports: any) => {\n              const ConnectionPrototype: mysqlTypes.Connection =\n                getConnectionPrototypeToInstrument(moduleExports);\n              patch(ConnectionPrototype);\n              return moduleExports;\n            },\n            (moduleExports: any) => {\n              if (moduleExports === undefined) return;\n              const ConnectionPrototype: mysqlTypes.Connection =\n                getConnectionPrototypeToInstrument(moduleExports);\n              unpatch(ConnectionPrototype);\n            }\n          ),\n        ]\n      ),\n    ];\n  }\n\n  private _patchQuery(format: formatType | undefined, isPrepared: boolean) {\n    return (originalQuery: Function): Function => {\n      const thisPlugin = this;\n      return function query(\n        this: mysqlTypes.Connection,\n        query: string | mysqlTypes.Query | mysqlTypes.QueryOptions,\n        _valuesOrCallback?: unknown[] | Function,\n        _callback?: Function\n      ) {\n        let values;\n        if (Array.isArray(_valuesOrCallback)) {\n          values = _valuesOrCallback;\n        } else if (arguments[2]) {\n          values = [_valuesOrCallback];\n        }\n        const { maskStatement, maskStatementHook, responseHook } =\n          thisPlugin.getConfig();\n\n        const attributes: api.Attributes = getConnectionAttributes(\n          this.config,\n          thisPlugin._dbSemconvStability,\n          thisPlugin._netSemconvStability\n        );\n        const dbQueryText = getQueryText(\n          query,\n          format,\n          values,\n          maskStatement,\n          maskStatementHook\n        );\n        if (thisPlugin._dbSemconvStability & SemconvStability.OLD) {\n          attributes[ATTR_DB_SYSTEM] = DB_SYSTEM_VALUE_MYSQL;\n          attributes[ATTR_DB_STATEMENT] = dbQueryText;\n        }\n        if (thisPlugin._dbSemconvStability & SemconvStability.STABLE) {\n          attributes[ATTR_DB_SYSTEM_NAME] = DB_SYSTEM_NAME_VALUE_MYSQL;\n          attributes[ATTR_DB_QUERY_TEXT] = dbQueryText;\n        }\n\n        const span = thisPlugin.tracer.startSpan(getSpanName(query), {\n          kind: api.SpanKind.CLIENT,\n          attributes,\n        });\n\n        if (\n          !isPrepared &&\n          thisPlugin.getConfig().addSqlCommenterCommentToQueries\n        ) {\n          arguments[0] = query =\n            typeof query === 'string'\n              ? addSqlCommenterComment(span, query)\n              : Object.assign(query, {\n                  sql: addSqlCommenterComment(span, query.sql),\n                });\n        }\n\n        const endSpan = once((err?: any, results?: any) => {\n          if (err) {\n            span.setStatus({\n              code: api.SpanStatusCode.ERROR,\n              message: err.message,\n            });\n          } else {\n            if (typeof responseHook === 'function') {\n              safeExecuteInTheMiddle(\n                () => {\n                  responseHook(span, {\n                    queryResults: results,\n                  });\n                },\n                err => {\n                  if (err) {\n                    thisPlugin._diag.warn('Failed executing responseHook', err);\n                  }\n                },\n                true\n              );\n            }\n          }\n\n          span.end();\n        });\n\n        if (arguments.length === 1) {\n          if (typeof (query as any).onResult === 'function') {\n            thisPlugin._wrap(\n              query as any,\n              'onResult',\n              thisPlugin._patchCallbackQuery(endSpan)\n            );\n          }\n\n          const streamableQuery: mysqlTypes.Query = originalQuery.apply(\n            this,\n            arguments\n          );\n\n          // `end` in mysql behaves similarly to `result` in mysql2.\n          streamableQuery\n            .once('error', err => {\n              endSpan(err);\n            })\n            .once('result', results => {\n              endSpan(undefined, results);\n            });\n\n          return streamableQuery;\n        }\n\n        if (typeof arguments[1] === 'function') {\n          thisPlugin._wrap(\n            arguments,\n            1,\n            thisPlugin._patchCallbackQuery(endSpan)\n          );\n        } else if (typeof arguments[2] === 'function') {\n          thisPlugin._wrap(\n            arguments,\n            2,\n            thisPlugin._patchCallbackQuery(endSpan)\n          );\n        }\n\n        return originalQuery.apply(this, arguments);\n      };\n    };\n  }\n\n  private _patchCallbackQuery(endSpan: Function) {\n    return (originalCallback: Function) => {\n      return function (\n        err: mysqlTypes.QueryError | null,\n        results?: any,\n        fields?: mysqlTypes.FieldPacket[]\n      ) {\n        endSpan(err, results);\n        return originalCallback(...arguments);\n      };\n    };\n  }\n}\n"]}