diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml index 21556dc2e5a1..4d81c7f233b2 100644 --- a/.github/workflows/auto-release.yml +++ b/.github/workflows/auto-release.yml @@ -24,8 +24,8 @@ jobs: with: # Parse version from head branch text: ${{ github.head_ref }} - # match: refs/heads/preprare-release/xx.xx.xx - regex: '^refs\/heads\/preprare-release\/(\d+\.\d+\.\d+)$' + # match: preprare-release/xx.xx.xx + regex: '^preprare-release\/(\d+\.\d+\.\d+)$' - name: Prepare release uses: getsentry/action-prepare-release@v1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 5493fdffbd62..6e96ee5251a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott +## 7.31.1 + +- fix(browser): Support `async` in stack frame urls (#7131) +- fix(nextjs): Make api route identifier stricter (#7126) +- fix(node): Don't rely on `this` in http integration (#7135) +- fix(replay): Fix missing fetch/xhr requests (#7134) +- fix(tracing): Export `defaultStackParser` from tracing CDN bundles (#7116) + ## 7.37.0 - feat: Add source map debug ids (#7068) diff --git a/packages/browser/src/stack-parsers.ts b/packages/browser/src/stack-parsers.ts index 7e77a6c0d8e3..d77bf0d901a2 100644 --- a/packages/browser/src/stack-parsers.ts +++ b/packages/browser/src/stack-parsers.ts @@ -31,7 +31,7 @@ function createFrame(filename: string, func: string, lineno?: number, colno?: nu // Chromium based browsers: Chrome, Brave, new Opera, new Edge const chromeRegex = - /^\s*at (?:(.*\).*?|.*?) ?\((?:address at )?)?((?:file|https?|blob|chrome-extension|address|native|eval|webpack||[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i; + /^\s*at (?:(.*\).*?|.*?) ?\((?:address at )?)?(?:async )?((?:file|https?|blob|chrome-extension|address|native|eval|webpack||[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i; const chromeEvalRegex = /\((\S*)(?::(\d+))(?::(\d+))\)/; const chrome: StackLineParserFn = line => { diff --git a/packages/browser/test/unit/tracekit/chromium.test.ts b/packages/browser/test/unit/tracekit/chromium.test.ts index 23ebf8d46118..b0df582ebeef 100644 --- a/packages/browser/test/unit/tracekit/chromium.test.ts +++ b/packages/browser/test/unit/tracekit/chromium.test.ts @@ -332,6 +332,31 @@ describe('Tracekit - Chrome Tests', () => { }); }); + it('should parse frames with async urls', () => { + const CHROME_109_ASYNC_URL = { + message: 'bad', + name: 'Error', + stack: `Error: bad + at callAnotherThing (http://localhost:5000/:20:16) + at Object.callback (async http://localhost:5000/:25:7) + at test (http://localhost:5000/:33:23)`, + }; + + const ex = exceptionFromError(parser, CHROME_109_ASYNC_URL); + + expect(ex).toEqual({ + value: 'bad', + type: 'Error', + stacktrace: { + frames: [ + { filename: 'http://localhost:5000/', function: 'test', lineno: 33, colno: 23, in_app: true }, + { filename: 'http://localhost:5000/', function: 'Object.callback', lineno: 25, colno: 7, in_app: true }, + { filename: 'http://localhost:5000/', function: 'callAnotherThing', lineno: 20, colno: 16, in_app: true }, + ], + }, + }); + }); + it('should parse exceptions with native code frames in Edge 44', () => { const EDGE44_NATIVE_CODE_EXCEPTION = { message: 'test', diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index 46a6c9e5ec72..0849ff761ea4 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -96,7 +96,7 @@ export function constructWebpackConfigFunction( appDirPath = path.join(projectDir, 'src', 'app'); } - const apiRoutesPath = path.join(pagesDirPath, 'api'); + const apiRoutesPath = path.join(pagesDirPath, 'api', '/'); const middlewareJsPath = path.join(pagesDirPath, '..', 'middleware.js'); const middlewareTsPath = path.join(pagesDirPath, '..', 'middleware.ts'); diff --git a/packages/nextjs/test/config/loaders.test.ts b/packages/nextjs/test/config/loaders.test.ts index 9c56f97e5b3b..84fb39ea80da 100644 --- a/packages/nextjs/test/config/loaders.test.ts +++ b/packages/nextjs/test/config/loaders.test.ts @@ -118,6 +118,11 @@ describe('webpack loaders', () => { resourcePath: '/Users/Maisey/projects/squirrelChasingSimulator/src/pages/[...testPage].js', expectedWrappingTargetKind: 'page', }, + // Regression test for https://github.com/getsentry/sentry-javascript/issues/7122 + { + resourcePath: '/Users/Maisey/projects/squirrelChasingSimulator/src/pages/apidoc/[version].tsx', + expectedWrappingTargetKind: 'page', + }, { resourcePath: '/Users/Maisey/projects/squirrelChasingSimulator/src/middleware.js', expectedWrappingTargetKind: 'middleware', diff --git a/packages/node/src/integrations/http.ts b/packages/node/src/integrations/http.ts index d3d0711fb158..99060b8c6f64 100644 --- a/packages/node/src/integrations/http.ts +++ b/packages/node/src/integrations/http.ts @@ -101,12 +101,11 @@ export class Http implements Integration { // and we will no longer have to do this optional merge, we can just pass `this._tracing` directly. const tracingOptions = this._tracing ? { ...clientOptions, ...this._tracing } : undefined; - const wrappedHandlerMaker = _createWrappedRequestMethodFactory(this._breadcrumbs, tracingOptions); - // eslint-disable-next-line @typescript-eslint/no-var-requires const httpModule = require('http'); - fill(httpModule, 'get', wrappedHandlerMaker); - fill(httpModule, 'request', wrappedHandlerMaker); + const wrappedHttpHandlerMaker = _createWrappedRequestMethodFactory(this._breadcrumbs, tracingOptions, httpModule); + fill(httpModule, 'get', wrappedHttpHandlerMaker); + fill(httpModule, 'request', wrappedHttpHandlerMaker); // NOTE: Prior to Node 9, `https` used internals of `http` module, thus we don't patch it. // If we do, we'd get double breadcrumbs and double spans for `https` calls. @@ -114,8 +113,13 @@ export class Http implements Integration { if (NODE_VERSION.major && NODE_VERSION.major > 8) { // eslint-disable-next-line @typescript-eslint/no-var-requires const httpsModule = require('https'); - fill(httpsModule, 'get', wrappedHandlerMaker); - fill(httpsModule, 'request', wrappedHandlerMaker); + const wrappedHttpsHandlerMaker = _createWrappedRequestMethodFactory( + this._breadcrumbs, + tracingOptions, + httpsModule, + ); + fill(httpsModule, 'get', wrappedHttpsHandlerMaker); + fill(httpsModule, 'request', wrappedHttpsHandlerMaker); } } } @@ -137,6 +141,7 @@ type WrappedRequestMethodFactory = (original: OriginalRequestMethod) => WrappedR function _createWrappedRequestMethodFactory( breadcrumbsEnabled: boolean, tracingOptions: TracingOptions | undefined, + httpModule: typeof http | typeof https, ): WrappedRequestMethodFactory { // We're caching results so we don't have to recompute regexp every time we create a request. const createSpanUrlMap = new LRUMap(100); @@ -172,11 +177,8 @@ function _createWrappedRequestMethodFactory( }; return function wrappedRequestMethodFactory(originalRequestMethod: OriginalRequestMethod): WrappedRequestMethod { - return function wrappedMethod(this: typeof http | typeof https, ...args: RequestMethodArgs): http.ClientRequest { - // eslint-disable-next-line @typescript-eslint/no-this-alias - const httpModule = this; - - const requestArgs = normalizeRequestArgs(this, args); + return function wrappedMethod(this: unknown, ...args: RequestMethodArgs): http.ClientRequest { + const requestArgs = normalizeRequestArgs(httpModule, args); const requestOptions = requestArgs[0]; const requestUrl = extractUrl(requestOptions); diff --git a/packages/replay/src/util/shouldFilterRequest.ts b/packages/replay/src/util/shouldFilterRequest.ts index 07a4e94e6a16..7d66cf31d780 100644 --- a/packages/replay/src/util/shouldFilterRequest.ts +++ b/packages/replay/src/util/shouldFilterRequest.ts @@ -3,7 +3,8 @@ import { getCurrentHub } from '@sentry/core'; import type { ReplayContainer } from '../types'; /** - * Check whether a given request URL should be filtered out. + * Check whether a given request URL should be filtered out. This is so we + * don't log Sentry ingest requests. */ export function shouldFilterRequest(replay: ReplayContainer, url: string): boolean { // If we enabled the `traceInternals` experiment, we want to trace everything @@ -11,7 +12,7 @@ export function shouldFilterRequest(replay: ReplayContainer, url: string): boole return false; } - return !_isSentryRequest(url); + return _isSentryRequest(url); } /** diff --git a/packages/replay/test/integration/shouldFilterRequest.test.ts b/packages/replay/test/integration/shouldFilterRequest.test.ts new file mode 100644 index 000000000000..888b30e2c25f --- /dev/null +++ b/packages/replay/test/integration/shouldFilterRequest.test.ts @@ -0,0 +1,20 @@ +import { shouldFilterRequest } from '../../src/util/shouldFilterRequest'; +import { mockSdk } from '../index'; + +describe('Integration | shouldFilterRequest', () => { + beforeEach(() => { + jest.resetModules(); + }); + + it('should not filter requests from non-Sentry ingest URLs', async () => { + const { replay } = await mockSdk(); + + expect(shouldFilterRequest(replay, 'https://example.com/foo')).toBe(false); + }); + + it('should filter requests for Sentry ingest URLs', async () => { + const { replay } = await mockSdk(); + + expect(shouldFilterRequest(replay, 'https://03031aa.ingest.f00.f00/api/129312/')).toBe(true); + }); +}); diff --git a/packages/tracing/src/index.bundle.ts b/packages/tracing/src/index.bundle.ts index 635be146d639..fce29d33758e 100644 --- a/packages/tracing/src/index.bundle.ts +++ b/packages/tracing/src/index.bundle.ts @@ -41,6 +41,7 @@ export { export { BrowserClient } from '@sentry/browser'; export { defaultIntegrations, + defaultStackParser, forceLoad, init, lastEventId,