Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
150 lines
5.3 KiB
Plaintext
150 lines
5.3 KiB
Plaintext
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
|
const semanticConventions = require('@opentelemetry/semantic-conventions');
|
|
const core = require('@sentry/core');
|
|
const debugBuild = require('../debug-build.js');
|
|
const nextSpanAttributes = require('../nextSpanAttributes.js');
|
|
const spanAttributesWithLogicAttached = require('../span-attributes-with-logic-attached.js');
|
|
|
|
const PAGE_SEGMENT = '__PAGE__';
|
|
|
|
const commonIsolationScopeMap = new WeakMap();
|
|
|
|
/**
|
|
* Takes a shared (garbage collectable) object between resources, e.g. a headers object shared between Next.js server components and returns a common propagation context.
|
|
*
|
|
* @param commonObject The shared object.
|
|
* @param isolationScope The isolationScope that should be shared between all the resources if no isolation scope was created yet.
|
|
* @returns the shared isolation scope.
|
|
*/
|
|
function commonObjectToIsolationScope(commonObject) {
|
|
if (typeof commonObject === 'object' && commonObject) {
|
|
const memoIsolationScope = commonIsolationScopeMap.get(commonObject);
|
|
if (memoIsolationScope) {
|
|
return memoIsolationScope;
|
|
} else {
|
|
const newIsolationScope = new core.Scope();
|
|
commonIsolationScopeMap.set(commonObject, newIsolationScope);
|
|
return newIsolationScope;
|
|
}
|
|
} else {
|
|
return new core.Scope();
|
|
}
|
|
}
|
|
|
|
let nextjsEscapedAsyncStorage;
|
|
|
|
/**
|
|
* Will mark the execution context of the callback as "escaped" from Next.js internal tracing by unsetting the active
|
|
* span and propagation context. When an execution passes through this function multiple times, it is a noop after the
|
|
* first time.
|
|
*/
|
|
function escapeNextjsTracing(cb) {
|
|
const MaybeGlobalAsyncLocalStorage = (core.GLOBAL_OBJ )
|
|
.AsyncLocalStorage;
|
|
|
|
if (!MaybeGlobalAsyncLocalStorage) {
|
|
debugBuild.DEBUG_BUILD &&
|
|
core.debug.warn(
|
|
"Tried to register AsyncLocalStorage async context strategy in a runtime that doesn't support AsyncLocalStorage.",
|
|
);
|
|
return cb();
|
|
}
|
|
|
|
if (!nextjsEscapedAsyncStorage) {
|
|
nextjsEscapedAsyncStorage = new MaybeGlobalAsyncLocalStorage();
|
|
}
|
|
|
|
if (nextjsEscapedAsyncStorage.getStore()) {
|
|
return cb();
|
|
} else {
|
|
return core.startNewTrace(() => {
|
|
return nextjsEscapedAsyncStorage.run(true, () => {
|
|
return cb();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ideally this function never lands in the develop branch.
|
|
*
|
|
* Drops the entire span tree this function was called in, if it was a span tree created by Next.js.
|
|
*/
|
|
function dropNextjsRootContext() {
|
|
const nextJsOwnedSpan = core.getActiveSpan();
|
|
if (nextJsOwnedSpan) {
|
|
const rootSpan = core.getRootSpan(nextJsOwnedSpan);
|
|
const rootSpanAttributes = core.spanToJSON(rootSpan).data;
|
|
if (rootSpanAttributes?.['next.span_type']) {
|
|
core.getRootSpan(nextJsOwnedSpan)?.setAttribute(spanAttributesWithLogicAttached.TRANSACTION_ATTR_SHOULD_DROP_TRANSACTION, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if the span is a resolve segment span.
|
|
* @param spanAttributes The attributes of the span to check.
|
|
* @returns True if the span is a resolve segment span, false otherwise.
|
|
*/
|
|
function isResolveSegmentSpan(spanAttributes) {
|
|
return (
|
|
spanAttributes[nextSpanAttributes.ATTR_NEXT_SPAN_TYPE] === 'NextNodeServer.getLayoutOrPageModule' &&
|
|
spanAttributes[nextSpanAttributes.ATTR_NEXT_SPAN_NAME] === 'resolve segment modules' &&
|
|
typeof spanAttributes[nextSpanAttributes.ATTR_NEXT_SEGMENT] === 'string'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns the enhanced name for a resolve segment span.
|
|
* @param segment The segment of the resolve segment span.
|
|
* @param route The route of the resolve segment span.
|
|
* @returns The enhanced name for the resolve segment span.
|
|
*/
|
|
function getEnhancedResolveSegmentSpanName({ segment, route }) {
|
|
if (segment === PAGE_SEGMENT) {
|
|
return `resolve page server component "${route}"`;
|
|
}
|
|
|
|
if (segment === '') {
|
|
return 'resolve root layout server component';
|
|
}
|
|
|
|
return `resolve layout server component "${segment}"`;
|
|
}
|
|
|
|
/**
|
|
* Maybe enhances the span name for a resolve segment span.
|
|
* If the span is not a resolve segment span, this function does nothing.
|
|
* @param activeSpan The active span.
|
|
* @param spanAttributes The attributes of the span to check.
|
|
* @param rootSpanAttributes The attributes of the according root span.
|
|
*/
|
|
function maybeEnhanceServerComponentSpanName(
|
|
activeSpan,
|
|
spanAttributes,
|
|
rootSpanAttributes,
|
|
) {
|
|
if (!isResolveSegmentSpan(spanAttributes)) {
|
|
return;
|
|
}
|
|
|
|
const segment = spanAttributes[nextSpanAttributes.ATTR_NEXT_SEGMENT] ;
|
|
const route = rootSpanAttributes[semanticConventions.ATTR_HTTP_ROUTE];
|
|
const enhancedName = getEnhancedResolveSegmentSpanName({ segment, route: typeof route === 'string' ? route : '' });
|
|
activeSpan.updateName(enhancedName);
|
|
activeSpan.setAttributes({
|
|
'sentry.nextjs.ssr.function.type': segment === PAGE_SEGMENT ? 'Page' : 'Layout',
|
|
'sentry.nextjs.ssr.function.route': route,
|
|
});
|
|
activeSpan.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'function.nextjs');
|
|
}
|
|
|
|
exports.commonObjectToIsolationScope = commonObjectToIsolationScope;
|
|
exports.dropNextjsRootContext = dropNextjsRootContext;
|
|
exports.escapeNextjsTracing = escapeNextjsTracing;
|
|
exports.getEnhancedResolveSegmentSpanName = getEnhancedResolveSegmentSpanName;
|
|
exports.isResolveSegmentSpan = isResolveSegmentSpan;
|
|
exports.maybeEnhanceServerComponentSpanName = maybeEnhanceServerComponentSpanName;
|
|
//# sourceMappingURL=tracingUtils.js.map
|