Skip to content

Commit

Permalink
Merge branch 'develop' into sig/esm-nuxt-dev-mode
Browse files Browse the repository at this point in the history
  • Loading branch information
s1gr1d authored Aug 13, 2024
2 parents 4ee62f6 + 6c0f01a commit 9686795
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 155 deletions.
26 changes: 22 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ jobs:
profiling_node:
- 'packages/profiling-node/**'
- 'dev-packages/e2e-tests/test-applications/node-profiling/**'
any_code:
- '!**/*.md'
- name: Get PR labels
Expand All @@ -109,6 +111,8 @@ jobs:
is_release: ${{ startsWith(github.ref, 'refs/heads/release/') }}
changed_profiling_node: ${{ steps.changed.outputs.profiling_node == 'true' }}
changed_ci: ${{ steps.changed.outputs.workflow == 'true' }}
changed_any_code: ${{ steps.changed.outputs.any_code == 'true' }}

# When merging into master, or from master
is_gitflow_sync: ${{ github.head_ref == 'master' || github.ref == 'refs/heads/master' }}
has_gitflow_label:
Expand All @@ -123,6 +127,7 @@ jobs:
runs-on: ubuntu-20.04
timeout-minutes: 15
if: |
(needs.job_get_metadata.outputs.changed_any_code) &&
(needs.job_get_metadata.outputs.is_gitflow_sync == 'false' && needs.job_get_metadata.outputs.has_gitflow_label == 'false')
steps:
- name: Check out base commit (${{ github.event.pull_request.base.sha }})
Expand Down Expand Up @@ -274,24 +279,37 @@ jobs:

job_check_format:
name: Check file formatting
needs: [job_get_metadata, job_build]
needs: [job_get_metadata]
timeout-minutes: 10
runs-on: ubuntu-20.04
steps:
- name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }})
uses: actions/checkout@v4
with:
ref: ${{ env.HEAD_COMMIT }}

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version-file: 'package.json'

# we use a hash of yarn.lock as our cache key, because if it hasn't changed, our dependencies haven't changed,
# so no need to reinstall them
- name: Compute dependency cache key
id: compute_lockfile_hash
run: echo "hash=${{ hashFiles('yarn.lock', '**/package.json') }}" >> "$GITHUB_OUTPUT"

- name: Check dependency cache
uses: actions/cache/restore@v4
uses: actions/cache@v4
id: cache_dependencies
with:
path: ${{ env.CACHED_DEPENDENCY_PATHS }}
key: ${{ needs.job_build.outputs.dependency_cache_key }}
fail-on-cache-miss: true
key: ${{ steps.compute_lockfile_hash.outputs.hash }}

- name: Install dependencies
if: steps.cache_dependencies.outputs.cache-hit != 'true'
run: yarn install --ignore-engines --frozen-lockfile

- name: Check file formatting
run: yarn lint:prettier && yarn lint:biome

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"@types/node": "18.11.17",
"@types/react": "18.0.26",
"@types/react-dom": "18.0.9",
"next": "15.0.0-canary.77",
"next": "15.0.0-canary.112",
"react": "beta",
"react-dom": "beta",
"typescript": "4.9.5"
Expand Down
4 changes: 2 additions & 2 deletions packages/nextjs/src/common/captureRequestError.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { captureException, withScope } from '@sentry/core';

type RequestInfo = {
url: string;
path: string;
method: string;
headers: Record<string, string | string[] | undefined>;
};
Expand Down Expand Up @@ -33,7 +33,7 @@ export function experimental_captureRequestError(
});

