Skip to content

Commit fb1e785

Browse files
authored
Merge pull request getsentry#13170 from getsentry/prepare-release/8.23.0
meta: Update CHANGELOG for 8.23.0
2 parents 93189df + c1aefca commit fb1e785

File tree

223 files changed

+2788
-2841
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

223 files changed

+2788
-2841
lines changed

.github/workflows/build.yml

Lines changed: 31 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,11 @@ jobs:
434434
timeout-minutes: 10
435435
runs-on: ubuntu-20.04
436436
steps:
437+
- name: Check out base commit (${{ github.event.pull_request.base.sha }})
438+
uses: actions/checkout@v4
439+
with:
440+
ref: ${{ github.event.pull_request.base.sha }}
441+
437442
- name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }})
438443
uses: actions/checkout@v4
439444
with:
@@ -446,8 +451,15 @@ jobs:
446451
uses: ./.github/actions/restore-cache
447452
env:
448453
DEPENDENCY_CACHE_KEY: ${{ needs.job_build.outputs.dependency_cache_key }}
449-
- name: Run tests
450-
run: yarn test-ci-browser
454+
455+
- name: Run affected tests
456+
run: yarn test:pr:browser --base=${{ github.event.pull_request.base.sha }}
457+
if: github.event_name == 'pull_request'
458+
459+
- name: Run all tests
460+
run: yarn test:ci:browser
461+
if: github.event_name != 'pull_request'
462+
451463
- name: Compute test coverage
452464
uses: codecov/codecov-action@v4
453465
with:
@@ -478,7 +490,7 @@ jobs:
478490
DEPENDENCY_CACHE_KEY: ${{ needs.job_build.outputs.dependency_cache_key }}
479491
- name: Run tests
480492
run: |
481-
yarn test-ci-bun
493+
yarn test:ci:bun
482494
483495
job_deno_unit_tests:
484496
name: Deno Unit Tests
@@ -521,6 +533,10 @@ jobs:
521533
matrix:
522534
node: [14, 16, 18, 20, 22]
523535
steps:
536+
- name: Check out base commit (${{ github.event.pull_request.base.sha }})
537+
uses: actions/checkout@v4
538+
with:
539+
ref: ${{ github.event.pull_request.base.sha }}
524540
- name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }})
525541
uses: actions/checkout@v4
526542
with:
@@ -533,10 +549,19 @@ jobs:
533549
uses: ./.github/actions/restore-cache
534550
env:
535551
DEPENDENCY_CACHE_KEY: ${{ needs.job_build.outputs.dependency_cache_key }}
536-
- name: Run tests
552+
553+
- name: Run affected tests
554+
run: yarn test:pr:node --base=${{ github.event.pull_request.base.sha }}
555+
if: github.event_name == 'pull_request'
537556
env:
538557
NODE_VERSION: ${{ matrix.node }}
539-
run: yarn test-ci-node
558+
559+
- name: Run all tests
560+
run: yarn test:ci:node
561+
if: github.event_name != 'pull_request'
562+
env:
563+
NODE_VERSION: ${{ matrix.node }}
564+
540565
- name: Compute test coverage
541566
uses: codecov/codecov-action@v4
542567
with:
@@ -570,56 +595,6 @@ jobs:
570595
- name: Unit Test
571596
run: yarn lerna run test --scope @sentry/profiling-node
572597

