function wrapQuery()

in lib/instrumentation/modules/pg.js [54:147]


  function wrapQuery(orig, name) {
    return function wrappedFunction(sql) {
      agent.logger.debug('intercepted call to %s.prototype.%s', klass, name);
      const ins = agent._instrumentation;
      const span = ins.createSpan('SQL', 'db', 'postgresql', 'query', {
        exitSpan: true,
      });
      if (!span) {
        return orig.apply(this, arguments);
      }

      // Get connection parameters from Client.
      let host, port, database, user;
      if (typeof this.connectionParameters === 'object') {
        ({ host, port, database, user } = this.connectionParameters);
      }
      span._setDestinationContext(getDBDestination(host, port));

      const dbContext = { type: 'sql' };
      let sqlText = sql;
      if (sql && typeof sql.text === 'string') {
        sqlText = sql.text;
      }
      if (typeof sqlText === 'string') {
        span.name = sqlSummary(sqlText);
        dbContext.statement = sqlText;
      } else {
        agent.logger.debug(
          'unable to parse sql form pg module (type: %s)',
          typeof sqlText,
        );
      }
      if (database) {
        dbContext.instance = database;
      }
      if (user) {
        dbContext.user = user;
      }
      span.setDbContext(dbContext);

      if (this[symbols.knexStackObj]) {
        span.customStackTrace(this[symbols.knexStackObj]);
        this[symbols.knexStackObj] = null;
      }

      let index = arguments.length - 1;
      let cb = arguments[index];
      if (Array.isArray(cb)) {
        index = cb.length - 1;
        cb = cb[index];
      }

      const spanRunContext = ins.currRunContext().enterSpan(span);
      const onQueryEnd = ins.bindFunctionToRunContext(
        spanRunContext,
        (_err) => {
          agent.logger.debug('intercepted end of %s.prototype.%s', klass, name);
          span.end();
        },
      );

      if (typeof cb === 'function') {
        arguments[index] = ins.bindFunction((err, res) => {
          onQueryEnd(err);
          return cb(err, res);
        });
        return orig.apply(this, arguments);
      } else {
        var queryOrPromise = orig.apply(this, arguments);

        // It is important to prefer `.on` to `.then` for pg <7 >=6.3.0, because
        // `query.then` is broken in those versions. See
        // https://github.com/brianc/node-postgres/commit/b5b49eb895727e01290e90d08292c0d61ab86322#r23267714
        if (typeof queryOrPromise.on === 'function') {
          queryOrPromise.on('end', onQueryEnd);
          queryOrPromise.on('error', onQueryEnd);
          if (queryOrPromise instanceof EventEmitter) {
            ins.bindEmitter(queryOrPromise);
          }
        } else if (typeof queryOrPromise.then === 'function') {
          queryOrPromise.then(() => {
            onQueryEnd();
          }, onQueryEnd);
        } else {
          agent.logger.debug(
            'ERROR: unknown pg query type: %s',
            typeof queryOrPromise,
          );
        }

        return queryOrPromise;
      }
    };
  }