Skip to content

Commit

Permalink
Merge pull request #9771 from getsentry/prepare-release/7.86.0
Browse files Browse the repository at this point in the history
meta(changelog): Update changelog for 7.86.0
  • Loading branch information
mydea committed Dec 7, 2023
2 parents 829a15c + 1132994 commit ad82dad
Show file tree
Hide file tree
Showing 35 changed files with 471 additions and 135 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -976,8 +976,7 @@ jobs:
runs-on: ubuntu-20.04
timeout-minutes: 30
if: |
contains(github.event.pull_request.labels.*.name, 'ci-overhead-measurements') ||
needs.job_get_metadata.outputs.is_develop == 'true'
contains(github.event.pull_request.labels.*.name, 'ci-overhead-measurements')
steps:
- name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }})
uses: actions/checkout@v4
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@

- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott

## 7.86.0

- feat(core): Use SDK_VERSION for hub API version (#9732)
- feat(nextjs): Emit warning if your app directory doesn't have a global-error.js file (#9753)
- feat(node): Add cloudflare pages commit sha (#9751)
- feat(remix): Bump @sentry/cli to 2.22.3 (#9741)
- fix(nextjs): Don't accidentally trigger static generation bailout (#9749)
- fix(node): Guard `process.env.NODE_ENV` access in Spotlight integration (#9748)
- fix(utils): Fix XHR instrumentation early return (#9770)
- ref(remix): Rework Error Handling (#9725)

## 7.85.0

- feat(core): Add `addEventProcessor` method (#9554)
Expand Down
2 changes: 1 addition & 1 deletion docs/using-yalc.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ to add the local SDK package to your project.

### My changes are not applied to the test project

Did you run `yarn build && yarn publish:yalc` after making your changes?
Did you run `yarn build && yarn yalc:publish` after making your changes?

### My test project uses Vite and I still don't see changes

Expand Down
8 changes: 4 additions & 4 deletions packages/astro/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

- [Official SDK Docs](https://docs.sentry.io/platforms/javascript/guides/astro/)

## Experimental Note
## SDK Status

This SDK is experimental and in Alpha state. Breaking changes can occurr at any time.
This SDK is in Beta and not yet fully stable.
If you have feedback or encounter any bugs, feel free to [open an issue](https://github.com/getsentry/sentry-javascript/issues/new/choose).

## General
Expand Down Expand Up @@ -58,9 +58,9 @@ SENTRY_AUTH_TOKEN="your-token"

### Server Instrumentation

For Astro apps configured for (hybrid) Server Side Rendering (SSR), the Sentry integration will automatically add middleware to your server to instrument incoming requests **if you're using Astro 3.5.0 or newer**.
For Astro apps configured for (hybrid) Server Side Rendering (SSR), the Sentry integration will automatically add middleware to your server to instrument incoming requests **if you're using Astro 3.5.2 or newer**.

If you're using Astro <3.5.0, complete the setup by adding the Sentry middleware to your `src/middleware.js` file:
If you're using Astro <3.5.2, complete the setup by adding the Sentry middleware to your `src/middleware.js` file:

```javascript
// src/middleware.js
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/hub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { DEFAULT_ENVIRONMENT } from './constants';
import { DEBUG_BUILD } from './debug-build';
import { Scope } from './scope';
import { closeSession, makeSession, updateSession } from './session';
import { SDK_VERSION } from './version';

/**
* API compatibility version of this hub.
Expand All @@ -35,7 +36,7 @@ import { closeSession, makeSession, updateSession } from './session';
*
* @hidden
*/
export const API_VERSION = 4;
export const API_VERSION = parseFloat(SDK_VERSION);

/**
* Default maximum number of breadcrumbs added to an event. Can be overwritten
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ Sentry.init({
tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production!
});

export function handleError(error: unknown, { request }: DataFunctionArgs): void {
Sentry.captureRemixServerException(error, 'remix.server', request);
}
export const handleError = Sentry.wrapRemixHandleError;

export default function handleRequest(
request: Request,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ Sentry.init({
tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production!
});

export function handleError(error: unknown, { request }: DataFunctionArgs): void {
Sentry.captureRemixServerException(error, 'remix.server', request);
}
export const handleError = Sentry.wrapRemixHandleError;

export default function handleRequest(
request: Request,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { NextResponse } from 'next/server';

export async function GET() {
return NextResponse.json({ result: 'static response' });
}

// This export makes it so that this route is always dynamically rendered (i.e Sentry will trace)
export const revalidate = 0;

// This export makes it so that this route will throw an error if the Request object is accessed in some way.
export const dynamic = 'error';
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,10 @@ test.describe('Edge runtime', () => {
expect(routehandlerError.contexts?.runtime?.name).toBe('vercel-edge');
});
});

test('should not crash route handlers that are configured with `export const dynamic = "error"`', async ({
request,
}) => {
const response = await request.get('/route-handlers/static');
expect(await response.json()).toStrictEqual({ result: 'static response' });
});
9 changes: 3 additions & 6 deletions packages/nextjs/src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,19 @@ export type ServerComponentContext = {
};

export interface RouteHandlerContext {
// TODO(v8): Remove
/**
* @deprecated The SDK will automatically pick up the method from the incoming Request object instead.
*/
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
parameterizedRoute: string;
// TODO(v8): Remove
/**
* @deprecated The SDK will automatically pick up the `sentry-trace` header from the incoming Request object instead.
* @deprecated pass a complete `Headers` object with the `headers` field instead.
*/
sentryTraceHeader?: string;
// TODO(v8): Remove
/**
* @deprecated The SDK will automatically pick up the `baggage` header from the incoming Request object instead.
* @deprecated pass a complete `Headers` object with the `headers` field instead.
*/
baggageHeader?: string;
headers?: WebFetchHeaders;
}

export type VercelCronsConfig = { path?: string; schedule?: string }[] | undefined;
Expand Down
21 changes: 8 additions & 13 deletions packages/nextjs/src/common/wrapRouteHandlerWithSentry.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { addTracingExtensions, captureException, flush, getCurrentHub, runWithAsyncContext, trace } from '@sentry/core';
import { tracingContextFromHeaders, winterCGRequestToRequestData } from '@sentry/utils';
import { tracingContextFromHeaders, winterCGHeadersToDict } from '@sentry/utils';

import { isRedirectNavigationError } from './nextNavigationErrorUtils';
import type { RouteHandlerContext } from './types';
Expand All @@ -15,23 +15,16 @@ export function wrapRouteHandlerWithSentry<F extends (...args: any[]) => any>(
): (...args: Parameters<F>) => ReturnType<F> extends Promise<unknown> ? ReturnType<F> : Promise<ReturnType<F>> {
addTracingExtensions();
// eslint-disable-next-line deprecation/deprecation
const { method, parameterizedRoute, baggageHeader, sentryTraceHeader } = context;
const { method, parameterizedRoute, baggageHeader, sentryTraceHeader, headers } = context;
return new Proxy(routeHandler, {
apply: (originalFunction, thisArg, args) => {
return runWithAsyncContext(async () => {
const hub = getCurrentHub();
const currentScope = hub.getScope();

let req: Request | undefined;
let reqMethod: string | undefined;
if (args[0] instanceof Request) {
req = args[0];
reqMethod = req.method;
}

const { traceparentData, dynamicSamplingContext, propagationContext } = tracingContextFromHeaders(
sentryTraceHeader,
baggageHeader,
sentryTraceHeader ?? headers?.get('sentry-trace') ?? undefined,
baggageHeader ?? headers?.get('baggage'),
);
currentScope.setPropagationContext(propagationContext);

Expand All @@ -40,11 +33,13 @@ export function wrapRouteHandlerWithSentry<F extends (...args: any[]) => any>(
res = await trace(
{
op: 'http.server',
name: `${reqMethod ?? method} ${parameterizedRoute}`,
name: `${method} ${parameterizedRoute}`,
status: 'ok',
...traceparentData,
metadata: {
request: req ? winterCGRequestToRequestData(req) : undefined,
request: {
headers: headers ? winterCGHeadersToDict(headers) : undefined,
},
source: 'route',
dynamicSamplingContext: traceparentData && !dynamicSamplingContext ? {} : dynamicSamplingContext,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as Sentry from '@sentry/nextjs';
import type { WebFetchHeaders } from '@sentry/types';
// @ts-expect-error Because we cannot be sure if the RequestAsyncStorage module exists (it is not part of the Next.js public
// API) we use a shim if it doesn't exist. The logic for this is in the wrapping loader.
import { requestAsyncStorage } from '__SENTRY_NEXTJS_REQUEST_ASYNC_STORAGE_SHIM__';
Expand Down Expand Up @@ -34,12 +35,14 @@ function wrapHandler<T>(handler: T, method: 'GET' | 'POST' | 'PUT' | 'PATCH' | '
apply: (originalFunction, thisArg, args) => {
let sentryTraceHeader: string | undefined | null = undefined;
let baggageHeader: string | undefined | null = undefined;
let headers: WebFetchHeaders | undefined = undefined;

// We try-catch here just in case the API around `requestAsyncStorage` changes unexpectedly since it is not public API
try {
const requestAsyncStore = requestAsyncStorage.getStore();
sentryTraceHeader = requestAsyncStore?.headers.get('sentry-trace') ?? undefined;
baggageHeader = requestAsyncStore?.headers.get('baggage') ?? undefined;
headers = requestAsyncStore?.headers;
} catch (e) {
/** empty */
}
Expand All @@ -50,6 +53,7 @@ function wrapHandler<T>(handler: T, method: 'GET' | 'POST' | 'PUT' | 'PATCH' | '
parameterizedRoute: '__ROUTE__',
sentryTraceHeader,
baggageHeader,
headers,
}).apply(thisArg, args);
},
});
Expand Down
19 changes: 19 additions & 0 deletions packages/nextjs/src/config/webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ let showedMissingOrgSlugErrorMsg = false;
let showedMissingProjectSlugErrorMsg = false;
let showedHiddenSourceMapsWarningMsg = false;
let showedMissingCliBinaryWarningMsg = false;
let showedMissingGlobalErrorWarningMsg = false;

// TODO: merge default SentryWebpackPlugin ignore with their SentryWebpackPlugin ignore or ignoreFile
// TODO: merge default SentryWebpackPlugin include with their SentryWebpackPlugin include
Expand Down Expand Up @@ -328,6 +329,24 @@ export function constructWebpackConfigFunction(
});
}

if (appDirPath) {
const hasGlobalErrorFile = ['global-error.js', 'global-error.jsx', 'global-error.ts', 'global-error.tsx'].some(
globalErrorFile => fs.existsSync(path.join(appDirPath!, globalErrorFile)),
);

if (!hasGlobalErrorFile && !showedMissingGlobalErrorWarningMsg) {
// eslint-disable-next-line no-console
console.log(
`${chalk.yellow(
'warn',
)} - It seems like you don't have a global error handler set up. It is recommended that you add a ${chalk.cyan(
'global-error.js',
)} file with Sentry instrumentation so that React rendering errors are reported to Sentry. Read more: https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#react-render-errors-in-app-router`,
);
showedMissingGlobalErrorWarningMsg = true;
}
}

// The SDK uses syntax (ES6 and ES6+ features like object spread) which isn't supported by older browsers. For users
// who want to support such browsers, `transpileClientSDK` allows them to force the SDK code to go through the same
// transpilation that their code goes through. We don't turn this on by default because it increases bundle size
Expand Down
4 changes: 2 additions & 2 deletions packages/node/src/integrations/spotlight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ export class Spotlight implements Integration {
* Sets up forwarding envelopes to the Spotlight Sidecar
*/
public setup(client: Client): void {
if (process.env.NODE_ENV !== 'development') {
logger.warn("[Spotlight] It seems you're not in dev mode. Do you really want to have Spoltight enabled?");
if (typeof process === 'object' && process.env && process.env.NODE_ENV !== 'development') {
logger.warn("[Spotlight] It seems you're not in dev mode. Do you really want to have Spotlight enabled?");
}
connectToSpotlight(client, this._options);
}
Expand Down
2 changes: 2 additions & 0 deletions packages/node/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ export function getSentryRelease(fallback?: string): string | undefined {
process.env.ZEIT_GITHUB_COMMIT_SHA ||
process.env.ZEIT_GITLAB_COMMIT_SHA ||
process.env.ZEIT_BITBUCKET_COMMIT_SHA ||
// Cloudflare Pages - https://developers.cloudflare.com/pages/platform/build-configuration/#environment-variables
process.env.CF_PAGES_COMMIT_SHA ||
fallback
);
}
Expand Down
36 changes: 34 additions & 2 deletions packages/node/test/integrations/spotlight.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ describe('Spotlight', () => {
integration.setup(client);

expect(loggerSpy).toHaveBeenCalledWith(
expect.stringContaining("It seems you're not in dev mode. Do you really want to have Spoltight enabled?"),
expect.stringContaining("It seems you're not in dev mode. Do you really want to have Spotlight enabled?"),
);

process.env.NODE_ENV = oldEnvValue;
Expand All @@ -152,9 +152,41 @@ describe('Spotlight', () => {
integration.setup(client);

expect(loggerSpy).not.toHaveBeenCalledWith(
expect.stringContaining("It seems you're not in dev mode. Do you really want to have Spoltight enabled?"),
expect.stringContaining("It seems you're not in dev mode. Do you really want to have Spotlight enabled?"),
);

process.env.NODE_ENV = oldEnvValue;
});

it('handles `process` not being available', () => {
const originalProcess = process;

// @ts-expect-error - TS complains but we explicitly wanna test this
delete global.process;

const integration = new Spotlight({ sidecarUrl: 'http://localhost:8969' });
integration.setup(client);

expect(loggerSpy).not.toHaveBeenCalledWith(
expect.stringContaining("It seems you're not in dev mode. Do you really want to have Spotlight enabled?"),
);

global.process = originalProcess;
});

it('handles `process.env` not being available', () => {
const originalEnv = process.env;

// @ts-expect-error - TS complains but we explicitly wanna test this
delete process.env;

const integration = new Spotlight({ sidecarUrl: 'http://localhost:8969' });
integration.setup(client);

expect(loggerSpy).not.toHaveBeenCalledWith(
expect.stringContaining("It seems you're not in dev mode. Do you really want to have Spotlight enabled?"),
);

process.env = originalEnv;
});
});
2 changes: 1 addition & 1 deletion packages/remix/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"access": "public"
},
"dependencies": {
"@sentry/cli": "^2.21.2",
"@sentry/cli": "^2.22.3",
"@sentry/core": "7.85.0",
"@sentry/node": "7.85.0",
"@sentry/react": "7.85.0",
Expand Down

0 comments on commit ad82dad

Please sign in to comment.