Skip to content

meta(changelog): Update changelog for 7.43.0 #7437

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Mar 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
94266d7
Merge pull request #7392 from getsentry/master
github-actions[bot] Mar 9, 2023
cc26081
feat(sveltekit): Inject `Sentry.init` calls into server and client bu…
Lms24 Mar 9, 2023
8b0d536
fix(core): Avoid using `Array.findIndex()` as it is ES5 incompatible …
mydea Mar 10, 2023
2a22f24
feat(sveltekit): Add SvelteKit client and server `init` functions (#7…
Lms24 Mar 10, 2023
bd45dfc
feat(sveltekit): Introduce client-side `handleError` wrapper (#7406)
AbhiPrasad Mar 10, 2023
ed1347e
feat(sveltekit): Add server-side `handleError` wrapper (#7411)
AbhiPrasad Mar 10, 2023
63ef40e
feat(types): add profilesSampler option to node client type (#7385)
JonasBa Mar 10, 2023
ebcbdda
fix(nextjs): Don't crash build when auth token is missing
Mar 13, 2023
c86e63c
Don't show full warning on vercel
Mar 13, 2023
9c2971b
chore(vscode): Add eslint working directories (#7428)
AbhiPrasad Mar 13, 2023
045d11b
make error
Mar 13, 2023
fe1231a
fix(node): Revert to dynamic `require` call to fix monkey patching (#…
Lms24 Mar 13, 2023
6ae68ca
Merge pull request #7427 from getsentry/lforst-dont-crash-on-missing-…
Mar 13, 2023
161b8f0
fix(types): Fix node types & add E2E test (#7429)
mydea Mar 13, 2023
3376a15
ref(utils): test for webpack error before running replace (#7412)
JonasBa Mar 13, 2023
5e27e8f
fix(nextjs): Add better error messages for missing params during next…
Mar 13, 2023
e358e16
feat(nextjs): Run source map upload in Vercel develop and preview env…
Mar 13, 2023
2c25610
meta(changelog): Update changelog for 7.43.0
AbhiPrasad Mar 13, 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
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,10 @@
"yaml.schemas": {
"https://json.schemastore.org/github-workflow.json": ".github/workflows/**.yml"
},
"eslint.packageManager": "yarn",
"eslint.workingDirectories": [
{
"mode": "auto"
}
]
}
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.43.0

- feat(nextjs): Run source map upload in Vercel develop and preview environments (#7436)
- feat(types): Add `profilesSampler` option to node client type (#7385)
- fix(core): Avoid using `Array.findIndex()` as it is ES5 incompatible (#7400)
- fix(nextjs): Add better error messages for missing params during next build (#7434)
- fix(nextjs): Don't crash build when auth token is missing
- fix(node): Revert to dynamic `require` call to fix monkey patching (#7430)
- fix(types): Fix node types & add E2E test (#7429)


## 7.42.0

- feat(core): Add lifecycle hooks (#7370)
Expand Down
4 changes: 2 additions & 2 deletions packages/browser/src/integrations/breadcrumbs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ function _consoleBreadcrumb(handlerData: HandlerData & { args: unknown[]; level:
/**
* Creates breadcrumbs from XHR API calls
*/
function _xhrBreadcrumb(handlerData: HandlerData & { xhr: SentryWrappedXMLHttpRequest }): void {
function _xhrBreadcrumb(handlerData: HandlerData & { xhr: XMLHttpRequest & SentryWrappedXMLHttpRequest }): void {
if (handlerData.endTimestamp) {
// We only capture complete, non-sentry requests
if (handlerData.xhr.__sentry_own_request__) {
Expand Down Expand Up @@ -248,7 +248,7 @@ function _xhrBreadcrumb(handlerData: HandlerData & { xhr: SentryWrappedXMLHttpRe
/**
* Creates breadcrumbs from fetch API calls
*/
function _fetchBreadcrumb(handlerData: HandlerData & HandlerDataFetch): void {
function _fetchBreadcrumb(handlerData: HandlerData & HandlerDataFetch & { response?: Response }): void {
// We only capture complete fetch requests
if (!handlerData.endTimestamp) {
return;
Expand Down
13 changes: 12 additions & 1 deletion packages/core/src/integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export function getIntegrationsToSetup(options: Options): Integration[] {
// `beforeSendTransaction`. It therefore has to run after all other integrations, so that the changes of all event
// processors will be reflected in the printed values. For lack of a more elegant way to guarantee that, we therefore
// locate it and, assuming it exists, pop it out of its current spot and shove it onto the end of the array.
const debugIndex = finalIntegrations.findIndex(integration => integration.name === 'Debug');
const debugIndex = findIndex(finalIntegrations, integration => integration.name === 'Debug');
if (debugIndex !== -1) {
const [debugInstance] = finalIntegrations.splice(debugIndex, 1);
finalIntegrations.push(debugInstance);
Expand Down Expand Up @@ -107,3 +107,14 @@ export function setupIntegration(integration: Integration, integrationIndex: Int
__DEBUG_BUILD__ && logger.log(`Integration installed: ${integration.name}`);
}
}

// Polyfill for Array.findIndex(), which is not supported in ES5
function findIndex<T>(arr: T[], callback: (item: T) => boolean): number {
for (let i = 0; i < arr.length; i++) {
if (callback(arr[i]) === true) {
return i;
}
}

return -1;
}
4 changes: 4 additions & 0 deletions packages/e2e-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ current state.

Prerequisites: Docker

- Copy `.env.example` to `.env`
- Fill in auth information in `.env` for an example Sentry project
- The `E2E_TEST_AUTH_TOKEN` must have all the default permissions

```bash
yarn test:e2e
```
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist
2 changes: 2 additions & 0 deletions packages/e2e-tests/test-applications/node-express-app/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@sentry:registry=http://localhost:4873
@sentry-internal:registry=http://localhost:4873
23 changes: 23 additions & 0 deletions packages/e2e-tests/test-applications/node-express-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "node-express-app",
"version": "1.0.0",
"private": true,
"scripts": {
"build": "yarn tsc",
"start": "node dist/app.js",
"test": "yarn playwright test"
},
"dependencies": {
"@sentry/integrations": "*",
"@sentry/node": "*",
"@sentry/tracing": "*",
"@sentry/types": "*",
"express": "4.18.2",
"@types/express": "4.17.17",
"@types/node": "18.15.1",
"typescript": "4.9.5"
},
"devDependencies": {
"@playwright/test": "^1.27.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import type { PlaywrightTestConfig } from '@playwright/test';
import { devices } from '@playwright/test';

/**
* See https://playwright.dev/docs/test-configuration.
*/
const config: PlaywrightTestConfig = {
testDir: './tests',
/* Maximum time one test can run for. */
timeout: 60 * 1000,
expect: {
/**
* Maximum time expect() should wait for the condition to be met.
* For example in `await expect(locator).toHaveText();`
*/
timeout: 5000,
},
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: 0,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'list',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
actionTimeout: 0,
/* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://localhost:3000',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},

/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
},
},
// For now we only test Chrome!
// {
// name: 'firefox',
// use: {
// ...devices['Desktop Firefox'],
// },
// },
// {
// name: 'webkit',
// use: {
// ...devices['Desktop Safari'],
// },
// },
],

/* Run your local dev server before starting the tests */
webServer: {
command: 'yarn start',
port: 3000,
},
};

export default config;
73 changes: 73 additions & 0 deletions packages/e2e-tests/test-applications/node-express-app/src/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import * as Sentry from '@sentry/node';
import '@sentry/tracing';
import * as Integrations from '@sentry/integrations';
import express from 'express';

declare global {
namespace globalThis {
var transactionIds: string[];
}
}

Sentry.init({
dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN,
integrations: [new Integrations.HttpClient()],
debug: true,
tracesSampleRate: 1,
});

const app = express();
const port = 3000;

app.use(Sentry.Handlers.requestHandler());
app.use(Sentry.Handlers.tracingHandler());

app.get('/test-success', function (req, res) {
res.send({ version: 'v1' });
});

app.get('/test-param/:param', function (req, res) {
res.send({ paramWas: req.params.param });
});

app.get('/test-transaction', async function (req, res) {
const transaction = Sentry.startTransaction({ name: 'test-transaction', op: 'e2e-test' });
Sentry.getCurrentHub().configureScope(scope => scope.setSpan(transaction));

const span = transaction.startChild();

span.finish();
transaction.finish();

await Sentry.flush();

res.send({
transactionIds: global.transactionIds || [],
});
});

app.get('/test-error', async function (req, res) {
const exceptionId = Sentry.captureException(new Error('This is an error'));

await Sentry.flush(2000);

res.send({ exceptionId });
});

app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});

Sentry.addGlobalEventProcessor(event => {
global.transactionIds = global.transactionIds || [];

if (event.type === 'transaction') {
const eventId = event.event_id;

if (eventId) {
global.transactionIds.push(eventId);
}
}

return event;
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "../../test-recipe-schema.json",
"testApplicationName": "Node Express App",
"buildCommand": "yarn install && yarn build",
"tests": [
{
"testName": "Test express server",
"testCommand": "yarn test",
"timeoutSeconds": 60
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { test, expect } from '@playwright/test';
import axios, { AxiosError } from 'axios';

const authToken = process.env.E2E_TEST_AUTH_TOKEN;
const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG;
const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT;
const EVENT_POLLING_TIMEOUT = 30_000;

test('Sends exception to Sentry', async ({ baseURL }) => {
const { data } = await axios.get(`${baseURL}/test-error`);
const { exceptionId } = data;

const url = `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${exceptionId}/`;

console.log(`Polling for error eventId: ${exceptionId}`);

await expect
.poll(
async () => {
try {
const response = await axios.get(url, { headers: { Authorization: `Bearer ${authToken}` } });

return response.status;
} catch (e) {
if (e instanceof AxiosError && e.response) {
if (e.response.status !== 404) {
throw e;
} else {
return e.response.status;
}
} else {
throw e;
}
}
},
{ timeout: EVENT_POLLING_TIMEOUT },
)
.toBe(200);
});

test('Sends transactions to Sentry', async ({ baseURL }) => {
const { data } = await axios.get(`${baseURL}/test-transaction`);
const { transactionIds } = data;

console.log(`Polling for transaction eventIds: ${JSON.stringify(transactionIds)}`);

expect(transactionIds.length).toBeGreaterThan(0);

await Promise.all(
transactionIds.map(async (transactionId: string) => {
const url = `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${transactionId}/`;

await expect
.poll(
async () => {
try {
const response = await axios.get(url, { headers: { Authorization: `Bearer ${authToken}` } });

return response.status;
} catch (e) {
if (e instanceof AxiosError && e.response) {
if (e.response.status !== 404) {
throw e;
} else {
return e.response.status;
}
} else {
throw e;
}
}
},
{ timeout: EVENT_POLLING_TIMEOUT },
)
.toBe(200);
}),
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"types": ["node"],
"esModuleInterop": true,
"lib": ["ES6"],
"strict": true,
"outDir": "dist"
},
"include": ["src/**/*.ts"]
}
Loading