UNPKG

next

Version:

The React Framework

96 lines (95 loc) 5.03 kB
/** * 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