Skip to content

meta(changelog): Update changelog for 7.96.0 #10330

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 16 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
2c43038
Merge pull request #10302 from getsentry/master
github-actions[bot] Jan 23, 2024
c5dcb5d
feat(browser): Export functional integrations & deprecate classes (#1…
mydea Jan 23, 2024
6fe349f
feat(deps): bump @sentry/cli from 2.25.0 to 2.26.0 (#10287)
dependabot[bot] Jan 23, 2024
3b4650c
feat(tracing): Deprecate transaction-related options for `BrowserTrac…
mydea Jan 24, 2024
a2f0bac
feat(browser): Deprecate `BrowserTracing` in favor of `browserTracing…
mydea Jan 24, 2024
d471dcf
fix(node): LocalVariables integration should use setupOnce (#10307)
timfish Jan 24, 2024
b1adeb6
fix(node): Fix downleveled types entry point (#10321)
Lms24 Jan 24, 2024
656b737
fix(node): Fix `node-cron` types and add test (#10315)
timfish Jan 24, 2024
b67d9b4
feat(react): Add `stripBasename` option for React Router 6. (#10314)
onurtemizkan Jan 24, 2024
b146d4c
test(node): Add `mongoose` auto instrumentation test for `@sentry/nod…
timfish Jan 24, 2024
10345d4
test(node): Add tests for Apollo / GraphQL OpenTelemetry auto-instrum…
onurtemizkan Jan 24, 2024
f613940
fix(replay): Fix type for options of replayIntegration (#10325)
Shubhdeep12 Jan 24, 2024
0d09983
feat(tracing): Revert browser tracing integration changes (#10328)
mydea Jan 24, 2024
52495c0
ref(tracing): Remove startChild calls from fetch/xhr instrumentation …
AbhiPrasad Jan 24, 2024
b72a681
fix(tracing): Ensure web vitals are correctly stopped/captured (#10323)
mydea Jan 24, 2024
bf84267
meta(changelog): Update changelog for 7.96.0
AbhiPrasad Jan 24, 2024
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
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,35 @@

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

## 7.96.0

### Important Changes

#### Deprecations

This release includes some deprecations for integrations in `@sentry/browser` and frontend framework SDKs
(`@sentry/react`, `@sentry/vue`, etc.). Please take a look at our
[migration guide](https://github.com/getsentry/sentry-javascript/blob/develop/MIGRATION.md) for more details.

- feat(browser): Export functional integrations & deprecate classes (#10267)

#### Web Vitals Fix for LCP and CLS

This release fixes an issue with the Web Vitals integration where LCP and CLS were not being captured correctly,
increasing capture rate by 10-30% for some apps. LCP and CLS capturing issues were introduced with version `7.75.0`.

- fix(tracing): Ensure web vitals are correctly stopped/captured (#10323)

### Other Changes

- feat(react): Add `stripBasename` option for React Router 6. (#10314)
- fix(node): Fix `node-cron` types and add test (#10315)
- fix(node): Fix downleveled types entry point (#10321)
- fix(node): LocalVariables integration should use setupOnce (#10307)
- fix(replay): Fix type for options of replayIntegration (#10325)

Work in this release contributed by @Shubhdeep12. Thank you for your contribution!

## 7.95.0

### Important Changes
Expand Down
36 changes: 25 additions & 11 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,31 @@ integrations from the `Integrations.XXX` hash, is deprecated in favor of using t

The following list shows how integrations should be migrated:

| Old | New | Packages |
| ------------------------ | ------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `new InboundFilters()` | `inboundFiltersIntegration()` | `@sentry/core`, `@sentry/browser`, `@sentry/node`, `@sentry/deno`, `@sentry/bun`, `@sentry/vercel-edge` |
| `new FunctionToString()` | `functionToStringIntegration()` | `@sentry/core`, `@sentry/browser`, `@sentry/node`, `@sentry/deno`, `@sentry/bun`, `@sentry/vercel-edge` |
| `new LinkedErrors()` | `linkedErrorsIntegration()` | `@sentry/core`, `@sentry/browser`, `@sentry/node`, `@sentry/deno`, `@sentry/bun`, `@sentry/vercel-edge` |
| `new ModuleMetadata()` | `moduleMetadataIntegration()` | `@sentry/core`, `@sentry/browser` |
| `new RequestData()` | `requestDataIntegration()` | `@sentry/core`, `@sentry/node`, `@sentry/deno`, `@sentry/bun`, `@sentry/vercel-edge` |
| `new Wasm() ` | `wasmIntegration()` | `@sentry/wasm` |
| `new Replay()` | `replayIntegration()` | `@sentry/browser` |
| `new ReplayCanvas()` | `replayCanvasIntegration()` | `@sentry/browser` |
| `new Feedback()` | `feedbackIntegration()` | `@sentry/browser` |
| Old | New | Packages |
| ------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `new InboundFilters()` | `inboundFiltersIntegration()` | `@sentry/core`, `@sentry/browser`, `@sentry/node`, `@sentry/deno`, `@sentry/bun`, `@sentry/vercel-edge` |
| `new FunctionToString()` | `functionToStringIntegration()` | `@sentry/core`, `@sentry/browser`, `@sentry/node`, `@sentry/deno`, `@sentry/bun`, `@sentry/vercel-edge` |
| `new LinkedErrors()` | `linkedErrorsIntegration()` | `@sentry/core`, `@sentry/browser`, `@sentry/node`, `@sentry/deno`, `@sentry/bun`, `@sentry/vercel-edge` |
| `new ModuleMetadata()` | `moduleMetadataIntegration()` | `@sentry/core`, `@sentry/browser` |
| `new RequestData()` | `requestDataIntegration()` | `@sentry/core`, `@sentry/node`, `@sentry/deno`, `@sentry/bun`, `@sentry/vercel-edge` |
| `new Wasm() ` | `wasmIntegration()` | `@sentry/wasm` |
| `new Replay()` | `replayIntegration()` | `@sentry/browser` |
| `new ReplayCanvas()` | `replayCanvasIntegration()` | `@sentry/browser` |
| `new Feedback()` | `feedbackIntegration()` | `@sentry/browser` |
| `new CaptureConsole()` | `captureConsoleIntegration()` | `@sentry/integrations` |
| `new Debug()` | `debugIntegration()` | `@sentry/integrations` |
| `new Dedupe()` | `dedupeIntegration()` | `@sentry/browser`, `@sentry/integrations`, `@sentry/deno` |
| `new ExtraErrorData()` | `extraErrorDataIntegration()` | `@sentry/integrations` |
| `new ReportingObserver()` | `reportingObserverIntegration()` | `@sentry/integrations` |
| `new RewriteFrames()` | `rewriteFramesIntegration()` | `@sentry/integrations` |
| `new SessionTiming()` | `sessionTimingIntegration()` | `@sentry/integrations` |
| `new HttpClient()` | `httpClientIntegration()` | `@sentry/integrations` |
| `new ContextLines()` | `contextLinesIntegration()` | `@sentry/browser` |
| `new Breadcrumbs()` | `breadcrumbsIntegration()` | `@sentry/browser`, `@sentry/deno` |
| `new GlobalHandlers()` | `globalHandlersIntegration()` | `@sentry/browser` |
| `new HttpContext()` | `httpContextIntegration()` | `@sentry/browser` |
| `new TryCatch()` | `browserApiErrorsIntegration()` | `@sentry/browser`, `@sentry/deno` |
| `new VueIntegration()` | `vueIntegration()` | `@sentry/vue` |

## Deprecate `hub.bindClient()` and `makeMain()`

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { addLcpInstrumentationHandler } from '@sentry-internal/tracing';

addLcpInstrumentationHandler(({ metric }) => {
const entry = metric.entries[metric.entries.length - 1];
window._LCP = entry.size;
});

addLcpInstrumentationHandler(({ metric }) => {
const entry = metric.entries[metric.entries.length - 1];
window._LCP2 = entry.size;
});

window.ADD_HANDLER = () => {
addLcpInstrumentationHandler(({ metric }) => {
const entry = metric.entries[metric.entries.length - 1];
window._LCP3 = entry.size;
});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<div id="content"></div>
<img src="https://example.com/path/to/image.png" />
<button type="button">Test button</button>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import type { Route } from '@playwright/test';
import { expect } from '@playwright/test';
import type { Event } from '@sentry/types';

import { sentryTest } from '../../../../utils/fixtures';
import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers';

const bundle = process.env.PW_BUNDLE || '';

sentryTest(
'should capture metrics for LCP instrumentation handlers',
async ({ browserName, getLocalTestPath, page }) => {
// This uses a utility that is not exported in CDN bundles
if (shouldSkipTracingTest() || browserName !== 'chromium' || bundle.startsWith('bundle')) {
sentryTest.skip();
}

await page.route('**/path/to/image.png', (route: Route) =>
route.fulfill({ path: `${__dirname}/assets/sentry-logo-600x179.png` }),
);

const url = await getLocalTestPath({ testDir: __dirname });
const [eventData] = await Promise.all([
getFirstSentryEnvelopeRequest<Event>(page),
page.goto(url),
page.click('button'),
]);

expect(eventData.measurements).toBeDefined();
expect(eventData.measurements?.lcp?.value).toBeDefined();

expect(eventData.tags?.['lcp.element']).toBe('body > img');
expect(eventData.tags?.['lcp.size']).toBe(107400);
expect(eventData.tags?.['lcp.url']).toBe('https://example.com/path/to/image.png');

const lcp = await (await page.waitForFunction('window._LCP')).jsonValue();
const lcp2 = await (await page.waitForFunction('window._LCP2')).jsonValue();
const lcp3 = await page.evaluate('window._LCP3');

expect(lcp).toEqual(107400);
expect(lcp2).toEqual(107400);
// this has not been triggered yet
expect(lcp3).toEqual(undefined);

// Adding a handler after LCP is completed still triggers the handler
await page.evaluate('window.ADD_HANDLER()');
const lcp3_2 = await (await page.waitForFunction('window._LCP3')).jsonValue();

expect(lcp3_2).toEqual(107400);
},
);
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,11 @@ export const ReplayRecordingData = [
description: 'largest-contentful-paint',
startTimestamp: expect.any(Number),
endTimestamp: expect.any(Number),
data: { value: expect.any(Number), size: expect.any(Number) },
data: {
value: expect.any(Number),
size: expect.any(Number),
nodeId: 16,
},
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,11 @@ export const ReplayRecordingData = [
description: 'largest-contentful-paint',
startTimestamp: expect.any(Number),
endTimestamp: expect.any(Number),
data: { value: expect.any(Number), size: expect.any(Number) },
data: {
value: expect.any(Number),
size: expect.any(Number),
nodeId: 16,
},
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,11 @@ export const ReplayRecordingData = [
description: 'largest-contentful-paint',
startTimestamp: expect.any(Number),
endTimestamp: expect.any(Number),
data: { value: expect.any(Number), size: expect.any(Number) },
data: {
value: expect.any(Number),
size: expect.any(Number),
nodeId: 16,
},
},
},
},
Expand Down
2 changes: 2 additions & 0 deletions dev-packages/node-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@
"apollo-server": "^3.11.1",
"axios": "^0.27.2",
"cors": "^2.8.5",
"cron": "^3.1.6",
"express": "^4.17.3",
"graphql": "^16.3.0",
"http-terminator": "^3.2.0",
"mongodb": "^3.7.3",
"mongoose": "^5.13.22",
"mongodb-memory-server-global": "^7.6.3",
"mysql": "^2.18.1",
"nock": "^13.1.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as Sentry from '@sentry/node';
import { CronJob } from 'cron';

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const CronJobWithCheckIn = Sentry.cron.instrumentCron(CronJob, 'my-cron-job');

setTimeout(() => {
process.exit(0);
}, 1_000);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { cleanupChildProcesses, createRunner } from '../../../utils/runner';

afterAll(() => {
cleanupChildProcesses();
});

test('node-cron types should match', done => {
createRunner(__dirname, 'scenario.ts').ensureNoErrorOutput().start(done);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const Sentry = require('@sentry/node-experimental');
const { loggingTransport } = require('@sentry-internal/node-integration-tests');

Sentry.init({
dsn: 'https://[email protected]/1337',
release: '1.0',
tracesSampleRate: 1.0,
transport: loggingTransport,
});

// Stop the process from exiting before the transaction is sent
setInterval(() => {}, 1000);

async function run() {
const { ApolloServer, gql } = require('apollo-server');

await Sentry.startSpan(
{
name: 'Test Transaction',
op: 'transaction',
},
async span => {
const typeDefs = gql`type Query { hello: String }`;

const resolvers = {
Query: {
hello: () => {
return 'Hello world!';
},
},
};

const server = new ApolloServer({
typeDefs,
resolvers,
});

// Ref: https://www.apollographql.com/docs/apollo-server/testing/testing/#testing-using-executeoperation
await server.executeOperation({
query: '{hello}',
});

setTimeout(() => {
span.end();
server.stop();
}, 500);
},
);
}

// eslint-disable-next-line @typescript-eslint/no-floating-promises
run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { conditionalTest } from '../../../utils';
import { createRunner } from '../../../utils/runner';

conditionalTest({ min: 14 })('GraphQL/Apollo Tests', () => {
const EXPECTED_TRANSACTION = {
transaction: 'Test Transaction',
spans: expect.arrayContaining([
expect.objectContaining({
data: {
'graphql.operation.type': 'query',
'graphql.source': '{hello}',
'otel.kind': 'INTERNAL',
'sentry.origin': 'auto.graphql.otel.graphql',
},
description: 'query',
status: 'ok',
origin: 'auto.graphql.otel.graphql',
}),
expect.objectContaining({
data: {
'graphql.field.name': 'hello',
'graphql.field.path': 'hello',
'graphql.field.type': 'String',
'graphql.source': 'hello',
'otel.kind': 'INTERNAL',
'sentry.origin': 'manual',
},
description: 'graphql.resolve',
status: 'ok',
origin: 'manual',
}),
]),
};

test('CJS - should instrument GraphQL queries used from Apollo Server.', done => {
createRunner(__dirname, 'scenario.js').expect({ transaction: EXPECTED_TRANSACTION }).start(done);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const { loggingTransport } = require('@sentry-internal/node-integration-tests');
const Sentry = require('@sentry/node-experimental');

Sentry.init({
dsn: 'https://[email protected]/1337',
release: '1.0',
debug: true,
tracesSampleRate: 1.0,
transport: loggingTransport,
});

// Stop the process from exiting before the transaction is sent
setInterval(() => {}, 1000);

// Must be required after Sentry is initialized
const mongoose = require('mongoose');

async function run() {
await mongoose.connect(process.env.MONGO_URL || '');

const Schema = mongoose.Schema;

const BlogPostSchema = new Schema({
title: String,
body: String,
date: Date,
});

const BlogPost = mongoose.model('BlogPost', BlogPostSchema);

await Sentry.startSpan(
{
name: 'Test Transaction',
op: 'transaction',
},
async () => {
const post = new BlogPost();
post.title = 'Test';
post.body = 'Test body';
post.date = new Date();

await post.save();

await BlogPost.findOne({});
},
);
}

// eslint-disable-next-line @typescript-eslint/no-floating-promises
run();
Loading