Files
klz-cables.com/.pnpm-store/v10/files/ce/fed6a048e38f3128d591720e8d7b058ede8c03986daec40216a2bd92a7296fbceae87bc98b9529ed263598a443053c61edd588d910ff5a5306a70eb7cd5763
Marc Mintel 5397309103
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
fix(products): fix breadcrumbs and product filtering (backport from main)
2026-02-24 16:04:21 +01:00

143 lines
5.0 KiB
Plaintext

import { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';
import { getActiveSpan, getRootSpan, spanToJSON, GLOBAL_OBJ, debug, startNewTrace, Scope, SEMANTIC_ATTRIBUTE_SENTRY_OP } from '@sentry/core';
import { DEBUG_BUILD } from '../debug-build.js';
import { ATTR_NEXT_SEGMENT, ATTR_NEXT_SPAN_TYPE, ATTR_NEXT_SPAN_NAME } from '../nextSpanAttributes.js';
import { TRANSACTION_ATTR_SHOULD_DROP_TRANSACTION } from '../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 Scope();
commonIsolationScopeMap.set(commonObject, newIsolationScope);
return newIsolationScope;
}
} else {
return new 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 = (GLOBAL_OBJ )
.AsyncLocalStorage;
if (!MaybeGlobalAsyncLocalStorage) {
DEBUG_BUILD &&
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 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 = getActiveSpan();
if (nextJsOwnedSpan) {
const rootSpan = getRootSpan(nextJsOwnedSpan);
const rootSpanAttributes = spanToJSON(rootSpan).data;
if (rootSpanAttributes?.['next.span_type']) {
getRootSpan(nextJsOwnedSpan)?.setAttribute(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[ATTR_NEXT_SPAN_TYPE] === 'NextNodeServer.getLayoutOrPageModule' &&
spanAttributes[ATTR_NEXT_SPAN_NAME] === 'resolve segment modules' &&
typeof spanAttributes[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[ATTR_NEXT_SEGMENT] ;
const route = rootSpanAttributes[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(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'function.nextjs');
}
export { commonObjectToIsolationScope, dropNextjsRootContext, escapeNextjsTracing, getEnhancedResolveSegmentSpanName, isResolveSegmentSpan, maybeEnhanceServerComponentSpanName };
//# sourceMappingURL=tracingUtils.js.map