573-
job_nextjs_integration_test:
574-
name: Nextjs (Node ${{ matrix.node }}) Tests
575-
needs: [job_get_metadata, job_build]
576-
if: needs.job_get_metadata.outputs.changed_nextjs == 'true' || github.event_name != 'pull_request'
577-
timeout-minutes: 25
578-
runs-on: ubuntu-20.04
579-
strategy:
580-
fail-fast: false
581-
matrix:
582-
node: [14, 16, 18, 20, 22]
583-
steps:
584-
- name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }})
585-
uses: actions/checkout@v4
586-
with:
587-
ref: ${{ env.HEAD_COMMIT }}
588-
- name: Set up Node
589-
uses: actions/setup-node@v4
590-
with:
591-
node-version: ${{ matrix.node }}
592-
- name: Restore caches
593-
uses: ./.github/actions/restore-cache
594-
env:
595-
DEPENDENCY_CACHE_KEY: ${{ needs.job_build.outputs.dependency_cache_key }}
596-
- name: Get npm cache directory
597-
id: npm-cache-dir
598-
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
599-
- name: Get Playwright version
600-
id: playwright-version
601-
run: echo "version=$(node -p "require('@playwright/test/package.json').version")" >> $GITHUB_OUTPUT
602-
- uses: actions/cache@v4
603-
name: Check if Playwright browser is cached
604-
id: playwright-cache
605-
with:
606-
path: ${{ steps.npm-cache-dir.outputs.dir }}
607-
key: ${{ runner.os }}-Playwright-${{steps.playwright-version.outputs.version}}
608-
- name: Install Playwright browser if not cached
609-
if: steps.playwright-cache.outputs.cache-hit != 'true'
610-
run: npx playwright install --with-deps
611-
env:
612-
PLAYWRIGHT_BROWSERS_PATH: ${{steps.npm-cache-dir.outputs.dir}}
613-
- name: Install OS dependencies of Playwright if cache hit
614-
if: steps.playwright-cache.outputs.cache-hit == 'true'
615-
run: npx playwright install-deps
616-
- name: Run tests
617-
env:
618-
NODE_VERSION: ${{ matrix.node }}
619-
run: |
620-
cd packages/nextjs
621-
yarn test:integration
622-
623598
job_browser_playwright_tests:
624599
name: Playwright (${{ matrix.bundle }}${{ matrix.shard && format(' {0}/{1}', matrix.shard, matrix.shards) || ''}}) Tests
625600
needs: [job_get_metadata, job_build]
@@ -994,6 +969,7 @@ jobs:
994969
'ember-classic',
995970
'ember-embroider',
996971
'nextjs-app-dir',
972+
'nextjs-13',
997973
'nextjs-14',
998974
'nextjs-15',
999975
'react-17',
@@ -1302,7 +1278,6 @@ jobs:
13021278
job_deno_unit_tests,
13031279
job_node_unit_tests,
13041280
job_profiling_node_unit_tests,
1305-
job_nextjs_integration_test,
13061281
job_node_integration_tests,
13071282
job_browser_playwright_tests,
13081283
job_browser_loader_tests,

.github/workflows/canary.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ jobs:
7878
- test-application: 'nextjs-app-dir'
7979
build-command: 'test:build-latest'
8080
label: 'nextjs-app-dir (latest)'
81+
- test-application: 'nextjs-13'
82+
build-command: 'test:build-canary'
83+
label: 'nextjs-13 (canary)'
84+
- test-application: 'nextjs-13'
85+
build-command: 'test:build-latest'
86+
label: 'nextjs-13 (latest)'
8187
- test-application: 'nextjs-14'
8288
build-command: 'test:build-canary'
8389
label: 'nextjs-14 (canary)'

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@
99

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

