function wrapHandler({ handler, index, argsLength, useAllParams, ctx, shim }) {
  if (
    isWrapped(shim, handler) ||
    (!useAllParams && index !== argsLength - 1) // Don't want all and not last
  ) {
    ctx.isWrapped = shim.isWrapped(handler)
    return handler
  }

  return function __NR_wrappedThenHandler() {
    if (!ctx?.handler?.[symbols.context]) {
      return handler.apply(this, arguments)
    }

    let promSegment = ctx.handler[symbols.context].getSegment()
    const segment = promSegment || shim.getSegment()
    if (segment && segment !== promSegment) {
      ctx.handler[symbols.context].setSegment(segment)
      promSegment = segment
    }
    const transaction = ctx.handler[symbols.context].getTransaction()

    let context = shim.tracer.getContext()
    context = context.enterSegment({ transaction, segment: promSegment })
    let ret = shim.applyContext({
      func: handler,
      context,
      full: true,
      boundThis: this,
      args: arguments
    })
    if (ret && typeof ret.then === 'function') {
      ret = ctx.handler[symbols.context].continueContext(ret)
    }

    return ret
  }
}
@private
@param {object} params object passed to wrapHandler
@param {Function} params.handler to wrap
@param {number} params.index index of argument
@param {number} params.argsLength length of args
@param {boolean} params.useAllParams flag to use all params
@param {object} params.ctx context passed in to store the next handler and isWrapped
@param {object} params.shim shim instance
@returns {Function} wrapped function