function wrapCallback({ shim, args, cbIdx, parentSegment, spec }) {
  const cb = args[cbIdx]
  const realParent = parentSegment || shim.getSegment()
  const context = shim.tracer.getContext()
  const transaction = context?.transaction

  args[cbIdx] = shim.wrap(cb, null, function callbackWrapper(shim, fn, name) {
    return function wrappedCallback() {
      if (realParent) {
        realParent.opaque = false
      }
      const segment = _rawCreateSegment({
        shim,
        parent: realParent,
        transaction,
        spec: new specs.SegmentSpec({
          name: 'Callback: ' + name
        })
      })

      if (segment) {
        segment.async = false
      }

      if (spec?.after) {
        spec.after({ shim, fn, name, args: arguments, segment: realParent, transaction })
      }

      // CB may end the transaction so update the parent's time preemptively.
      realParent && realParent.touch()
      const newContext = context.enterSegment({ segment })
      return shim.applyContext({
        func: cb,
        context: newContext,
        full: true,
        boundThis: this,
        args: arguments
      })
    }
  })
  shim.storeSegment(args[cbIdx], realParent)
}
Wraps the callback and creates a segment for the callback function.
It will also call an after hook with the arguments passed to callback

@private
@param {Object} params to function
@param {Shim} params.shim instance of shim
@param {Array | object} params.args
 The arguments array to pull the cb from.
@param {number|string} params.cbIdx
 The index of the callback.
@param {TraceSegment} [params.parentSegment]
 The segment to use as the callback segment's parent. Defaults to the
 currently active segment.
@param {Spec} params.spec spec to original wrapped function, used to call after method with arguments passed to callback