Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
432495d
feat(replay): Add feedback breadcrumb to replay (#9495)
billyvg Nov 9, 2023
0485d11
feat(feedback): Add `source` to feedback payload (#9494)
billyvg Nov 9, 2023
636f4d9
test(browser-integration): Tweak promises a bit to reduce flakes in r…
billyvg Nov 9, 2023
f013f1e
Merge pull request #9513 from getsentry/master
github-actions[bot] Nov 9, 2023
49b9ec3
fix(tracing): Update prisma span to be `db.prisma` (#9512)
AbhiPrasad Nov 9, 2023
bfa8c2e
changelog: include CVE details for security fixes on 7.77.0
mdtro Nov 9, 2023
530f786
Merge pull request #9515 from getsentry/mdtro/cve-2023-46729-changelog
mdtro Nov 9, 2023
069f981
test(deps): bump @sentry/nextjs from 7.57.0 to 7.80.0 in /packages/ne…
dependabot[bot] Nov 10, 2023
e0211e1
build(deps-dev): bump axios from 1.1.2 to 1.6.0 in /packages/e2e-test…
dependabot[bot] Nov 10, 2023
49e7953
build(deps-dev): bump axios from 1.1.2 to 1.6.0 in /packages/e2e-test…
dependabot[bot] Nov 10, 2023
4187606
build(deps-dev): bump axios from 1.1.2 to 1.6.0 in /packages/e2e-test…
dependabot[bot] Nov 10, 2023
911746b
build(deps-dev): bump axios from 1.1.2 to 1.6.0 in /packages/e2e-test…
dependabot[bot] Nov 10, 2023
ecdd22f
build(deps): bump axios from 1.3.4 to 1.6.0 in /packages/browser-inte…
dependabot[bot] Nov 10, 2023
82e87dc
build(remix): Fix version for remix build on node 14 (#9528)
mydea Nov 10, 2023
1d50eef
fix(nextjs): Fix serverside transaction names on Windows (#9526)
Nov 10, 2023
04e7be9
fix(replay): Add additional safeguards for capturing network bodies (…
mydea Nov 10, 2023
569e5b5
ref(nextjs): Improve wording in case CLI is missing (#9538)
Nov 13, 2023
d80e27b
fix(astro): Adjust Vite plugin config to upload server source maps (#…
Lms24 Nov 13, 2023
27686ba
fix(nextjs): Add tracing extensions in all serverside wrappers (#9537)
Nov 13, 2023
b623a68
fix(node): Fix tRPC middleware typing (#9540)
Nov 14, 2023
4d9e57f
meta(changelog): Update changelog for 7.80.1
mydea Nov 14, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@

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

## 7.80.1

- fix(astro): Adjust Vite plugin config to upload server source maps (#9541)
- fix(nextjs): Add tracing extensions in all serverside wrappers (#9537)
- fix(nextjs): Fix serverside transaction names on Windows (#9526)
- fix(node): Fix tRPC middleware typing (#9540)
- fix(replay): Add additional safeguards for capturing network bodies (#9506)
- fix(tracing): Update prisma span to be `db.prisma` (#9512)

## 7.80.0

- feat(astro): Add distributed tracing via `<meta>` tags (#9483)
Expand Down Expand Up @@ -32,7 +41,7 @@ This was possible by extensive use of tree shaking and a host of small changes t

By using [tree shaking](https://docs.sentry.io/platforms/javascript/configuration/tree-shaking/) it is possible to shave up to 10 additional KB off the bundle.

#### Other Changes
### Other Changes

- feat(astro): Add Sentry middleware (#9445)
- feat(feedback): Add "outline focus" and "foreground hover" vars (#9462)
Expand All @@ -52,13 +61,18 @@ By using [tree shaking](https://docs.sentry.io/platforms/javascript/configuratio

## 7.77.0

### Security Fixes

- fix(nextjs): Match only numbers as orgid in tunnelRoute (#9416) (CVE-2023-46729)
- fix(nextjs): Strictly validate tunnel target parameters (#9415) (CVE-2023-46729)

### Other Changes

- feat: Move LinkedErrors integration to @sentry/core (#9404)
- feat(remix): Update sentry-cli version to ^2.21.2 (#9401)
- feat(replay): Allow to treeshake & configure compression worker URL (#9409)
- fix(angular-ivy): Adjust package entry points to support Angular 17 with SSR config (#9412)
- fix(feedback): Fixing feedback import (#9403)
- fix(nextjs): Match only numbers as orgid in tunnelRoute (#9416)
- fix(nextjs): Strictly validate tunnel target parameters (#9415)
- fix(utils): Avoid keeping a reference of last used event (#9387)

## 7.76.0
Expand Down
23 changes: 21 additions & 2 deletions packages/astro/src/integration/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable no-console */
import { sentryVitePlugin } from '@sentry/vite-plugin';
import type { AstroIntegration } from 'astro';
import type { AstroConfig, AstroIntegration } from 'astro';
import * as fs from 'fs';
import * as path from 'path';

Expand All @@ -13,7 +13,8 @@ export const sentryAstro = (options: SentryOptions = {}): AstroIntegration => {
return {
name: PKG_NAME,
hooks: {
'astro:config:setup': async ({ updateConfig, injectScript }) => {
// eslint-disable-next-line complexity
'astro:config:setup': async ({ updateConfig, injectScript, config }) => {
// The third param here enables loading of all env vars, regardless of prefix
// see: https://main.vitejs.dev/config/#using-environment-variables-in-config

Expand All @@ -40,6 +41,10 @@ export const sentryAstro = (options: SentryOptions = {}): AstroIntegration => {
project: uploadOptions.project ?? env.SENTRY_PROJECT,
authToken: uploadOptions.authToken ?? env.SENTRY_AUTH_TOKEN,
telemetry: uploadOptions.telemetry ?? true,
sourcemaps: {
assets: [getSourcemapsAssetsGlob(config)],
},
debug: options.debug ?? false,
}),
],
},
Expand Down Expand Up @@ -79,3 +84,17 @@ function findDefaultSdkInitFile(type: 'server' | 'client'): string | undefined {
.map(ext => path.resolve(path.join(process.cwd(), `sentry.${type}.config.${ext}`)))
.find(filename => fs.existsSync(filename));
}

function getSourcemapsAssetsGlob(config: AstroConfig): string {
// paths are stored as "file://" URLs
const outDirPathname = config.outDir && path.resolve(config.outDir.pathname);
const rootDirName = path.resolve((config.root && config.root.pathname) || process.cwd());

if (outDirPathname) {
const relativePath = path.relative(rootDirName, outDirPathname);
return `${relativePath}/**/*`;
}

// fallback to default output dir
return 'dist/**/*';
}
48 changes: 35 additions & 13 deletions packages/astro/test/integration/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ process.env = {
SENTRY_AUTH_TOKEN: 'my-token',
};

const updateConfig = vi.fn();
const injectScript = vi.fn();
const config = {
root: new URL('file://path/to/project'),
outDir: new URL('file://path/to/project/out'),
};

describe('sentryAstro integration', () => {
afterEach(() => {
vi.clearAllMocks();
Expand All @@ -28,12 +35,10 @@ describe('sentryAstro integration', () => {
const integration = sentryAstro({
sourceMapsUploadOptions: { enabled: true, org: 'my-org', project: 'my-project', telemetry: false },
});
const updateConfig = vi.fn();
const injectScript = vi.fn();

expect(integration.hooks['astro:config:setup']).toBeDefined();
// @ts-expect-error - the hook exists and we only need to pass what we actually use
await integration.hooks['astro:config:setup']({ updateConfig, injectScript });
await integration.hooks['astro:config:setup']({ updateConfig, injectScript, config });

expect(updateConfig).toHaveBeenCalledTimes(1);
expect(updateConfig).toHaveBeenCalledWith({
Expand All @@ -51,32 +56,52 @@ describe('sentryAstro integration', () => {
org: 'my-org',
project: 'my-project',
telemetry: false,
debug: false,
sourcemaps: {
assets: ['out/**/*'],
},
});
});

it('falls back to default output dir, if out and root dir are not available', async () => {
const integration = sentryAstro({
sourceMapsUploadOptions: { enabled: true, org: 'my-org', project: 'my-project', telemetry: false },
});
// @ts-expect-error - the hook exists and we only need to pass what we actually use
await integration.hooks['astro:config:setup']({ updateConfig, injectScript, config: {} });

expect(sentryVitePluginSpy).toHaveBeenCalledTimes(1);
expect(sentryVitePluginSpy).toHaveBeenCalledWith({
authToken: 'my-token',
org: 'my-org',
project: 'my-project',
telemetry: false,
debug: false,
sourcemaps: {
assets: ['dist/**/*'],
},
});
});

it("doesn't enable source maps if `sourceMapsUploadOptions.enabled` is `false`", async () => {
const integration = sentryAstro({
sourceMapsUploadOptions: { enabled: false },
});
const updateConfig = vi.fn();
const injectScript = vi.fn();

expect(integration.hooks['astro:config:setup']).toBeDefined();
// @ts-expect-error - the hook exists and we only need to pass what we actually use
await integration.hooks['astro:config:setup']({ updateConfig, injectScript });
await integration.hooks['astro:config:setup']({ updateConfig, injectScript, config });

expect(updateConfig).toHaveBeenCalledTimes(0);
expect(sentryVitePluginSpy).toHaveBeenCalledTimes(0);
});

it('injects client and server init scripts', async () => {
const integration = sentryAstro({});
const updateConfig = vi.fn();
const injectScript = vi.fn();

expect(integration.hooks['astro:config:setup']).toBeDefined();
// @ts-expect-error - the hook exists and we only need to pass what we actually use
await integration.hooks['astro:config:setup']({ updateConfig, injectScript });
await integration.hooks['astro:config:setup']({ updateConfig, injectScript, config });

expect(injectScript).toHaveBeenCalledTimes(2);
expect(injectScript).toHaveBeenCalledWith('page', expect.stringContaining('Sentry.init'));
Expand All @@ -89,12 +114,9 @@ describe('sentryAstro integration', () => {
serverInitPath: 'my-server-init-path.js',
});

const updateConfig = vi.fn();
const injectScript = vi.fn();

expect(integration.hooks['astro:config:setup']).toBeDefined();
// @ts-expect-error - the hook exists and we only need to pass what we actually use
await integration.hooks['astro:config:setup']({ updateConfig, injectScript });
await integration.hooks['astro:config:setup']({ updateConfig, injectScript, config });

expect(injectScript).toHaveBeenCalledTimes(2);
expect(injectScript).toHaveBeenCalledWith('page', expect.stringContaining('my-client-init-path.js'));
Expand Down
2 changes: 1 addition & 1 deletion packages/browser-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"dependencies": {
"@babel/preset-typescript": "^7.16.7",
"@playwright/test": "^1.31.1",
"axios": "1.3.4",
"axios": "1.6.0",
"babel-loader": "^8.2.2",
"html-webpack-plugin": "^5.5.0",
"pako": "^2.1.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ sentryTest('captures Breadcrumb for clicks & debounces them for a second', async
await page.waitForTimeout(1000);
await page.click('#button2');

await page.evaluate('Sentry.captureException("test exception")');

const eventData = await promise;
const [eventData] = await Promise.all([promise, page.evaluate('Sentry.captureException("test exception")')]);

expect(eventData.exception?.values).toHaveLength(1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ sentryTest('captures request headers', async ({ getLocalTestPath, page, browserN
/* eslint-enable */
});

const request = await requestPromise;
const [request, replayReq1] = await Promise.all([requestPromise, replayRequestPromise1]);
const eventData = envelopeRequestParser(request);

expect(eventData.exception?.values).toHaveLength(1);
Expand All @@ -71,7 +71,6 @@ sentryTest('captures request headers', async ({ getLocalTestPath, page, browserN
},
});

const replayReq1 = await replayRequestPromise1;
const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1);
expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([
{
Expand Down Expand Up @@ -142,7 +141,8 @@ sentryTest(
/* eslint-enable */
});

const request = await requestPromise;
const [request, replayReq1] = await Promise.all([requestPromise, replayRequestPromise1]);

const eventData = envelopeRequestParser(request);

expect(eventData.exception?.values).toHaveLength(1);
Expand All @@ -159,7 +159,6 @@ sentryTest(
},
});

const replayReq1 = await replayRequestPromise1;
const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1);
expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,24 @@ sentryTest(
const url = await getLocalTestPath({ testDir: __dirname });

await page.goto(url);
const fullSnapshot = getFullRecordingSnapshots(await reqPromise0);

const text = 'test';

const [req0] = await Promise.all([reqPromise0, page.locator('#input').fill(text)]);
await forceFlushReplay();

const fullSnapshot = getFullRecordingSnapshots(req0);
const stringifiedSnapshot = JSON.stringify(fullSnapshot);
expect(stringifiedSnapshot.includes('Submit form')).toBe(false);
expect(stringifiedSnapshot.includes('Unmasked button')).toBe(true);

const text = 'test';

await page.locator('#input').fill(text);
const [req1] = await Promise.all([reqPromise1, page.locator('#input-unmasked').fill(text)]);
await forceFlushReplay();

const snapshots = getIncrementalRecordingSnapshots(await reqPromise1).filter(isInputMutation);
const snapshots = getIncrementalRecordingSnapshots(req1).filter(isInputMutation);
const lastSnapshot = snapshots[snapshots.length - 1];
expect(lastSnapshot.data.text).toBe('*'.repeat(text.length));

await page.locator('#input-unmasked').fill(text);
await forceFlushReplay();
const snapshots2 = getIncrementalRecordingSnapshots(await reqPromise2).filter(isInputMutation);
const lastSnapshot2 = snapshots2[snapshots2.length - 1];
expect(lastSnapshot2.data.text).toBe(text);
Expand Down Expand Up @@ -120,18 +122,18 @@ sentryTest(

await page.goto(url);

await reqPromise0;

const text = 'test';

await page.locator('#textarea').fill(text);
await Promise.all([reqPromise0, page.locator('#textarea').fill(text)]);
await forceFlushReplay();

const [req1] = await Promise.all([reqPromise1, page.locator('#textarea-unmasked').fill(text)]);
await forceFlushReplay();
const snapshots = getIncrementalRecordingSnapshots(await reqPromise1).filter(isInputMutation);

const snapshots = getIncrementalRecordingSnapshots(req1).filter(isInputMutation);
const lastSnapshot = snapshots[snapshots.length - 1];
expect(lastSnapshot.data.text).toBe('*'.repeat(text.length));

await page.locator('#textarea-unmasked').fill(text);
await forceFlushReplay();
const snapshots2 = getIncrementalRecordingSnapshots(await reqPromise2).filter(isInputMutation);
const lastSnapshot2 = snapshots2[snapshots2.length - 1];
expect(lastSnapshot2.data.text).toBe(text);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
},
"devDependencies": {
"@playwright/test": "1.26.1",
"axios": "1.1.2",
"axios": "1.6.0",
"serve": "14.0.1"
},
"volta": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
},
"devDependencies": {
"@playwright/test": "1.26.1",
"axios": "1.1.2",
"axios": "1.6.0",
"serve": "14.0.1"
},
"volta": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
},
"devDependencies": {
"@playwright/test": "1.26.1",
"axios": "1.1.2",
"axios": "1.6.0",
"serve": "14.0.1"
},
"volta": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
},
"devDependencies": {
"@playwright/test": "1.26.1",
"axios": "1.1.2",
"axios": "1.6.0",
"serve": "14.0.1"
},
"volta": {
Expand Down
4 changes: 3 additions & 1 deletion packages/feedback/src/sendFeedback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ interface SendFeedbackParams {
name?: string;
email?: string;
url?: string;
source?: string;
}

/**
* Public API to send a Feedback item to Sentry
*/
export function sendFeedback(
{ name, email, message, url = getLocationHref() }: SendFeedbackParams,
{ name, email, message, source = 'api', url = getLocationHref() }: SendFeedbackParams,
{ includeReplay = true }: SendFeedbackOptions = {},
): ReturnType<typeof sendFeedbackRequest> {
const client = getCurrentHub().getClient<BrowserClient>();
Expand All @@ -37,6 +38,7 @@ export function sendFeedback(
message,
url,
replay_id: replayId,
source,
},
});
}
1 change: 1 addition & 0 deletions packages/feedback/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface SendFeedbackData {
email?: string;
replay_id?: string;
name?: string;
source?: string;
};
}

Expand Down
2 changes: 1 addition & 1 deletion packages/feedback/src/util/handleFeedbackSubmit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export async function handleFeedbackSubmit(
dialog.hideError();

try {
const resp = await sendFeedback(feedback, options);
const resp = await sendFeedback({ ...feedback, source: 'widget' }, options);

// Success!
return resp;
Expand Down
3 changes: 2 additions & 1 deletion packages/feedback/src/util/sendFeedbackRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { prepareFeedbackEvent } from './prepareFeedbackEvent';
* Send feedback using transport
*/
export async function sendFeedbackRequest({
feedback: { message, email, name, replay_id, url },
feedback: { message, email, name, source, replay_id, url },
}: SendFeedbackData): Promise<void | TransportMakeRequestResponse> {
const hub = getCurrentHub();
const client = hub.getClient();
Expand All @@ -28,6 +28,7 @@ export async function sendFeedbackRequest({
message,
replay_id,
url,
source,
},
},
type: 'feedback',
Expand Down
Loading