Skip to content

Commit 09cf541

Browse files
authoredFeb 16, 2022
deps(sentry): move from raven to @sentry/node (#9325)
1 parent 0d9f0b9 commit 09cf541

File tree

7 files changed

+152
-98
lines changed

7 files changed

+152
-98
lines changed
 

‎build/build-bundle.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ async function build(entryPath, distPath, opts = {minify: true}) {
9494
'intl-pluralrules',
9595
'intl',
9696
'pako/lib/zlib/inflate.js',
97-
'raven',
97+
'@sentry/node',
9898
'source-map',
9999
'ws',
100100
require.resolve('../lighthouse-core/gather/connections/cri.js'),

‎lighthouse-cli/bin.js

+1-4
Original file line numberDiff line numberDiff line change
@@ -137,12 +137,9 @@ async function begin() {
137137
url: urlUnderTest,
138138
flags: cliFlags,
139139
environmentData: {
140-
name: 'redacted', // prevent sentry from using hostname
140+
serverName: 'redacted', // prevent sentry from using hostname
141141
environment: isDev() ? 'development' : 'production',
142142
release: pkg.version,
143-
tags: {
144-
channel: 'cli',
145-
},
146143
},
147144
});
148145
}

‎lighthouse-core/lib/sentry.js

+39-24
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77

88
const log = require('lighthouse-logger');
99

10-
/** @typedef {import('raven').CaptureOptions} CaptureOptions */
11-
/** @typedef {import('raven').ConstructorOptions} ConstructorOptions */
10+
/** @typedef {import('@sentry/node').Breadcrumb} Breadcrumb */
11+
/** @typedef {import('@sentry/node').NodeClient} NodeClient */
12+
/** @typedef {import('@sentry/node').NodeOptions} NodeOptions */
13+
/** @typedef {import('@sentry/node').Severity} Severity */
1214

1315
const SENTRY_URL = 'https://a6bb0da87ee048cc9ae2a345fc09ab2e:63a7029f46f74265981b7e005e0f69f8@sentry.io/174697';
1416

@@ -21,30 +23,30 @@ const SAMPLED_ERRORS = [
2123
// e.g.: {pattern: /No.*node with given id/, rate: 0.01},
2224
];
2325

24-
const noop = () => {};
26+
const noop = () => { };
2527

2628
/**
2729
* A delegate for sentry so that environments without error reporting enabled will use
2830
* noop functions and environments with error reporting will call the actual Sentry methods.
2931
*/
3032
const sentryDelegate = {
3133
init,
32-
/** @type {(message: string, options?: CaptureOptions) => void} */
34+
/** @type {(message: string, level?: Severity) => void} */
3335
captureMessage: noop,
34-
/** @type {(breadcrumb: any) => void} */
36+
/** @type {(breadcrumb: Breadcrumb) => void} */
3537
captureBreadcrumb: noop,
3638
/** @type {() => any} */
3739
getContext: noop,
38-
/** @type {(error: Error, options?: CaptureOptions) => Promise<void>} */
39-
captureException: async () => {},
40+
/** @type {(error: Error, options: {level?: string, tags?: {[key: string]: any}, extra?: {[key: string]: any}}) => Promise<void>} */
41+
captureException: async () => { },
4042
_shouldSample() {
4143
return SAMPLE_RATE >= Math.random();
4244
},
4345
};
4446