scope.setContext('nextjs', {
request_path: request.url,
request_path: request.path,
router_kind: errorContext.routerKind,
router_path: errorContext.routePath,
route_type: errorContext.routeType,
Expand Down
15 changes: 12 additions & 3 deletions packages/nextjs/src/common/utils/wrapperUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
SPAN_STATUS_OK,
captureException,
continueTrace,
getTraceData,
startInactiveSpan,
startSpan,
startSpanManual,
Expand Down Expand Up @@ -88,8 +89,11 @@ export function withTracedServerSideDataFetcher<F extends (...args: any[]) => Pr
/** Name of the data fetching method - will be used for describing the data fetcher's span. */
dataFetchingMethodName: string;
},
): (...params: Parameters<F>) => Promise<ReturnType<F>> {
return async function (this: unknown, ...args: Parameters<F>): Promise<ReturnType<F>> {
): (...params: Parameters<F>) => Promise<{ data: ReturnType<F>; sentryTrace?: string; baggage?: string }> {
return async function (
this: unknown,
...args: Parameters<F>
): Promise<{ data: ReturnType<F>; sentryTrace?: string; baggage?: string }> {
return escapeNextjsTracing(() => {
const isolationScope = commonObjectToIsolationScope(req);
return withIsolationScope(isolationScope, () => {
Expand All @@ -116,8 +120,13 @@ export function withTracedServerSideDataFetcher<F extends (...args: any[]) => Pr
},
async dataFetcherSpan => {
dataFetcherSpan.setStatus({ code: SPAN_STATUS_OK });
const { 'sentry-trace': sentryTrace, baggage } = getTraceData();
try {
return await origDataFetcher.apply(this, args);
return {
sentryTrace: sentryTrace,
baggage: baggage,
data: await origDataFetcher.apply(this, args),
};
} catch (e) {
dataFetcherSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
requestSpan?.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
Expand Down
45 changes: 21 additions & 24 deletions packages/nextjs/src/common/wrapAppGetInitialPropsWithSentry.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { getActiveSpan, getDynamicSamplingContextFromSpan, getRootSpan, spanToTraceHeader } from '@sentry/core';
import { dynamicSamplingContextToSentryBaggageHeader } from '@sentry/utils';
import type App from 'next/app';

import { isBuild } from './utils/isBuild';
import { getSpanFromRequest, withErrorInstrumentation, withTracedServerSideDataFetcher } from './utils/wrapperUtils';
import { withErrorInstrumentation, withTracedServerSideDataFetcher } from './utils/wrapperUtils';

type AppGetInitialProps = (typeof App)['getInitialProps'];

Expand All @@ -26,6 +24,7 @@ export function wrapAppGetInitialPropsWithSentry(origAppGetInitialProps: AppGetI
const { req, res } = context.ctx;

const errorWrappedAppGetInitialProps = withErrorInstrumentation(wrappingTarget);

// Generally we can assume that `req` and `res` are always defined on the server:
// https://nextjs.org/docs/api-reference/data-fetching/get-initial-props#context-object
// This does not seem to be the case in dev mode. Because we have no clean way of associating the the data fetcher
Expand All @@ -37,16 +36,21 @@ export function wrapAppGetInitialPropsWithSentry(origAppGetInitialProps: AppGetI
dataFetchingMethodName: 'getInitialProps',
});

const appGetInitialProps: {
pageProps: {
_sentryTraceData?: string;
_sentryBaggage?: string;
const {
data: appGetInitialProps,
sentryTrace,
baggage,
}: {
data: {
pageProps: {
_sentryTraceData?: string;
_sentryBaggage?: string;
};
};
sentryTrace?: string;
baggage?: string;
} = await tracedGetInitialProps.apply(thisArg, args);

const activeSpan = getActiveSpan();
const requestSpan = getSpanFromRequest(req) ?? (activeSpan ? getRootSpan(activeSpan) : undefined);

// Per definition, `pageProps` is not optional, however an increased amount of users doesn't seem to call
// `App.getInitialProps(appContext)` in their custom `_app` pages which is required as per
// https://nextjs.org/docs/advanced-features/custom-app - resulting in missing `pageProps`.
Expand All @@ -55,21 +59,14 @@ export function wrapAppGetInitialPropsWithSentry(origAppGetInitialProps: AppGetI
appGetInitialProps.pageProps = {};
}

if (requestSpan) {
const sentryTrace = spanToTraceHeader(requestSpan);

// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (sentryTrace) {
appGetInitialProps.pageProps._sentryTraceData = sentryTrace;
}

const dynamicSamplingContext = getDynamicSamplingContextFromSpan(requestSpan);
const baggage = dynamicSamplingContextToSentryBaggageHeader(dynamicSamplingContext);
// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (sentryTrace) {
appGetInitialProps.pageProps._sentryTraceData = sentryTrace;
}

// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (baggage) {
appGetInitialProps.pageProps._sentryBaggage = baggage;
}
// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (baggage) {
appGetInitialProps.pageProps._sentryBaggage = baggage;
}

return appGetInitialProps;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function wrapDocumentGetInitialPropsWithSentry(
origDocumentGetInitialProps: DocumentGetInitialProps,
): DocumentGetInitialProps {
return new Proxy(origDocumentGetInitialProps, {
apply: (wrappingTarget, thisArg, args: Parameters<DocumentGetInitialProps>) => {
apply: async (wrappingTarget, thisArg, args: Parameters<DocumentGetInitialProps>) => {
if (isBuild()) {
return wrappingTarget.apply(thisArg, args);
}
Expand All @@ -37,7 +37,8 @@ export function wrapDocumentGetInitialPropsWithSentry(
dataFetchingMethodName: 'getInitialProps',
});

return tracedGetInitialProps.apply(thisArg, args);
const { data } = await tracedGetInitialProps.apply(thisArg, args);
return data;
} else {
return errorWrappedGetInitialProps.apply(thisArg, args);
}
Expand Down
42 changes: 19 additions & 23 deletions packages/nextjs/src/common/wrapErrorGetInitialPropsWithSentry.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { getActiveSpan, getDynamicSamplingContextFromSpan, getRootSpan, spanToTraceHeader } from '@sentry/core';
import { dynamicSamplingContextToSentryBaggageHeader } from '@sentry/utils';
import type { NextPageContext } from 'next';
import type { ErrorProps } from 'next/error';

import { isBuild } from './utils/isBuild';
import { getSpanFromRequest, withErrorInstrumentation, withTracedServerSideDataFetcher } from './utils/wrapperUtils';
import { withErrorInstrumentation, withTracedServerSideDataFetcher } from './utils/wrapperUtils';

type ErrorGetInitialProps = (context: NextPageContext) => Promise<ErrorProps>;

Expand Down Expand Up @@ -40,29 +38,27 @@ export function wrapErrorGetInitialPropsWithSentry(
dataFetchingMethodName: 'getInitialProps',
});

const errorGetInitialProps: ErrorProps & {
_sentryTraceData?: string;
_sentryBaggage?: string;
const {
data: errorGetInitialProps,
baggage,
sentryTrace,
}: {
data: ErrorProps & {
_sentryTraceData?: string;
_sentryBaggage?: string;
};
baggage?: string;
sentryTrace?: string;
} = await tracedGetInitialProps.apply(thisArg, args);

const activeSpan = getActiveSpan();
const requestSpan = getSpanFromRequest(req) ?? (activeSpan ? getRootSpan(activeSpan) : undefined);

if (requestSpan) {
const sentryTrace = spanToTraceHeader(requestSpan);

// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (sentryTrace) {
errorGetInitialProps._sentryTraceData = sentryTrace;
}

const dynamicSamplingContext = getDynamicSamplingContextFromSpan(requestSpan);
const baggage = dynamicSamplingContextToSentryBaggageHeader(dynamicSamplingContext);
// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (sentryTrace) {
errorGetInitialProps._sentryTraceData = sentryTrace;
}

// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (baggage) {
errorGetInitialProps._sentryBaggage = baggage;
}
// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (baggage) {
errorGetInitialProps._sentryBaggage = baggage;
}

return errorGetInitialProps;
Expand Down
42 changes: 19 additions & 23 deletions packages/nextjs/src/common/wrapGetInitialPropsWithSentry.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { getActiveSpan, getDynamicSamplingContextFromSpan, getRootSpan, spanToTraceHeader } from '@sentry/core';
import { dynamicSamplingContextToSentryBaggageHeader } from '@sentry/utils';
import type { NextPage } from 'next';

import { isBuild } from './utils/isBuild';
import { getSpanFromRequest, withErrorInstrumentation, withTracedServerSideDataFetcher } from './utils/wrapperUtils';
import { withErrorInstrumentation, withTracedServerSideDataFetcher } from './utils/wrapperUtils';

type GetInitialProps = Required<NextPage>['getInitialProps'];

Expand Down Expand Up @@ -36,29 +34,27 @@ export function wrapGetInitialPropsWithSentry(origGetInitialProps: GetInitialPro
dataFetchingMethodName: 'getInitialProps',
});

const initialProps: {
_sentryTraceData?: string;
_sentryBaggage?: string;
const {
data: initialProps,
baggage,
sentryTrace,
}: {
data: {
_sentryTraceData?: string;
_sentryBaggage?: string;
};
baggage?: string;
sentryTrace?: string;
} = (await tracedGetInitialProps.apply(thisArg, args)) ?? {}; // Next.js allows undefined to be returned from a getInitialPropsFunction.

const activeSpan = getActiveSpan();
const requestSpan = getSpanFromRequest(req) ?? (activeSpan ? getRootSpan(activeSpan) : undefined);

if (requestSpan) {
const sentryTrace = spanToTraceHeader(requestSpan);

// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (sentryTrace) {
initialProps._sentryTraceData = sentryTrace;
}

const dynamicSamplingContext = getDynamicSamplingContextFromSpan(requestSpan);
const baggage = dynamicSamplingContextToSentryBaggageHeader(dynamicSamplingContext);
// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (sentryTrace) {
initialProps._sentryTraceData = sentryTrace;
}

// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (baggage) {
initialProps._sentryBaggage = baggage;
}
// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (baggage) {
initialProps._sentryBaggage = baggage;
}

return initialProps;
Expand Down
36 changes: 14 additions & 22 deletions packages/nextjs/src/common/wrapGetServerSidePropsWithSentry.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { getActiveSpan, getDynamicSamplingContextFromSpan, getRootSpan, spanToTraceHeader } from '@sentry/core';
import { dynamicSamplingContextToSentryBaggageHeader } from '@sentry/utils';
import type { GetServerSideProps } from 'next';

import { isBuild } from './utils/isBuild';
import { getSpanFromRequest, withErrorInstrumentation, withTracedServerSideDataFetcher } from './utils/wrapperUtils';
import { withErrorInstrumentation, withTracedServerSideDataFetcher } from './utils/wrapperUtils';

/**
* Create a wrapped version of the user's exported `getServerSideProps` function
Expand Down Expand Up @@ -32,27 +30,21 @@ export function wrapGetServerSidePropsWithSentry(
dataFetchingMethodName: 'getServerSideProps',
});

const serverSideProps = await (tracedGetServerSideProps.apply(thisArg, args) as ReturnType<
typeof tracedGetServerSideProps
>);
const {
data: serverSideProps,
baggage,
sentryTrace,
} = await (tracedGetServerSideProps.apply(thisArg, args) as ReturnType<typeof tracedGetServerSideProps>);

if (serverSideProps && 'props' in serverSideProps) {
const activeSpan = getActiveSpan();
const requestSpan = getSpanFromRequest(req) ?? (activeSpan ? getRootSpan(activeSpan) : undefined);
if (requestSpan) {
const sentryTrace = spanToTraceHeader(requestSpan);

// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (sentryTrace) {
(serverSideProps.props as Record<string, unknown>)._sentryTraceData = sentryTrace;
}

const dynamicSamplingContext = getDynamicSamplingContextFromSpan(requestSpan);
const baggage = dynamicSamplingContextToSentryBaggageHeader(dynamicSamplingContext);
// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (baggage) {
(serverSideProps.props as Record<string, unknown>)._sentryBaggage = baggage;
}
// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (sentryTrace) {
(serverSideProps.props as Record<string, unknown>)._sentryTraceData = sentryTrace;
}

// The Next.js serializer throws on undefined values so we need to guard for it (#12102)
if (baggage) {
(serverSideProps.props as Record<string, unknown>)._sentryBaggage = baggage;
}
}

Expand Down
Loading

0 comments on commit 9686795

Please sign in to comment.