@envelop/instrumentation
Version:
This package contains utility functions and types to ease the use of instrumentation accross Envelop, Yoga, whatwg-node and Hive Gateway plugins.
90 lines (89 loc) • 3.27 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getInstrumented = void 0;
exports.chain = chain;
exports.composeInstrumentation = composeInstrumentation;
exports.getInstrumentationAndPlugin = getInstrumentationAndPlugin;
const promise_helpers_1 = require("@whatwg-node/promise-helpers");
/**
* Composes 2 instrumentations together into one instrumentation.
* The first one will be the outer call, the second one the inner call.
*/
function chain(first, next) {
const merged = { ...next, ...first };
for (const key of Object.keys(merged)) {
if (key in first && key in next) {
merged[key] = (payload, wrapped) => first[key](payload, () => next[key](payload, wrapped));
}
}
return merged;
}
/**
* Composes a list of instrumentation together into one instrumentation object.
* The order of execution will respect the order of the array,
* the first one being the outter most call, the last one the inner most call.
*/
function composeInstrumentation(instrumentation) {
return instrumentation.length > 0 ? instrumentation.reduce(chain) : undefined;
}
/**
* Extract instrumentation from a list of plugins.
* It returns instrumentation found, and the list of plugins without their instrumentation.
*
* You can use this to easily customize the composition of the instrumentation if the default one
* doesn't suits your needs.
*/
function getInstrumentationAndPlugin(plugins) {
const pluginInstrumentation = [];
const newPlugins = [];
for (const { instrumentation, ...plugin } of plugins) {
if (instrumentation) {
pluginInstrumentation.push(instrumentation);
}
newPlugins.push(plugin);
}
return { pluginInstrumentation, plugins: newPlugins };
}
/**
* A helper to instrument a function.
*
* @param payload: The first argument that will be passed to the instrumentation on each function call
* @returns Function and Async Functions factories allowing to wrap a function with a given instrument.
*/
const getInstrumented = (payload) => ({
/**
* Wraps the `wrapped` function with the given `instrument` wrapper.
* @returns The wrapped function, or `undefined` if the instrument is `undefined`.
*/
fn(instrument, wrapped) {
if (!instrument) {
return wrapped;
}
return (...args) => {
let result;
instrument(payload, () => {
result = wrapped(...args);
});
return result;
};
},
/**
* Wraps the `wrapped` function with the given `instrument` wrapper.
* @returns The wrapped function, or `undefined` if the instrument is `undefined`.
*/
asyncFn(instrument, wrapped) {
if (!instrument) {
return wrapped;
}
return (...args) => {
let result;
return (0, promise_helpers_1.handleMaybePromise)(() => instrument(payload, () => {
result = wrapped(...args);
return (0, promise_helpers_1.isPromise)(result) ? result.then(() => undefined) : undefined;
}), () => {
return result;
});
};
},
});
exports.getInstrumented = getInstrumented;