@sentry/node
Version:
Sentry Node SDK using OpenTelemetry for performance instrumentation
136 lines (115 loc) • 3.42 kB
JavaScript
import { registerInstrumentations } from '@opentelemetry/instrumentation';
/** Exported only for tests. */
const INSTRUMENTED = {};
/**
* Instrument an OpenTelemetry instrumentation once.
* This will skip running instrumentation again if it was already instrumented.
*/
function generateInstrumentOnce(
name,
creatorOrClass,
optionsCallback,
) {
if (optionsCallback) {
return _generateInstrumentOnceWithOptions(
name,
creatorOrClass ,
optionsCallback,
);
}
return _generateInstrumentOnce(name, creatorOrClass );
}
// The plain version without handling of options
// Should not be used with custom options that are mutated in the creator!
function _generateInstrumentOnce(
name,
creator,
) {
return Object.assign(
(options) => {
const instrumented = INSTRUMENTED[name] ;
if (instrumented) {
// If options are provided, ensure we update them
if (options) {
instrumented.setConfig(options);
}
return instrumented;
}
const instrumentation = creator(options);
INSTRUMENTED[name] = instrumentation;
registerInstrumentations({
instrumentations: [instrumentation],
});
return instrumentation;
},
{ id: name },
);
}
// This version handles options properly
function _generateInstrumentOnceWithOptions
(
name,
instrumentationClass,
optionsCallback,
) {
return Object.assign(
(_options) => {
const options = optionsCallback(_options);
const instrumented = INSTRUMENTED[name] ;
if (instrumented) {
// Ensure we update options
instrumented.setConfig(options);
return instrumented;
}
const instrumentation = new instrumentationClass(options) ;
INSTRUMENTED[name] = instrumentation;
registerInstrumentations({
instrumentations: [instrumentation],
});
return instrumentation;
},
{ id: name },
);
}
/**
* Ensure a given callback is called when the instrumentation is actually wrapping something.
* This can be used to ensure some logic is only called when the instrumentation is actually active.
*
* This function returns a function that can be invoked with a callback.
* This callback will either be invoked immediately
* (e.g. if the instrumentation was already wrapped, or if _wrap could not be patched),
* or once the instrumentation is actually wrapping something.
*
* Make sure to call this function right after adding the instrumentation, otherwise it may be too late!
* The returned callback can be used any time, and also multiple times.
*/
function instrumentWhenWrapped(instrumentation) {
let isWrapped = false;
let callbacks = [];
if (!hasWrap(instrumentation)) {
isWrapped = true;
} else {
const originalWrap = instrumentation['_wrap'];
instrumentation['_wrap'] = (...args) => {
isWrapped = true;
callbacks.forEach(callback => callback());
callbacks = [];
return originalWrap(...args);
};
}
const registerCallback = (callback) => {
if (isWrapped) {
callback();
} else {
callbacks.push(callback);
}
};
return registerCallback;
}
function hasWrap(
instrumentation,
) {
return typeof (instrumentation )['_wrap'] === 'function';
}
export { INSTRUMENTED, generateInstrumentOnce, instrumentWhenWrapped };
//# sourceMappingURL=instrument.js.map