Skip to content

Commit a749f4a

Browse files
Merge pull request #53 from codecov/spalmurray/sentry
feat: Add Sentry error monitoring
2 parents 1f9a6a7 + 5003d60 commit a749f4a

8 files changed

+1733
-355
lines changed

package-lock.json

+1,639-345
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+10-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,14 @@
134134
"codecov.api.gitProvider": {
135135
"type": "string",
136136
"default": "github",
137-
"enum": ["github", "github_enterprise", "gitlab", "gitlab_enterprise", "bitbucket", "bitbucket_server"],
137+
"enum": [
138+
"github",
139+
"github_enterprise",
140+
"gitlab",
141+
"gitlab_enterprise",
142+
"bitbucket",
143+
"bitbucket_server"
144+
],
138145
"description": "Where are your repositories hosted?",
139146
"order": 4
140147
},
@@ -155,6 +162,8 @@
155162
"lint": "eslint src --ext ts"
156163
},
157164
"dependencies": {
165+
"@sentry/browser": "^8.39.0",
166+
"@sentry/webpack-plugin": "^2.22.6",
158167
"axios": "^1.6.2",
159168
"fs-extra": "^11.2.0",
160169
"request-light": "^0.7.0",

src/coverage/coverage.ts

+16-5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
workspace,
1616
} from "vscode";
1717
import axios from "axios";
18+
import Sentry from "../sentry";
1819

1920
type Coverage =
2021
| {
@@ -239,9 +240,14 @@ export function activateCoverage(context: ExtensionContext) {
239240

240241
window.onDidChangeActiveTextEditor(
241242
(editor) => {
242-
activeEditor = editor;
243-
if (editor) {
244-
updateDecorations();
243+
try {
244+
activeEditor = editor;
245+
if (editor) {
246+
updateDecorations();
247+
}
248+
} catch (e) {
249+
Sentry.captureException(e);
250+
throw e;
245251
}
246252
},
247253
null,
@@ -250,8 +256,13 @@ export function activateCoverage(context: ExtensionContext) {
250256

251257
workspace.onDidSaveTextDocument(
252258
(event) => {
253-
if (activeEditor && event === activeEditor.document) {
254-
updateDecorations();
259+
try {
260+
if (activeEditor && event === activeEditor.document) {
261+
updateDecorations();
262+
}
263+
} catch (e) {
264+
Sentry.captureException(e);
265+
throw e;
255266
}
256267
},
257268
null,

src/main.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
import { ExtensionContext } from "vscode";
22
import { activateCoverage } from "./coverage/coverage";
33
import { activateYAML } from "./yaml/yamlClientMain";
4+
import Sentry from "./sentry";
45

56
export function activate(context: ExtensionContext) {
6-
activateCoverage(context);
7-
return activateYAML(context);
7+
try {
8+
activateCoverage(context);
9+
return activateYAML(context);
10+
} catch (e) {
11+
Sentry.captureException(e);
12+
throw e;
13+
}
814
}

src/sentry.ts

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import {
2+
BrowserClient,
3+
defaultStackParser,
4+
getDefaultIntegrations,
5+
makeFetchTransport,
6+
Scope,
7+
} from "@sentry/browser";
8+
9+
// Sentry config
10+
// Browser extensions (and vscode extensions!) must initialize Sentry a bit
11+
// differently to avoid conflicts between Sentry instances should the site the
12+
// extension is running on also use Sentry. Read more here:
13+
// https://docs.sentry.io/platforms/javascript/best-practices/browser-extensions/
14+
15+
const sentryIntegrations = getDefaultIntegrations({}).filter(
16+
(defaultIntegration) => {
17+
return ![
18+
"BrowserApiErrors",
19+
"TryCatch",
20+
"Breadcrumbs",
21+
"GlobalHandlers",
22+
].includes(defaultIntegration.name);
23+
}
24+
);
25+
26+
const sentryClient = new BrowserClient({
27+
// @ts-ignore SENTRY_DSN is populated by Webpack at build time
28+
dsn: SENTRY_DSN,
29+
transport: makeFetchTransport,
30+
stackParser: defaultStackParser,
31+
integrations: sentryIntegrations,
32+
});
33+
34+
const Sentry = new Scope();
35+
Sentry.setClient(sentryClient);
36+
sentryClient.init();
37+
38+
export default Sentry;

src/yaml/extension.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import type { IJSONSchemaCache } from "./json-schema-cache";
2323
import { getJsonSchemaContent } from "./json-schema-content-provider";
2424
import { joinPath } from "./paths";
2525
import { validateAction } from "./validate";
26+
import Sentry from "../sentry";
2627

2728
export interface ISchemaAssociations {
2829
[pattern: string]: string[];
@@ -134,7 +135,12 @@ export async function startClient(
134135
// Activate validator
135136
const command = "codecov.validate";
136137
const commandHandler = () => {
137-
validateAction(context);
138+
try {
139+
validateAction(context);
140+
} catch (e) {
141+
Sentry.captureException(e);
142+
throw e;
143+
}
138144
};
139145

140146
context.subscriptions.push(commands.registerCommand(command, commandHandler));

src/yaml/json-schema-content-provider.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ import {
1212
} from "request-light";
1313
import { SchemaExtensionAPI } from "./schema-extension-api";
1414
import type { IJSONSchemaCache } from "./json-schema-cache";
15+
import Sentry from "../sentry";
1516

1617
export class JSONSchemaDocumentContentProvider
17-
implements TextDocumentContentProvider {
18+
implements TextDocumentContentProvider
19+
{
1820
constructor(
1921
private readonly schemaCache: IJSONSchemaCache,
2022
private readonly schemaApi: SchemaExtensionAPI
@@ -117,6 +119,7 @@ export async function getJsonSchemaContent(
117119
}
118120

119121
function createReject(error: XHRResponse): Promise<string> {
122+
Sentry.captureException(error);
120123
return Promise.reject(
121124
error.responseText ||
122125
getErrorStatusDescription(error.status) ||

webpack.config.js

+11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
"use strict";
77

8+
const { sentryWebpackPlugin } = require("@sentry/webpack-plugin");
89
// eslint-disable-next-line @typescript-eslint/no-var-requires
910
const path = require("path");
1011
// eslint-disable-next-line @typescript-eslint/no-var-requires
@@ -55,6 +56,16 @@ const config = {
5556
},
5657
],
5758
},
59+
plugins: [
60+
new webpack.DefinePlugin({
61+
SENTRY_DSN: JSON.stringify(process.env.SENTRY_DSN),
62+
}),
63+
sentryWebpackPlugin({
64+
authToken: process.env.SENTRY_AUTH_TOKEN,
65+
org: "codecov",
66+
project: "vscode",
67+
}),
68+
],
5869
};
5970

6071
module.exports = [config];

0 commit comments

Comments
 (0)