96 lines
4.9 KiB
JavaScript
96 lines
4.9 KiB
JavaScript
/**
|
|
* This extension augments opentelemetry after registration if applicable.
|
|
* This extension must only be loaded in Node environments.
|
|
*/ "use strict";
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
Object.defineProperty(exports, "afterRegistration", {
|
|
enumerable: true,
|
|
get: function() {
|
|
return afterRegistration;
|
|
}
|
|
});
|
|
const _workunitasyncstorageexternal = require("../../app-render/work-unit-async-storage.external");
|
|
const _invarianterror = require("../../../shared/lib/invariant-error");
|
|
const _clientandserverreferences = require("../../../lib/client-and-server-references");
|
|
function afterRegistration() {
|
|
if (process.env.NEXT_RUNTIME === 'edge') {
|
|
throw Object.defineProperty(new _invarianterror.InvariantError('Node.js instrumentation extensions should not be loaded in the Edge runtime.'), "__NEXT_ERROR_CODE", {
|
|
value: "E775",
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
}
|
|
extendTracerProviderForCacheComponents();
|
|
}
|
|
// In theory we only want to enable this extension when cacheComponents is enabled
|
|
// however there are certain servers that might load instrumentation before nextConfig is available
|
|
// and so gating it on the config might lead to skipping this extension even when it is necessary.
|
|
// When cacheComponents is disabled this extension should be a no-op so we enable it universally.
|
|
// Additionally, soon, cacheComponents will be enabled always so this just pulls the extension forward in time
|
|
function extendTracerProviderForCacheComponents() {
|
|
let api;
|
|
// we want to allow users to use their own version of @opentelemetry/api if they
|
|
// want to, so we try to require it first, and if it fails we fall back to the
|
|
// version that is bundled with Next.js
|
|
// this is because @opentelemetry/api has to be synced with the version of
|
|
// @opentelemetry/tracing that is used, and we don't want to force users to use
|
|
// the version that is bundled with Next.js.
|
|
// the API is ~stable, so this should be fine
|
|
try {
|
|
api = require('@opentelemetry/api');
|
|
} catch (err) {
|
|
api = require('next/dist/compiled/@opentelemetry/api');
|
|
}
|
|
const provider = api.trace.getTracerProvider();
|
|
// When Cache Components is enabled we need to instrument the tracer
|
|
// to exit the workUnitAsyncStorage context when generating spans.
|
|
const originalGetTracer = provider.getTracer.bind(provider);
|
|
provider.getTracer = (...args)=>{
|
|
const tracer = originalGetTracer.apply(provider, args);
|
|
if (WeakTracers.has(tracer)) {
|
|
return tracer;
|
|
}
|
|
const originalStartSpan = tracer.startSpan;
|
|
tracer.startSpan = (...startSpanArgs)=>{
|
|
return _workunitasyncstorageexternal.workUnitAsyncStorage.exit(()=>originalStartSpan.apply(tracer, startSpanArgs));
|
|
};
|
|
const originalStartActiveSpan = tracer.startActiveSpan;
|
|
// @ts-ignore TS doesn't recognize the overloads correctly
|
|
tracer.startActiveSpan = (...startActiveSpanArgs)=>{
|
|
const workUnitStore = _workunitasyncstorageexternal.workUnitAsyncStorage.getStore();
|
|
if (!workUnitStore) {
|
|
// @ts-ignore TS doesn't recognize the overloads correctly
|
|
return originalStartActiveSpan.apply(tracer, startActiveSpanArgs);
|
|
}
|
|
let fnIdx = 0;
|
|
if (startActiveSpanArgs.length === 2 && typeof startActiveSpanArgs[1] === 'function') {
|
|
fnIdx = 1;
|
|
} else if (startActiveSpanArgs.length === 3 && typeof startActiveSpanArgs[2] === 'function') {
|
|
fnIdx = 2;
|
|
} else if (startActiveSpanArgs.length > 3 && typeof startActiveSpanArgs[3] === 'function') {
|
|
fnIdx = 3;
|
|
}
|
|
if (fnIdx) {
|
|
const originalFn = startActiveSpanArgs[fnIdx];
|
|
if ((0, _clientandserverreferences.isUseCacheFunction)(originalFn)) {
|
|
console.error('A Cache Function (`use cache`) was passed to startActiveSpan which means it will receive a Span argument with a possibly random ID on every invocation leading to cache misses. Provide a wrapping function around the Cache Function that does not forward the Span argument to avoid this issue.');
|
|
}
|
|
startActiveSpanArgs[fnIdx] = withWorkUnitContext(workUnitStore, originalFn);
|
|
}
|
|
return _workunitasyncstorageexternal.workUnitAsyncStorage.exit(()=>{
|
|
// @ts-ignore TS doesn't recognize the overloads correctly
|
|
return originalStartActiveSpan.apply(tracer, startActiveSpanArgs);
|
|
});
|
|
};
|
|
WeakTracers.add(tracer);
|
|
return tracer;
|
|
};
|
|
}
|
|
const WeakTracers = new WeakSet();
|
|
function withWorkUnitContext(workUnitStore, fn) {
|
|
return (...args)=>_workunitasyncstorageexternal.workUnitAsyncStorage.run(workUnitStore, fn, ...args);
|
|
}
|
|
|
|
//# sourceMappingURL=instrumentation-node-extensions.js.map
|