4547
/**
4648
* When called, replaces noops with actual Sentry implementation.
47-
* @param {{url: string, flags: LH.CliFlags, environmentData: ConstructorOptions}} opts
49+
* @param {{url: string, flags: LH.CliFlags, environmentData: NodeOptions}} opts
4850
*/
4951
function init(opts) {
5052
// If error reporting is disabled, leave the functions as a noop
@@ -58,15 +60,25 @@ function init(opts) {
5860
}
5961

6062
try {
61-
const Sentry = require('raven');
62-
const sentryConfig = Object.assign({}, opts.environmentData,
63-
{captureUnhandledRejections: true});
64-
Sentry.config(SENTRY_URL, sentryConfig).install();
63+
const Sentry = require('@sentry/node');
64+
Sentry.init({
65+
...opts.environmentData,
66+
dsn: SENTRY_URL,
67+
});
68+
69+
const extras = {
70+
...opts.flags.throttling,
71+
channel: opts.flags.channel || 'cli',
72+
url: opts.url,
73+
formFactor: opts.flags.formFactor,
74+
throttlingMethod: opts.flags.throttlingMethod,
75+
};
76+
Sentry.setExtras(extras);
6577

6678
// Have each delegate function call the corresponding sentry function by default
6779
sentryDelegate.captureMessage = (...args) => Sentry.captureMessage(...args);
68-
sentryDelegate.captureBreadcrumb = (...args) => Sentry.captureBreadcrumb(...args);
69-
sentryDelegate.getContext = () => Sentry.getContext();
80+
sentryDelegate.captureBreadcrumb = (...args) => Sentry.addBreadcrumb(...args);
81+
sentryDelegate.getContext = () => extras;
7082

7183
// Keep a record of exceptions per audit/gatherer so we can just report once
7284
const sentryExceptionCache = new Map();
@@ -107,21 +119,24 @@ function init(opts) {
107119
opts.tags.protocolMethod = err.protocolMethod;
108120
}
109121

110-
return new Promise(resolve => {
111-
Sentry.captureException(err, opts, () => resolve());
122+
Sentry.withScope(scope => {
123+
if (opts.level) {
124+
// @ts-expect-error - allow any string.
125+
scope.setLevel(opts.level);
126+
}
127+
if (opts.tags) {
128+
scope.setTags(opts.tags);
129+
}
130+
if (opts.extra) {
131+
scope.setExtras(opts.extra);
132+
}
133+
Sentry.captureException(err);
112134
});
113135
};
114-
115-
const context = Object.assign({
116-
url: opts.url,
117-
formFactor: opts.flags.formFactor,
118-
throttlingMethod: opts.flags.throttlingMethod,
119-
}, opts.flags.throttling);
120-
Sentry.mergeContext({extra: Object.assign({}, opts.environmentData.extra, context)});
121136
} catch (e) {
122137
log.warn(
123138
'sentry',
124-
'Could not load raven library, errors will not be reported.'
139+
'Could not load Sentry, errors will not be reported.'
125140
);
126141
}
127142
}

‎lighthouse-core/runner.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ class Runner {
149149
Sentry.captureBreadcrumb({
150150
message: 'Run started',
151151
category: 'lifecycle',
152-
data: sentryContext?.extra,
152+
data: sentryContext,
153153
});
154154

155155
/** @type {LH.Artifacts} */

‎lighthouse-core/test/lib/sentry-test.js

+28-24
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
*/
66
'use strict';
77

8-
jest.mock('raven');
8+
jest.mock('@sentry/node');
99

10-
const raven = require('raven');
10+
const sentryNode = require('@sentry/node');
1111
const Sentry = require('../../lib/sentry.js');
1212

1313
/* eslint-env jest */
@@ -27,9 +27,14 @@ describe('Sentry', () => {
2727
// We want to have a fresh state for every test.
2828
originalSentry = {...Sentry};
2929

30-
raven.config = jest.fn().mockReturnValue({install: jest.fn()});
31-
raven.mergeContext = jest.fn();
32-
raven.captureException = jest.fn().mockImplementation((err, opts, cb) => cb());
30+
sentryNode.init = jest.fn().mockReturnValue({install: jest.fn()});
31+
sentryNode.setExtras = jest.fn();
32+
sentryNode.captureException = jest.fn();
33+
sentryNode.withScope = (fn) => fn({
34+
setLevel: () => {},
35+
setTags: () => {},
36+
setExtras: () => {},
37+
});
3338
Sentry._shouldSample = jest.fn().mockReturnValue(true);
3439
});
3540

@@ -41,18 +46,18 @@ describe('Sentry', () => {
4146
describe('.init', () => {
4247
it('should noop when !enableErrorReporting', () => {
4348
Sentry.init({url: 'http://example.com', flags: {}});
44-
expect(raven.config).not.toHaveBeenCalled();
49+
expect(sentryNode.init).not.toHaveBeenCalled();
4550
Sentry.init({url: 'http://example.com', flags: {enableErrorReporting: false}});
46-
expect(raven.config).not.toHaveBeenCalled();
51+
expect(sentryNode.init).not.toHaveBeenCalled();
4752
});
4853

4954
it('should noop when not picked for sampling', () => {
5055
Sentry._shouldSample.mockReturnValue(false);
5156
Sentry.init({url: 'http://example.com', flags: {enableErrorReporting: true}});
52-
expect(raven.config).not.toHaveBeenCalled();
57+
expect(sentryNode.init).not.toHaveBeenCalled();
5358
});
5459

55-
it('should initialize the raven client when enableErrorReporting', () => {
60+
it('should initialize the Sentry client when enableErrorReporting', () => {
5661
Sentry.init({
5762
url: 'http://example.com',
5863
flags: {
@@ -63,26 +68,25 @@ describe('Sentry', () => {
6368
environmentData: {},
6469
});
6570

66-
expect(raven.config).toHaveBeenCalled();
67-
expect(raven.mergeContext).toHaveBeenCalled();
68-
expect(raven.mergeContext.mock.calls[0][0]).toEqual({
69-
extra: {
70-
url: 'http://example.com',
71-
formFactor: 'desktop',
72-
throttlingMethod: 'devtools',
73-
},
71+
expect(sentryNode.init).toHaveBeenCalled();
72+
expect(sentryNode.setExtras).toHaveBeenCalled();
73+
expect(sentryNode.setExtras.mock.calls[0][0]).toEqual({
74+
channel: 'cli',
75+
url: 'http://example.com',
76+
formFactor: 'desktop',
77+
throttlingMethod: 'devtools',
7478
});
7579
});
7680
});
7781

7882
describe('.captureException', () => {
79-
it('should forward exceptions to raven client', async () => {
83+
it('should forward exceptions to Sentry client', async () => {
8084
Sentry.init(configPayload);
8185
const error = new Error('oops');
8286
await Sentry.captureException(error);
8387

84-
expect(raven.captureException).toHaveBeenCalled();
85-
expect(raven.captureException.mock.calls[0][0]).toBe(error);
88+
expect(sentryNode.captureException).toHaveBeenCalled();
89+
expect(sentryNode.captureException.mock.calls[0][0]).toBe(error);
8690
});
8791

8892
it('should skip expected errors', async () => {
@@ -91,7 +95,7 @@ describe('Sentry', () => {
9195
error.expected = true;
9296
await Sentry.captureException(error);
9397

94-
expect(raven.captureException).not.toHaveBeenCalled();
98+
expect(sentryNode.captureException).not.toHaveBeenCalled();
9599
});
96100

97101
it('should skip duplicate audit errors', async () => {
@@ -100,7 +104,7 @@ describe('Sentry', () => {
100104
await Sentry.captureException(error, {tags: {audit: 'my-audit'}});
101105
await Sentry.captureException(error, {tags: {audit: 'my-audit'}});
102106

103-
expect(raven.captureException).toHaveBeenCalledTimes(1);
107+
expect(sentryNode.captureException).toHaveBeenCalledTimes(1);
104108
});
105109

106110
it('should still allow different audit errors', async () => {
@@ -110,7 +114,7 @@ describe('Sentry', () => {
110114
await Sentry.captureException(errorA, {tags: {audit: 'my-audit'}});
111115
await Sentry.captureException(errorB, {tags: {audit: 'my-audit'}});
112116

113-
expect(raven.captureException).toHaveBeenCalledTimes(2);
117+
expect(sentryNode.captureException).toHaveBeenCalledTimes(2);
114118
});
115119

116120
it('should skip duplicate gatherer errors', async () => {
@@ -119,7 +123,7 @@ describe('Sentry', () => {
119123
await Sentry.captureException(error, {tags: {gatherer: 'my-gatherer'}});
120124
await Sentry.captureException(error, {tags: {gatherer: 'my-gatherer'}});
121125

122-
expect(raven.captureException).toHaveBeenCalledTimes(1);
126+
expect(sentryNode.captureException).toHaveBeenCalledTimes(1);
123127
});
124128
});
125129
});

‎package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@
121121
"@types/lodash.set": "^4.3.6",
122122
"@types/node": "*",
123123
"@types/pako": "^1.0.1",
124-
"@types/raven": "^2.5.1",
125124
"@types/resize-observer-browser": "^0.1.1",
126125
"@types/semver": "^5.5.0",
127126
"@types/tabulator-tables": "^4.9.1",
@@ -183,6 +182,7 @@
183182
"webtreemap-cdt": "^3.2.1"
184183
},
185184
"dependencies": {
185+
"@sentry/node": "^6.17.4",
186186
"axe-core": "4.3.5",
187187
"chrome-launcher": "^0.15.0",
188188
"configstore": "^5.0.1",
@@ -204,7 +204,6 @@
204204
"open": "^8.4.0",
205205
"parse-cache-control": "1.0.1",
206206
"ps-list": "^8.0.0",
207-
"raven": "^2.2.1",
208207
"robots-parser": "^3.0.0",
209208
"semver": "^5.3.0",
210209
"speedline-core": "^1.4.3",

0 commit comments

Comments
 (0)
Please sign in to comment.