makeNewProfiledTapFn = (hookName, tracer, { name, type, fn }) => {
	const defaultCategory = ["blink.user_timing"];

	switch (type) {
		case "promise":
			return (...args) => {
				const id = ++tracer.counter;
				tracer.trace.begin({
					name,
					id,
					cat: defaultCategory
				});
				const promise =
					/** @type {Promise<(...args: EXPECTED_ANY[]) => EXPECTED_ANY>} */
					(fn(...args));
				return promise.then(r => {
					tracer.trace.end({
						name,
						id,
						cat: defaultCategory
					});
					return r;
				});
			};
		case "async":
			return (...args) => {
				const id = ++tracer.counter;
				tracer.trace.begin({
					name,
					id,
					cat: defaultCategory
				});
				const callback = args.pop();
				fn(
					...args,
					/**
					 * @param {...EXPECTED_ANY[]} r result
					 */
					(...r) => {
						tracer.trace.end({
							name,
							id,
							cat: defaultCategory
						});
						callback(...r);
					}
				);
			};
		case "sync":
			return (...args) => {
				const id = ++tracer.counter;
				// Do not instrument ourself due to the CPU
				// profile needing to be the last event in the trace.
				if (name === PLUGIN_NAME) {
					return fn(...args);
				}

				tracer.trace.begin({
					name,
					id,
					cat: defaultCategory
				});
				let r;
				try {
					r = fn(...args);
				} catch (err) {
					tracer.trace.end({
						name,
						id,
						cat: defaultCategory
					});
					throw err;
				}
				tracer.trace.end({
					name,
					id,
					cat: defaultCategory
				});
				return r;
			};
		default:
			return fn;
	}
}
@param {string} hookName Name of the hook to profile.
@param {Trace} tracer The trace object.
@param {object} options Options for the profiled fn.
@param {string} options.name Plugin name
@param {"sync" | "async" | "promise"} options.type Plugin type (sync | async | promise)
@param {PluginFunction} options.fn Plugin function
@returns {PluginFunction} Chainable hooked function.