next
Version:
The React Framework
118 lines (117 loc) • 4.99 kB
JavaScript
import path from 'node:path';
import isError from '../../../lib/is-error';
import { INSTRUMENTATION_HOOK_FILENAME } from '../../../lib/constants';
import { interopDefault } from '../../../lib/interop-default';
import { afterRegistration as extendInstrumentationAfterRegistration } from './instrumentation-node-extensions';
import { getTracer, SpanStatusCode } from '../trace/tracer';
import { InstrumentationSpan } from '../trace/constants';
let cachedInstrumentationModule;
let instrumentationModuleLoadTiming;
function getInstrumentationTimestamp() {
// Date.now() is treated as synchronous I/O while Cache Components render.
return performance.timeOrigin + performance.now();
}
function traceBackdatedInstrumentationSpan(type, spanName, { startTime, endTime, error }) {
getTracer().trace(type, {
spanName,
startTime,
endTime
}, error === undefined ? ()=>undefined : (span)=>{
span == null ? void 0 : span.recordException(error);
if (isError(error)) {
span == null ? void 0 : span.setAttribute('error.type', error.name);
}
span == null ? void 0 : span.setStatus({
code: SpanStatusCode.ERROR,
message: isError(error) ? error.message : undefined
});
});
}
function traceInstrumentationModuleLoad() {
if (!instrumentationModuleLoadTiming) return;
const timing = instrumentationModuleLoadTiming;
instrumentationModuleLoadTiming = undefined;
traceBackdatedInstrumentationSpan(InstrumentationSpan.loadModule, 'load instrumentation module', timing);
}
export async function getInstrumentationModule(projectDir, distDir) {
if (cachedInstrumentationModule) {
return cachedInstrumentationModule;
}
const startTime = getInstrumentationTimestamp();
let error;
try {
cachedInstrumentationModule = interopDefault(await require(path.join(projectDir, distDir, 'server', `${INSTRUMENTATION_HOOK_FILENAME}.js`)));
return cachedInstrumentationModule;
} catch (err) {
if (isError(err) && err.code !== 'ENOENT' && err.code !== 'MODULE_NOT_FOUND' && err.code !== 'ERR_MODULE_NOT_FOUND') {
error = err;
throw err;
}
} finally{
instrumentationModuleLoadTiming ??= {
startTime,
endTime: getInstrumentationTimestamp(),
error
};
}
}
let instrumentationModulePromise = null;
async function registerInstrumentation(projectDir, distDir) {
// Ensure registerInstrumentation is not called in production build
if (process.env.NEXT_PHASE === 'phase-production-build') {
return;
}
if (!instrumentationModulePromise) {
instrumentationModulePromise = getInstrumentationModule(projectDir, distDir);
}
let instrumentation;
try {
instrumentation = await instrumentationModulePromise;
} catch (err) {
// A load error is only exportable when a provider was already installed.
traceInstrumentationModuleLoad();
throw err;
}
if (instrumentation == null ? void 0 : instrumentation.register) {
const startTime = getInstrumentationTimestamp();
let error;
try {
await instrumentation.register();
extendInstrumentationAfterRegistration();
} catch (err) {
error = err;
err.message = `An error occurred while loading instrumentation hook: ${err.message}`;
throw err;
} finally{
const endTime = getInstrumentationTimestamp();
// register() commonly installs the provider, so emit both lifecycle
// spans afterward with their original timestamps.
traceInstrumentationModuleLoad();
traceBackdatedInstrumentationSpan(InstrumentationSpan.register, 'register instrumentation', {
startTime,
endTime,
error
});
}
} else {
traceInstrumentationModuleLoad();
}
}
export async function instrumentationOnRequestError(projectDir, distDir, ...args) {
const instrumentation = await getInstrumentationModule(projectDir, distDir);
try {
var _instrumentation_onRequestError;
await (instrumentation == null ? void 0 : (_instrumentation_onRequestError = instrumentation.onRequestError) == null ? void 0 : _instrumentation_onRequestError.call(instrumentation, ...args));
} catch (err) {
// Log the soft error and continue, since the original error has already been thrown
console.error('Error in instrumentation.onRequestError:', err);
}
}
let registerInstrumentationPromise = null;
export function ensureInstrumentationRegistered(projectDir, distDir) {
if (!registerInstrumentationPromise) {
registerInstrumentationPromise = registerInstrumentation(projectDir, distDir);
}
return registerInstrumentationPromise;
}
//# sourceMappingURL=instrumentation-globals.external.js.map