12+
## 8.23.0
13+
14+
- feat(cloudflare): Add Cloudflare D1 instrumentation (#13142)
15+
- feat(nestjs): Automatic instrumentation of nestjs interceptors before route execution (#13153)
16+
- feat(nestjs): Automatic instrumentation of nestjs pipes (#13137)
17+
- feat(nuxt): Filter out Nuxt build assets (#13148)
18+
- feat(profiling): attach sdk info to chunks (#13145)
19+
- fix(browser): Avoid showing browser extension error message in non-`window` global scopes (#13156)
20+
- fix(nestjs): Inline Observable type to resolve missing 'rxjs' dependency (#13166)
21+
1222
## 8.22.0
1323

1424
### Important Changes

dev-packages/e2e-tests/test-applications/nestjs-basic/src/app.controller.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { Controller, Get, Param, UseGuards } from '@nestjs/common';
1+
import { Controller, Get, Param, ParseIntPipe, UseGuards, UseInterceptors } from '@nestjs/common';
22
import { AppService } from './app.service';
33
import { ExampleGuard } from './example.guard';
4+
import { ExampleInterceptor } from './example.interceptor';
45

56
@Controller()
67
export class AppController {
@@ -13,7 +14,7 @@ export class AppController {
1314

1415
@Get('test-middleware-instrumentation')
1516
testMiddlewareInstrumentation() {
16-
return this.appService.testMiddleware();
17+
return this.appService.testSpan();
1718
}
1819

1920
@Get('test-guard-instrumentation')
@@ -22,6 +23,17 @@ export class AppController {
2223
return {};
2324
}
2425

26+
@Get('test-interceptor-instrumentation')
27+
@UseInterceptors(ExampleInterceptor)
28+
testInterceptorInstrumentation() {
29+
return this.appService.testSpan();
30+
}
31+
32+
@Get('test-pipe-instrumentation/:id')
33+
testPipeInstrumentation(@Param('id', ParseIntPipe) id: number) {
34+
return { value: id };
35+
}
36+
2537
@Get('test-exception/:id')
2638
async testException(@Param('id') id: string) {
2739
return this.appService.testException(id);

dev-packages/e2e-tests/test-applications/nestjs-basic/src/app.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class AppService {
2121
});
2222
}
2323

24-
testMiddleware() {
24+
testSpan() {
2525
// span that should not be a child span of the middleware span
2626
Sentry.startSpan({ name: 'test-controller-span' }, () => {});
2727
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
2+
import * as Sentry from '@sentry/nestjs';
3+
4+
@Injectable()
5+
export class ExampleInterceptor implements NestInterceptor {
6+
intercept(context: ExecutionContext, next: CallHandler) {
7+
Sentry.startSpan({ name: 'test-interceptor-span' }, () => {});
8+
return next.handle().pipe();
9+
}
10+
}

dev-packages/e2e-tests/test-applications/nestjs-basic/tests/transactions.test.ts

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,3 +266,155 @@ test('API route transaction includes nest guard span and span started in guard i
266266
// 'ExampleGuard' is the parent of 'test-guard-span'
267267
expect(testGuardSpan.parent_span_id).toBe(exampleGuardSpanId);
268268
});
269+
270+
test('API route transaction includes nest pipe span for valid request', async ({ baseURL }) => {
271+
const transactionEventPromise = waitForTransaction('nestjs', transactionEvent => {
272+
return (
273+
transactionEvent?.contexts?.trace?.op === 'http.server' &&
274+
transactionEvent?.transaction === 'GET /test-pipe-instrumentation/:id'
275+
);
276+
});
277+
278+
const response = await fetch(`${baseURL}/test-pipe-instrumentation/123`);
279+
expect(response.status).toBe(200);
280+
281+
const transactionEvent = await transactionEventPromise;
282+
283+
expect(transactionEvent).toEqual(
284+
expect.objectContaining({
285+
spans: expect.arrayContaining([
286+
{
287+
span_id: expect.any(String),
288+
trace_id: expect.any(String),
289+
data: {
290+
'sentry.op': 'middleware.nestjs',
291+
'sentry.origin': 'auto.middleware.nestjs',
292+
},
293+
description: 'ParseIntPipe',
294+
parent_span_id: expect.any(String),
295+
start_timestamp: expect.any(Number),
296+
timestamp: expect.any(Number),
297+
status: 'ok',
298+
op: 'middleware.nestjs',
299+
origin: 'auto.middleware.nestjs',
300+
},
301+
]),
302+
}),
303+
);
304+
});
305+
306+
test('API route transaction includes nest pipe span for invalid request', async ({ baseURL }) => {
307+
const transactionEventPromise = waitForTransaction('nestjs', transactionEvent => {
308+
return (
309+
transactionEvent?.contexts?.trace?.op === 'http.server' &&
310+
transactionEvent?.transaction === 'GET /test-pipe-instrumentation/:id'
311+
);
312+
});
313+
314+
const response = await fetch(`${baseURL}/test-pipe-instrumentation/abc`);
315+
expect(response.status).toBe(400);
316+
317+
const transactionEvent = await transactionEventPromise;
318+
319+
expect(transactionEvent).toEqual(
320+
expect.objectContaining({
321+
spans: expect.arrayContaining([
322+
{
323+
span_id: expect.any(String),
324+
trace_id: expect.any(String),
325+
data: {
326+
'sentry.op': 'middleware.nestjs',
327+
'sentry.origin': 'auto.middleware.nestjs',
328+
},
329+
description: 'ParseIntPipe',
330+
parent_span_id: expect.any(String),
331+
start_timestamp: expect.any(Number),
332+
timestamp: expect.any(Number),
333+
status: 'unknown_error',
334+
op: 'middleware.nestjs',
335+
origin: 'auto.middleware.nestjs',
336+
},
337+
]),
338+
}),
339+
);
340+
});
341+
342+
test('API route transaction includes nest interceptor span. Spans created in and after interceptor are nested correctly', async ({
343+
baseURL,
344+
}) => {
345+
const pageloadTransactionEventPromise = waitForTransaction('nestjs', transactionEvent => {
346+
return (
347+
transactionEvent?.contexts?.trace?.op === 'http.server' &&
348+
transactionEvent?.transaction === 'GET /test-interceptor-instrumentation'
349+
);
350+
});
351+
352+
const response = await fetch(`${baseURL}/test-interceptor-instrumentation`);
353+
expect(response.status).toBe(200);
354+
355+
const transactionEvent = await pageloadTransactionEventPromise;
356+
357+
expect(transactionEvent).toEqual(
358+
expect.objectContaining({
359+
spans: expect.arrayContaining([
360+
{
361+
span_id: expect.any(String),
362+
trace_id: expect.any(String),
363+
data: {
364+
'sentry.op': 'middleware.nestjs',
365+
'sentry.origin': 'auto.middleware.nestjs',
366+
},
367+
description: 'ExampleInterceptor',
368+
parent_span_id: expect.any(String),
369+
start_timestamp: expect.any(Number),
370+
timestamp: expect.any(Number),
371+
status: 'ok',
372+
op: 'middleware.nestjs',
373+
origin: 'auto.middleware.nestjs',
374+
},
375+
]),
376+
}),
377+
);
378+
379+
const exampleInterceptorSpan = transactionEvent.spans.find(span => span.description === 'ExampleInterceptor');
380+
const exampleInterceptorSpanId = exampleInterceptorSpan?.span_id;
381+
382+
expect(transactionEvent).toEqual(
383+
expect.objectContaining({
384+
spans: expect.arrayContaining([
385+
{
386+
span_id: expect.any(String),
387+
trace_id: expect.any(String),
388+
data: expect.any(Object),
389+
description: 'test-controller-span',
390+
parent_span_id: expect.any(String),
391+
start_timestamp: expect.any(Number),
392+
timestamp: expect.any(Number),
393+
status: 'ok',
394+
origin: 'manual',
395+
},
396+
{
397+
span_id: expect.any(String),
398+
trace_id: expect.any(String),
399+
data: expect.any(Object),
400+
description: 'test-interceptor-span',
401+
parent_span_id: expect.any(String),
402+
start_timestamp: expect.any(Number),
403+
timestamp: expect.any(Number),
404+
status: 'ok',
405+
origin: 'manual',
406+
},
407+
]),
408+
}),
409+
);
410+
411+
// verify correct span parent-child relationships
412+
const testInterceptorSpan = transactionEvent.spans.find(span => span.description === 'test-interceptor-span');
413+
const testControllerSpan = transactionEvent.spans.find(span => span.description === 'test-controller-span');
414+
415+
// 'ExampleInterceptor' is the parent of 'test-interceptor-span'
416+
expect(testInterceptorSpan.parent_span_id).toBe(exampleInterceptorSpanId);
417+
418+
// 'ExampleInterceptor' is NOT the parent of 'test-controller-span'
419+
expect(testControllerSpan.parent_span_id).not.toBe(exampleInterceptorSpanId);
420+
});

0 commit comments

Comments
 (0)