From 0c8d0435c0e3c95fbf257e2ce99c7ac52a72631a Mon Sep 17 00:00:00 2001 From: Sophie Stadler Date: Tue, 17 Oct 2023 12:33:33 -0400 Subject: [PATCH 1/4] Remove Bugsnag code --- .evergreen.yml | 2 - package.json | 4 - scripts/deploy/deploy.sh | 6 - scripts/deploy/upload-bugsnag-sourcemaps.js | 9 - scripts/setup-credentials.js | 1 - src/components/ErrorHandling/Bugsnag.tsx | 65 ------ .../ErrorHandling/ErrorBoundary.test.tsx | 6 +- .../ErrorHandling/ErrorBoundary.tsx | 20 +- .../ErrorHandling/initialize.test.ts | 39 ---- src/components/ErrorHandling/initialize.ts | 6 - src/utils/environmentVariables.ts | 7 - yarn.lock | 194 +----------------- 12 files changed, 7 insertions(+), 352 deletions(-) delete mode 100644 scripts/deploy/upload-bugsnag-sourcemaps.js delete mode 100644 src/components/ErrorHandling/Bugsnag.tsx diff --git a/.evergreen.yml b/.evergreen.yml index 020c49467f..15cd9c6e4f 100644 --- a/.evergreen.yml +++ b/.evergreen.yml @@ -391,7 +391,6 @@ functions: working_dir: spruce script: | echo "Generating .env-cmdrc.json" - REACT_APP_BUGSNAG_API_KEY=${REACT_APP_BUGSNAG_API_KEY} \ REACT_APP_SENTRY_AUTH_TOKEN=${REACT_APP_SENTRY_AUTH_TOKEN} \ REACT_APP_SENTRY_DSN=${REACT_APP_SENTRY_DSN} \ REACT_APP_NEW_RELIC_ACCOUNT_ID=${REACT_APP_NEW_RELIC_ACCOUNT_ID} \ @@ -420,7 +419,6 @@ functions: shell: bash script: | ${PREPARE_SHELL} - REACT_APP_BUGSNAG_API_KEY=${REACT_APP_BUGSNAG_API_KEY} \ BUCKET=${bucket} \ AWS_ACCESS_KEY_ID=${aws_key} \ AWS_SECRET_ACCESS_KEY=${aws_secret} \ diff --git a/package.json b/package.json index a147f07ff5..e04c97138d 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,6 @@ "storybook": "storybook dev -p 6006", "test:watch": "node scripts/test.js --verbose", "test": "node scripts/test.js --watchAll=false", - "upload-source-maps": "env-cmd -e production node ./scripts/deploy/upload-bugsnag-sourcemaps", "postversion": "scripts/push-version.sh" }, "browserslist": { @@ -55,8 +54,6 @@ }, "dependencies": { "@apollo/client": "3.8.4", - "@bugsnag/js": "7.20.2", - "@bugsnag/plugin-react": "7.18.0", "@emotion/css": "11.11.2", "@emotion/react": "11.11.1", "@emotion/styled": "11.11.0", @@ -133,7 +130,6 @@ "@babel/plugin-proposal-private-property-in-object": "^7.17.12", "@babel/preset-react": "^7.12.13", "@babel/preset-typescript": "7.21.5", - "@bugsnag/source-maps": "^2.3.0", "@emotion/babel-plugin": "11.11.0", "@emotion/eslint-plugin": "11.11.0", "@emotion/jest": "11.11.0", diff --git a/scripts/deploy/deploy.sh b/scripts/deploy/deploy.sh index 0529c24301..b0b5e8507c 100644 --- a/scripts/deploy/deploy.sh +++ b/scripts/deploy/deploy.sh @@ -1,14 +1,8 @@ #!/bin/sh # This script runs the aws cli command to deploy the app to s3 -# It also uploads source maps to bugsnag # Try this step and throw an error if it fails echo "Deploying to S3" aws s3 sync build/ s3://"${BUCKET}"/ --acl public-read --follow-symlinks --delete --exclude .env-cmdrc.json echo "Deployed to S3" - -# If the above step succeeds, run this step -echo "Uploading source maps to Bugsnag" -./scripts/deploy/app-version.sh && node ./scripts/deploy/upload-bugsnag-sourcemaps.js -echo "Source maps uploaded to Bugsnag" diff --git a/scripts/deploy/upload-bugsnag-sourcemaps.js b/scripts/deploy/upload-bugsnag-sourcemaps.js deleted file mode 100644 index e548b70163..0000000000 --- a/scripts/deploy/upload-bugsnag-sourcemaps.js +++ /dev/null @@ -1,9 +0,0 @@ -const { browser } = require("@bugsnag/source-maps"); - -browser.uploadMultiple({ - apiKey: process.env.REACT_APP_BUGSNAG_API_KEY, - appVersion: process.env.REACT_APP_VERSION, - overwrite: true, - directory: "./build/assets", - baseUrl: `${process.env.REACT_APP_SPRUCE_URL}/assets`, -}); diff --git a/scripts/setup-credentials.js b/scripts/setup-credentials.js index 3e03c06d8b..dceb6357ef 100644 --- a/scripts/setup-credentials.js +++ b/scripts/setup-credentials.js @@ -12,7 +12,6 @@ const production = { REACT_APP_PARSLEY_URL: "https://parsley.mongodb.com", REACT_APP_SPRUCE_URL: "https://spruce.mongodb.com", REACT_APP_RELEASE_STAGE: "production", - REACT_APP_BUGSNAG_API_KEY: process.env.REACT_APP_BUGSNAG_API_KEY, REACT_APP_SENTRY_AUTH_TOKEN: process.env.REACT_APP_SENTRY_AUTH_TOKEN, REACT_APP_SENTRY_DSN: process.env.REACT_APP_SENTRY_DSN, REACT_APP_NEW_RELIC_ACCOUNT_ID: process.env.REACT_APP_NEW_RELIC_ACCOUNT_ID, diff --git a/src/components/ErrorHandling/Bugsnag.tsx b/src/components/ErrorHandling/Bugsnag.tsx deleted file mode 100644 index 0232f89985..0000000000 --- a/src/components/ErrorHandling/Bugsnag.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import React from "react"; -import Bugsnag, { Event } from "@bugsnag/js"; -import BugsnagPluginReact from "@bugsnag/plugin-react"; -import { environmentVariables } from "utils"; -import ErrorFallback from "./ErrorFallback"; - -const { getAppVersion, getBugsnagApiKey, getReleaseStage } = - environmentVariables; - -const initializeBugsnag = () => { - try { - Bugsnag.start({ - apiKey: getBugsnagApiKey(), - plugins: [new BugsnagPluginReact()], - appVersion: getAppVersion(), - releaseStage: getReleaseStage(), - }); - } catch (e) { - // If Bugsnag fails we have no where to log it and we can't do anything about it. - console.error("Failed to initialize Bugsnag", e); - } -}; - -const ErrorBoundary: React.FC<{ children: React.ReactNode }> = ({ - children, -}) => { - const BugsnagErrorBoundary = - Bugsnag.getPlugin("react").createErrorBoundary(React); - - const onError = (event: Event) => { - const userId = localStorage.getItem("userId") ?? undefined; - event.setUser(userId); - event.addMetadata("metadata", { - viewedErrorPage: true, - }); - }; - - return ( - } - > - {children} - - ); -}; - -const sendError = ( - err: Error, - severity: Event["severity"], - metadata?: { [key: string]: any } -) => { - const userId = localStorage.getItem("userId"); - Bugsnag.notify(err, (event) => { - // reassigning param is recommended usage in bugsnag docs - // eslint-disable-next-line no-param-reassign - event.severity = severity; - event.setUser(userId); - if (metadata) { - event.addMetadata("metadata", metadata); - } - }); -}; - -export { ErrorBoundary, initializeBugsnag, sendError }; diff --git a/src/components/ErrorHandling/ErrorBoundary.test.tsx b/src/components/ErrorHandling/ErrorBoundary.test.tsx index 7ce1788530..e55c5649d7 100644 --- a/src/components/ErrorHandling/ErrorBoundary.test.tsx +++ b/src/components/ErrorHandling/ErrorBoundary.test.tsx @@ -1,4 +1,3 @@ -import Bugsnag from "@bugsnag/js"; import * as Sentry from "@sentry/react"; import { render, screen } from "test_utils"; import { mockEnvironmentVariables } from "test_utils/utils"; @@ -9,13 +8,14 @@ const { cleanup } = mockEnvironmentVariables(); describe("default error boundary", () => { beforeEach(() => { jest.spyOn(console, "error").mockImplementation(() => {}); - jest.spyOn(Bugsnag, "notify"); jest.spyOn(Sentry, "captureException"); }); + afterEach(() => { cleanup(); jest.restoreAllMocks(); }); + it("should render the passed in component", () => { const TestComponent = () =>
Hello
; const TestErrorBoundary = () => ( @@ -26,6 +26,7 @@ describe("default error boundary", () => { render(); expect(screen.getByText("Hello")).toBeInTheDocument(); }); + it("should display the fallback when an error occurs", () => { const err = new Error("Test error"); @@ -45,7 +46,6 @@ describe("default error boundary", () => { componentStack: expect.any(String), }), }); - expect(Bugsnag.notify).not.toHaveBeenCalled(); expect(Sentry.captureException).not.toHaveBeenCalled(); }); }); diff --git a/src/components/ErrorHandling/ErrorBoundary.tsx b/src/components/ErrorHandling/ErrorBoundary.tsx index 2986c59ef1..1ec73ae7f6 100644 --- a/src/components/ErrorHandling/ErrorBoundary.tsx +++ b/src/components/ErrorHandling/ErrorBoundary.tsx @@ -1,6 +1,4 @@ import { Component } from "react"; -import Bugsnag from "@bugsnag/js"; -import { ErrorBoundary as BugsnagErrorBoundary } from "./Bugsnag"; import ErrorFallback from "./ErrorFallback"; import { ErrorBoundary as SentryErrorBoundary, isInitialized } from "./Sentry"; @@ -41,24 +39,10 @@ class DefaultErrorBoundary extends Component< export const ErrorBoundary: React.FC<{ children: React.ReactNode }> = ({ children, }) => { - const useBugsnag = Bugsnag.isStarted(); const useSentry = isInitialized(); - if (!useBugsnag && !useSentry) { - return {children}; - } - - let errorBoundary = children; - if (useSentry) { - errorBoundary = {errorBoundary}; + return {children}; } - - if (useBugsnag) { - errorBoundary = ( - {errorBoundary} - ); - } - - return <>{errorBoundary}; // eslint-disable-line react/jsx-no-useless-fragment + return {children}; }; diff --git a/src/components/ErrorHandling/initialize.test.ts b/src/components/ErrorHandling/initialize.test.ts index 65bbb694b7..43e2862b54 100644 --- a/src/components/ErrorHandling/initialize.test.ts +++ b/src/components/ErrorHandling/initialize.test.ts @@ -1,5 +1,3 @@ -import Bugsnag from "@bugsnag/js"; -import BugsnagPluginReact from "@bugsnag/plugin-react"; import * as Sentry from "@sentry/react"; import { mockEnvironmentVariables } from "test_utils/utils"; import { initializeErrorHandling } from "."; @@ -8,8 +6,6 @@ const { cleanup, mockEnv } = mockEnvironmentVariables(); describe("should initialize error handlers according to release stage", () => { beforeEach(() => { - jest.spyOn(Bugsnag, "start").mockImplementation(jest.fn()); - jest.spyOn(Bugsnag, "isStarted").mockImplementation(jest.fn(() => false)); jest.spyOn(Sentry, "init").mockImplementation(jest.fn()); jest .spyOn(Sentry, "Replay") @@ -27,7 +23,6 @@ describe("should initialize error handlers according to release stage", () => { mockEnv("REACT_APP_RELEASE_STAGE", "production"); initializeErrorHandling(); - expect(Bugsnag.start).not.toHaveBeenCalled(); expect(Sentry.init).not.toHaveBeenCalled(); }); @@ -35,17 +30,9 @@ describe("should initialize error handlers according to release stage", () => { mockEnv("NODE_ENV", "production"); mockEnv("REACT_APP_VERSION", "1.0.0"); mockEnv("REACT_APP_RELEASE_STAGE", "production"); - mockEnv("REACT_APP_BUGSNAG_API_KEY", "i-am-a-fake-key"); mockEnv("REACT_APP_SENTRY_DSN", "fake-sentry-key"); initializeErrorHandling(); - expect(Bugsnag.start).toHaveBeenCalledWith({ - apiKey: "i-am-a-fake-key", - appVersion: "1.0.0", - releaseStage: "production", - plugins: [new BugsnagPluginReact()], - }); - expect(Sentry.init).toHaveBeenCalledWith({ dsn: "fake-sentry-key", debug: false, @@ -61,17 +48,9 @@ describe("should initialize error handlers according to release stage", () => { mockEnv("REACT_APP_RELEASE_STAGE", "beta"); mockEnv("NODE_ENV", "production"); mockEnv("REACT_APP_VERSION", "1.0.0"); - mockEnv("REACT_APP_BUGSNAG_API_KEY", "i-am-a-fake-key"); mockEnv("REACT_APP_SENTRY_DSN", "fake-sentry-key"); initializeErrorHandling(); - expect(Bugsnag.start).toHaveBeenCalledWith({ - apiKey: "i-am-a-fake-key", - appVersion: "1.0.0", - releaseStage: "beta", - plugins: [new BugsnagPluginReact()], - }); - expect(Sentry.init).toHaveBeenCalledWith({ dsn: "fake-sentry-key", debug: true, @@ -87,17 +66,9 @@ describe("should initialize error handlers according to release stage", () => { mockEnv("NODE_ENV", "production"); mockEnv("REACT_APP_VERSION", "1.0.0"); mockEnv("REACT_APP_RELEASE_STAGE", "staging"); - mockEnv("REACT_APP_BUGSNAG_API_KEY", "i-am-a-fake-key"); mockEnv("REACT_APP_SENTRY_DSN", "fake-sentry-key"); initializeErrorHandling(); - expect(Bugsnag.start).toHaveBeenCalledWith({ - apiKey: "i-am-a-fake-key", - appVersion: "1.0.0", - releaseStage: "staging", - plugins: [new BugsnagPluginReact()], - }); - expect(Sentry.init).toHaveBeenCalledWith({ dsn: "fake-sentry-key", debug: true, @@ -112,8 +83,6 @@ describe("should initialize error handlers according to release stage", () => { describe("should not initialize if the client is already running", () => { beforeEach(() => { - jest.spyOn(Bugsnag, "start").mockImplementation(jest.fn()); - jest.spyOn(Bugsnag, "isStarted").mockImplementation(jest.fn(() => false)); jest.spyOn(Sentry, "init").mockImplementation(jest.fn()); mockEnv("NODE_ENV", "production"); }); @@ -123,19 +92,11 @@ describe("should not initialize if the client is already running", () => { cleanup(); }); - it("does not initialize Bugsnag twice", () => { - jest.spyOn(Bugsnag, "isStarted").mockImplementation(jest.fn(() => true)); - initializeErrorHandling(); - expect(Bugsnag.start).not.toHaveBeenCalled(); - expect(Sentry.init).toHaveBeenCalledTimes(1); - }); - it("does not initialize Sentry twice", () => { const mockClient = { getClient: jest.fn(() => true) }; // @ts-expect-error - Type error occurs because the entire return value of getCurrentHub is not mocked jest.spyOn(Sentry, "getCurrentHub").mockReturnValue(mockClient); initializeErrorHandling(); - expect(Bugsnag.start).toHaveBeenCalledTimes(1); expect(Sentry.init).not.toHaveBeenCalled(); }); }); diff --git a/src/components/ErrorHandling/initialize.ts b/src/components/ErrorHandling/initialize.ts index 37b777b2fe..b3bcbc50f3 100644 --- a/src/components/ErrorHandling/initialize.ts +++ b/src/components/ErrorHandling/initialize.ts @@ -1,6 +1,4 @@ -import Bugsnag from "@bugsnag/js"; import { environmentVariables } from "utils"; -import { initializeBugsnag } from "./Bugsnag"; import { initializeSentry, isInitialized } from "./Sentry"; const { isProductionBuild } = environmentVariables; @@ -10,10 +8,6 @@ export const initializeErrorHandling = () => { return; } - if (!Bugsnag.isStarted()) { - initializeBugsnag(); - } - if (!isInitialized()) { initializeSentry(); } diff --git a/src/utils/environmentVariables.ts b/src/utils/environmentVariables.ts index a78dfb8495..019614f6d5 100644 --- a/src/utils/environmentVariables.ts +++ b/src/utils/environmentVariables.ts @@ -5,13 +5,6 @@ export const getApiUrl: () => string = () => process.env.REACT_APP_API_URL || ""; -/** - * `getBugsnagApiKey()` - Get the BUGSNAG API KEY from the environment variables - * @returns - The API KEY - */ -export const getBugsnagApiKey: () => string = () => - process.env.REACT_APP_BUGSNAG_API_KEY; - /** * `getSentryDSN()` - Get the Sentry Data Source Name (SENTRY_DSN) from the environment variables * @returns - The application's DSN diff --git a/yarn.lock b/yarn.lock index 0373265c0c..512b97fce1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1758,72 +1758,6 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@bugsnag/browser@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@bugsnag/browser/-/browser-7.20.2.tgz#1db0c52fbe6b90217c4efd7ac79e16ccb7336b78" - integrity sha512-4J4s53ZpYr3hHA+QjxUjOI6U+A8+XuUVH45UshE87Jp2Y4mV8ML2DovejqJS8J8yjdbnh2z1Wtg/v3WUNt4ayQ== - dependencies: - "@bugsnag/core" "^7.19.0" - -"@bugsnag/core@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@bugsnag/core/-/core-7.19.0.tgz#7663a4addb1322e8315a4012dc9db2aad3fea53b" - integrity sha512-2KGwdaLD9PhR7Wk7xPi3jGuGsKTatc/28U4TOZIDU3CgC2QhGjubwiXSECel5gwxhZ3jACKcMKSV2ovHhv1NrA== - dependencies: - "@bugsnag/cuid" "^3.0.0" - "@bugsnag/safe-json-stringify" "^6.0.0" - error-stack-parser "^2.0.3" - iserror "0.0.2" - stack-generator "^2.0.3" - -"@bugsnag/cuid@^3.0.0": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@bugsnag/cuid/-/cuid-3.0.2.tgz#544f8e6e7e3768c8cb618ca5c5fb1eea6aacbb7e" - integrity sha512-cIwzC93r3PQ/INeuwtZwkZIG2K8WWN0rRLZQhu+mr48Ay+i6sEki4GYfTsflse7hZ1BeDWrNb/Q9vgY3B31xHQ== - -"@bugsnag/js@7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@bugsnag/js/-/js-7.20.2.tgz#218ec77d1df8b70d9353d4f2f2ccd3e51a331786" - integrity sha512-Q08k0h0h6NFwFGkFmib39Uln2WpvJdqT1EGF1JlyYiGW03Y+VopVb9r37pZrRrN9IY08mxaIEO8la5xeaWAs6A== - dependencies: - "@bugsnag/browser" "^7.20.2" - "@bugsnag/node" "^7.19.0" - -"@bugsnag/node@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@bugsnag/node/-/node-7.19.0.tgz#6a8e5d0f5e73a1d0bad19537def1a7ff65e19787" - integrity sha512-c4snyxx5d/fsMogmgehFBGc//daH6+4XCplia4zrEQYltjaQ+l8ud0dPx623DgJl/2j1+2zlRc7y7IHSd7Gm5w== - dependencies: - "@bugsnag/core" "^7.19.0" - byline "^5.0.0" - error-stack-parser "^2.0.2" - iserror "^0.0.2" - pump "^3.0.0" - stack-generator "^2.0.3" - -"@bugsnag/plugin-react@7.18.0": - version "7.18.0" - resolved "https://registry.yarnpkg.com/@bugsnag/plugin-react/-/plugin-react-7.18.0.tgz#cce7e0185ba4f7c2ca581138efa3f0f6ad1c5564" - integrity sha512-i4FYauv/8G1ZRH4dTegYPzw5+xt76ubt1GCr4wRieD8q5QBKcvHIqaNrnM9yQ/QNmWnz24LeCCDUVdIb5SrhPA== - -"@bugsnag/safe-json-stringify@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@bugsnag/safe-json-stringify/-/safe-json-stringify-6.0.0.tgz#22abdcd83e008c369902976730c34c150148a758" - integrity sha512-htzFO1Zc57S8kgdRK9mLcPVTW1BY2ijfH7Dk2CeZmspTWKdKqSo1iwmqrq2WtRjFlo8aRZYgLX0wFrDXF/9DLA== - -"@bugsnag/source-maps@^2.3.0": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@bugsnag/source-maps/-/source-maps-2.3.1.tgz#3caa33b7b9879e58e233eae017726852c50b1106" - integrity sha512-9xJTcf5+W7+y1fQBftSOste/3ORi+d5EeCCMdvaHSX69MKQP0lrDiSYpLwX/ErcXrTbvu7nimGGKJP2vBdF7zQ== - dependencies: - command-line-args "^5.1.1" - command-line-usage "^6.1.0" - concat-stream "^2.0.0" - consola "^2.15.0" - form-data "^3.0.0" - glob "^7.1.6" - read-pkg-up "^7.0.1" - "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" @@ -6820,16 +6754,6 @@ aria-query@^5.0.0: dependencies: dequal "^2.0.3" -array-back@^3.0.1, array-back@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" - integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== - -array-back@^4.0.1, array-back@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" - integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== - array-buffer-byte-length@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" @@ -7394,11 +7318,6 @@ busboy@^1.6.0: dependencies: streamsearch "^1.1.0" -byline@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" - integrity sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q== - bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -7749,26 +7668,6 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -command-line-args@^5.1.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" - integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== - dependencies: - array-back "^3.1.0" - find-replace "^3.0.0" - lodash.camelcase "^4.3.0" - typical "^4.0.0" - -command-line-usage@^6.1.0: - version "6.1.3" - resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" - integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== - dependencies: - array-back "^4.0.2" - chalk "^2.4.2" - table-layout "^1.0.2" - typical "^5.2.0" - commander@^2.19.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -7873,26 +7772,11 @@ concat-stream@^1.6.2: readable-stream "^2.2.2" typedarray "^0.0.6" -concat-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1" - integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.0.2" - typedarray "^0.0.6" - confusing-browser-globals@^1.0.10: version "1.0.11" resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== -consola@^2.15.0: - version "2.15.3" - resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550" - integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw== - constant-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-3.0.4.tgz#3b84a9aeaf4cf31ec45e6bf5de91bdfb0589faf1" @@ -8240,11 +8124,6 @@ deep-equal@^2.0.5: which-collection "^1.0.1" which-typed-array "^1.1.9" -deep-extend@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -8603,13 +8482,6 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -error-stack-parser@^2.0.2, error-stack-parser@^2.0.3: - version "2.1.4" - resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286" - integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== - dependencies: - stackframe "^1.3.4" - es-abstract@^1.19.0, es-abstract@^1.20.4: version "1.22.1" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.1.tgz#8b4e5fc5cefd7f1660f0f8e1a52900dfbc9d9ccc" @@ -9580,13 +9452,6 @@ find-cache-dir@^4.0.0: common-path-prefix "^3.0.0" pkg-dir "^7.0.0" -find-replace@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" - integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== - dependencies: - array-back "^3.0.1" - find-root@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" @@ -9946,7 +9811,7 @@ glob@^10.0.0: minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-scurry "^1.10.1" -glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0: +glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.2.0: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -10857,11 +10722,6 @@ isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== -iserror@0.0.2, iserror@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/iserror/-/iserror-0.0.2.tgz#bd53451fe2f668b9f2402c1966787aaa2c7c0bf5" - integrity sha512-oKGGrFVaWwETimP3SiWwjDeY27ovZoyZPHtxblC4hCq9fXxed/jasx+ATWFFjCVSRZng8VTMsN1nDnGo6zMBSw== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -11784,11 +11644,6 @@ lodash-es@^4.17.15: resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== - lodash.debounce@4.0.8, lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -13722,7 +13577,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.2.2, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0: +readable-stream@^3.1.1, readable-stream@^3.4.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -13777,11 +13632,6 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" -reduce-flatten@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" - integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== - regenerate-unicode-properties@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" @@ -14456,13 +14306,6 @@ sshpk@^1.14.1: safer-buffer "^2.0.2" tweetnacl "~0.14.0" -stack-generator@^2.0.3: - version "2.0.10" - resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.10.tgz#8ae171e985ed62287d4f1ed55a1633b3fb53bb4d" - integrity sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ== - dependencies: - stackframe "^1.3.4" - stack-utils@^2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" @@ -14470,11 +14313,6 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" -stackframe@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" - integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== - statuses@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" @@ -14750,16 +14588,6 @@ tabbable@^6.2.0: resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-6.2.0.tgz#732fb62bc0175cfcec257330be187dcfba1f3b97" integrity sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew== -table-layout@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" - integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== - dependencies: - array-back "^4.0.1" - deep-extend "~0.6.0" - typical "^5.2.0" - wordwrapjs "^4.0.0" - tar-fs@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" @@ -15156,16 +14984,6 @@ typescript@5.0.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.3.tgz#fe976f0c826a88d0a382007681cbb2da44afdedf" integrity sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA== -typical@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" - integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== - -typical@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" - integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== - ua-parser-js@^1.0.35: version "1.0.35" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.35.tgz#c4ef44343bc3db0a3cbefdf21822f1b1fc1ab011" @@ -15745,14 +15563,6 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -wordwrapjs@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" - integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== - dependencies: - reduce-flatten "^2.0.0" - typical "^5.2.0" - "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" From 61d3df2c3f7dde89ff16da3f7cca361c90146d4e Mon Sep 17 00:00:00 2001 From: Sophie Stadler Date: Tue, 17 Oct 2023 12:54:46 -0400 Subject: [PATCH 2/4] Remove bugsnag to sentry conversion --- src/components/HistoryTable/HistoryTable.tsx | 6 +- src/context/auth.tsx | 6 +- src/gql/GQLWrapper.tsx | 14 ++- src/pages/taskHistory/index.tsx | 6 +- src/pages/variantHistory/index.tsx | 6 +- src/utils/errorReporting.test.ts | 41 ++----- src/utils/errorReporting.ts | 113 +++++-------------- 7 files changed, 60 insertions(+), 132 deletions(-) diff --git a/src/components/HistoryTable/HistoryTable.tsx b/src/components/HistoryTable/HistoryTable.tsx index 07941330db..f8bcbbbde8 100644 --- a/src/components/HistoryTable/HistoryTable.tsx +++ b/src/components/HistoryTable/HistoryTable.tsx @@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef } from "react"; import throttle from "lodash.throttle"; import { Virtuoso, VirtuosoHandle } from "react-virtuoso"; import { useDimensions } from "hooks/useDimensions"; -import { leaveBreadcrumb } from "utils/errorReporting"; +import { leaveBreadcrumb, SentryBreadcrumb } from "utils/errorReporting"; import { types } from "."; import { useHistoryTable } from "./HistoryTableContext"; import EndOfHistoryRow from "./HistoryTableRow/EndOfHistoryRow"; @@ -55,7 +55,7 @@ const HistoryTable: React.FC = ({ { selectedCommit, }, - "process" + SentryBreadcrumb.UI ); listRef.current.scrollToIndex(selectedCommit.rowIndex); } @@ -71,7 +71,7 @@ const HistoryTable: React.FC = ({ selectedCommit, processedCommitCount, }, - "process" + SentryBreadcrumb.UI ); loadMoreItems(); } diff --git a/src/context/auth.tsx b/src/context/auth.tsx index 8d704d3637..5f02b0bb71 100644 --- a/src/context/auth.tsx +++ b/src/context/auth.tsx @@ -1,6 +1,6 @@ import { createContext, useContext, useMemo, useReducer } from "react"; import { environmentVariables } from "utils"; -import { leaveBreadcrumb } from "utils/errorReporting"; +import { leaveBreadcrumb, SentryBreadcrumb } from "utils/errorReporting"; const { getLoginDomain, getUiUrl } = environmentVariables; @@ -66,13 +66,13 @@ const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ window.location.href = `${getLoginDomain()}/login`; }) .catch((error) => { - leaveBreadcrumb("Logout failed", { error }, "user"); + leaveBreadcrumb("Logout failed", { error }, SentryBreadcrumb.User); }); }, dispatchAuthenticated: () => { if (!state.isAuthenticated) { dispatch({ type: "authenticated" }); - leaveBreadcrumb("Authenticated", {}, "user"); + leaveBreadcrumb("Authenticated", {}, SentryBreadcrumb.User); } }, }), diff --git a/src/gql/GQLWrapper.tsx b/src/gql/GQLWrapper.tsx index ba3193c943..f0e62bd846 100644 --- a/src/gql/GQLWrapper.tsx +++ b/src/gql/GQLWrapper.tsx @@ -10,7 +10,11 @@ import { RetryLink } from "@apollo/client/link/retry"; import { routes } from "constants/routes"; import { useAuthDispatchContext } from "context/auth"; import { environmentVariables } from "utils"; -import { leaveBreadcrumb, reportError } from "utils/errorReporting"; +import { + leaveBreadcrumb, + reportError, + SentryBreadcrumb, +} from "utils/errorReporting"; const { getGQLUrl } = environmentVariables; @@ -128,7 +132,11 @@ const authLink = (logout: () => void): ApolloLink => networkError.statusCode === 401 && window.location.pathname !== routes.login ) { - leaveBreadcrumb("Not Authenticated", { statusCode: 401 }, "user"); + leaveBreadcrumb( + "Not Authenticated", + { status_code: 401 }, + SentryBreadcrumb.User + ); logout(); } }); @@ -164,7 +172,7 @@ const authenticateIfSuccessfulLink = ( status: !response.errors ? "OK" : "ERROR", errors: response.errors, }, - "request" + SentryBreadcrumb.HTTP ); return response; }) diff --git a/src/pages/taskHistory/index.tsx b/src/pages/taskHistory/index.tsx index 897856330b..0883a788e1 100644 --- a/src/pages/taskHistory/index.tsx +++ b/src/pages/taskHistory/index.tsx @@ -26,7 +26,7 @@ import { import { MAINLINE_COMMITS_FOR_HISTORY } from "gql/queries"; import { usePageTitle } from "hooks"; import { string } from "utils"; -import { leaveBreadcrumb } from "utils/errorReporting"; +import { leaveBreadcrumb, SentryBreadcrumb } from "utils/errorReporting"; import BuildVariantSelector from "./BuildVariantSelector"; import ColumnHeaders from "./ColumnHeaders"; import TaskHistoryRow from "./TaskHistoryRow"; @@ -76,7 +76,7 @@ const TaskHistoryContents: React.FC = () => { taskName, numCommits: mainlineCommits.versions.length, }, - "process" + SentryBreadcrumb.UI ); ingestNewCommits(mainlineCommits); }, @@ -96,7 +96,7 @@ const TaskHistoryContents: React.FC = () => { taskName, skipOrderNumber: data.mainlineCommits?.nextPageOrderNumber, }, - "process" + SentryBreadcrumb.UI ); refetch({ mainlineCommitsOptions: { diff --git a/src/pages/variantHistory/index.tsx b/src/pages/variantHistory/index.tsx index fde2af78ca..e0a373ae05 100644 --- a/src/pages/variantHistory/index.tsx +++ b/src/pages/variantHistory/index.tsx @@ -26,7 +26,7 @@ import { import { MAINLINE_COMMITS_FOR_HISTORY } from "gql/queries"; import { usePageTitle } from "hooks"; import { string } from "utils"; -import { leaveBreadcrumb } from "utils/errorReporting"; +import { leaveBreadcrumb, SentryBreadcrumb } from "utils/errorReporting"; import ColumnHeaders from "./ColumnHeaders"; import TaskSelector from "./TaskSelector"; import VariantHistoryRow from "./VariantHistoryRow"; @@ -74,7 +74,7 @@ const VariantHistoryContents: React.FC = () => { variantName, numCommits: mainlineCommits.versions.length, }, - "process" + SentryBreadcrumb.UI ); ingestNewCommits(mainlineCommits); }, @@ -94,7 +94,7 @@ const VariantHistoryContents: React.FC = () => { variantName, skipOrderNumber: data.mainlineCommits?.nextPageOrderNumber, }, - "process" + SentryBreadcrumb.UI ); refetch({ mainlineCommitsOptions: { diff --git a/src/utils/errorReporting.test.ts b/src/utils/errorReporting.test.ts index c219dbf666..4ed10d3b68 100644 --- a/src/utils/errorReporting.test.ts +++ b/src/utils/errorReporting.test.ts @@ -1,14 +1,16 @@ -import Bugsnag from "@bugsnag/js"; import * as Sentry from "@sentry/react"; import { mockEnvironmentVariables } from "test_utils/utils"; -import { leaveBreadcrumb, reportError } from "utils/errorReporting"; +import { + leaveBreadcrumb, + reportError, + SentryBreadcrumb, +} from "utils/errorReporting"; const { cleanup, mockEnv } = mockEnvironmentVariables(); describe("error reporting", () => { beforeEach(() => { jest.spyOn(console, "error").mockImplementation(() => {}); - jest.spyOn(Bugsnag, "notify"); jest.spyOn(Sentry, "captureException"); }); afterEach(() => { @@ -29,28 +31,23 @@ describe("error reporting", () => { err, severity: "warning", }); - expect(Bugsnag.notify).not.toHaveBeenCalled(); expect(Sentry.captureException).not.toHaveBeenCalled(); }); - it("should report errors to Bugsnag and Sentry when in production", () => { + it("should report errors to Sentry when in production", () => { mockEnv("NODE_ENV", "production"); - jest.spyOn(Bugsnag, "notify").mockImplementation(jest.fn()); jest.spyOn(Sentry, "captureException").mockImplementation(jest.fn()); const err = new Error("test error"); const result = reportError(err); result.severe(); - expect(Bugsnag.notify).toHaveBeenCalledWith(err, expect.any(Function)); expect(Sentry.captureException).toHaveBeenCalledWith(err); result.warning(); - expect(Bugsnag.notify).toHaveBeenLastCalledWith(err, expect.any(Function)); expect(Sentry.captureException).toHaveBeenCalledWith(err); }); it("supports metadata field", () => { mockEnv("NODE_ENV", "production"); - jest.spyOn(Bugsnag, "notify").mockImplementation(jest.fn()); jest.spyOn(Sentry, "captureException").mockImplementation(jest.fn()); const err = { message: "GraphQL Error", @@ -60,10 +57,8 @@ describe("error reporting", () => { const metadata = { customField: "foo" }; const result = reportError(err, metadata); result.severe(); - expect(Bugsnag.notify).toHaveBeenCalledWith(err, expect.any(Function)); expect(Sentry.captureException).toHaveBeenCalledWith(err); result.warning(); - expect(Bugsnag.notify).toHaveBeenLastCalledWith(err, expect.any(Function)); expect(Sentry.captureException).toHaveBeenCalledWith(err); }); }); @@ -71,7 +66,6 @@ describe("error reporting", () => { describe("breadcrumbs", () => { beforeEach(() => { jest.spyOn(console, "debug").mockImplementation(() => {}); - jest.spyOn(Bugsnag, "leaveBreadcrumb"); jest.spyOn(Sentry, "addBreadcrumb"); }); afterEach(() => { @@ -81,7 +75,7 @@ describe("breadcrumbs", () => { it("should log breadcrumbs into console when not in production", () => { const message = "my message"; - const type = "error"; + const type = SentryBreadcrumb.Error; const metadata = { foo: "bar" }; leaveBreadcrumb(message, metadata, type); @@ -90,26 +84,19 @@ describe("breadcrumbs", () => { metadata, type, }); - expect(Bugsnag.leaveBreadcrumb).not.toHaveBeenCalled(); expect(Sentry.addBreadcrumb).not.toHaveBeenCalled(); }); - it("should report breadcrumbs to Bugsnag and Sentry when in production and convert Sentry breadcrumbs", () => { + it("should report breadcrumbs to Sentry when in production", () => { jest.useFakeTimers().setSystemTime(new Date("2020-01-01")); mockEnv("NODE_ENV", "production"); - jest.spyOn(Bugsnag, "leaveBreadcrumb").mockImplementation(jest.fn()); jest.spyOn(Sentry, "addBreadcrumb").mockImplementation(jest.fn()); const message = "my message"; - const type = "log"; - const metadata = { statusCode: 401 }; + const type = SentryBreadcrumb.Info; + const metadata = { status_code: 401 }; leaveBreadcrumb(message, metadata, type); - expect(Bugsnag.leaveBreadcrumb).toHaveBeenCalledWith( - message, - metadata, - type - ); expect(Sentry.addBreadcrumb).toHaveBeenCalledWith({ message, type: "info", @@ -123,11 +110,10 @@ describe("breadcrumbs", () => { jest.useFakeTimers().setSystemTime(new Date("2020-01-01")); jest.spyOn(console, "warn").mockImplementation(() => {}); mockEnv("NODE_ENV", "production"); - jest.spyOn(Bugsnag, "leaveBreadcrumb").mockImplementation(jest.fn()); jest.spyOn(Sentry, "addBreadcrumb").mockImplementation(jest.fn()); const message = "navigation message"; - const type = "navigation"; + const type = SentryBreadcrumb.Navigation; const metadata = {}; leaveBreadcrumb(message, metadata, type); @@ -139,11 +125,6 @@ describe("breadcrumbs", () => { 2, "Navigation breadcrumbs should include a 'to' metadata field." ); - expect(Bugsnag.leaveBreadcrumb).toHaveBeenCalledWith( - message, - metadata, - type - ); expect(Sentry.addBreadcrumb).toHaveBeenCalledWith({ message, type, diff --git a/src/utils/errorReporting.ts b/src/utils/errorReporting.ts index c555c81160..1e9cf63ae8 100644 --- a/src/utils/errorReporting.ts +++ b/src/utils/errorReporting.ts @@ -1,6 +1,4 @@ -import Bugsnag, { BreadcrumbType } from "@bugsnag/js"; import { addBreadcrumb, Breadcrumb } from "@sentry/react"; -import { sendError as bugsnagSendError } from "components/ErrorHandling/Bugsnag"; import { sendError as sentrySendError } from "components/ErrorHandling/Sentry"; import { isProductionBuild } from "./environmentVariables"; @@ -26,55 +24,14 @@ const reportError = ( return { severe: () => { - bugsnagSendError(err, "error", metadata); sentrySendError(err, "error", metadata); }, warning: () => { - bugsnagSendError(err, "warning", metadata); sentrySendError(err, "warning", metadata); }, }; }; -type Metadata = { - [key: string]: any; -}; - -const leaveBreadcrumb = ( - message: string, - metadata: Metadata, - type: BreadcrumbType -) => { - if (!isProductionBuild()) { - console.debug({ message, metadata, type }); - } else { - Bugsnag.leaveBreadcrumb(message, metadata, type); - addBreadcrumb(convertToSentryBreadcrumb(message, metadata, type)); - } -}; - -/** - * Convert a Bugsnag breadcrumb to Sentry's type. - * @param message - a string indicating details about the breadcrumb - * @param metadata - additional fields - * @param type - the type of Bugsnag breadcrumb to be sent - * @returns a Sentry breadcrumb - */ -const convertToSentryBreadcrumb = ( - message: string, - metadata: Metadata, - type: BreadcrumbType -): Breadcrumb => { - const breadcrumbType = convertBreadcrumbType(type); - return { - message, - data: convertMetadata(metadata, breadcrumbType), - // Divide date by 1000 because Sentry wants the timestamp in RFC 3339, or seconds (not milliseconds!) since the Unix epoch. - timestamp: new Date().getTime() / 1000, - type: breadcrumbType, - }; -}; - // The "type" field for Sentry breadcrumbs is just "string", but we can approximate the types listed here: // https://develop.sentry.dev/sdk/event-payloads/breadcrumbs/#breadcrumb-types enum SentryBreadcrumb { @@ -90,68 +47,50 @@ enum SentryBreadcrumb { User = "user", } -/** - * Convert a Bugsnag breadcrumb type to one of our custom Sentry types. - * @param breadcrumbType - the type of Bugsnag breadcrumb to be sent - * @returns a custom Sentry breadcrumb type - */ -const convertBreadcrumbType = ( - breadcrumbType: BreadcrumbType -): SentryBreadcrumb => { - switch (breadcrumbType) { - case "error": - return SentryBreadcrumb.Error; - case "navigation": - return SentryBreadcrumb.Navigation; - case "process": - return SentryBreadcrumb.UI; - case "request": - return SentryBreadcrumb.HTTP; - case "user": - return SentryBreadcrumb.User; - case "log": - return SentryBreadcrumb.Info; - case "manual": - case "state": - default: - return SentryBreadcrumb.Default; +const leaveBreadcrumb = ( + message: string, + metadata: Breadcrumb["data"], + type: SentryBreadcrumb +) => { + if (!isProductionBuild()) { + console.debug({ message, metadata, type }); + } else { + const bc: Breadcrumb = { + message, + data: validateMetadata(metadata, type), + // Divide date by 1000 because Sentry wants the timestamp in RFC 3339, or seconds (not milliseconds!) since the Unix epoch. + timestamp: new Date().getTime() / 1000, + type, + }; + addBreadcrumb(bc); } }; /** - * Convert a Bugsnag metadata field to use Sentry's key names and warn about missing fields. + * Ensure metadata follows Sentry's breadcrumb guidelines. * https://develop.sentry.dev/sdk/event-payloads/breadcrumbs/#breadcrumb-types - * @param bugsnagMetadata - Metadata object using Bugsnag-specific key names + * @param metadata - Metadata object * @param breadcrumbType - Sentry breadcrumb type - * @returns an object with the key names converted to Sentry's names. + * @returns an object adhering to Sentry's metadata rules. */ -const convertMetadata = ( - bugsnagMetadata: Metadata, +const validateMetadata = ( + metadata: Breadcrumb["data"], breadcrumbType: SentryBreadcrumb -): Metadata => { - // Convert statusCode => status_code - if (bugsnagMetadata.statusCode) { - const { statusCode, ...rest } = bugsnagMetadata; - return { - ...rest, - status_code: statusCode, - }; - } - +): Breadcrumb["data"] => { if (breadcrumbType === SentryBreadcrumb.Navigation) { - if (!bugsnagMetadata.from) { + if (!metadata.from) { console.warn( "Navigation breadcrumbs should include a 'from' metadata field." ); } - if (!bugsnagMetadata.to) { + if (!metadata.to) { console.warn( "Navigation breadcrumbs should include a 'to' metadata field." ); } } - return bugsnagMetadata; + return metadata; }; -export { leaveBreadcrumb, reportError }; +export { leaveBreadcrumb, reportError, SentryBreadcrumb }; From 6f85b5039dfeaf71649f1812c9d0f7a75bbcac61 Mon Sep 17 00:00:00 2001 From: Sophie Stadler Date: Tue, 17 Oct 2023 13:17:25 -0400 Subject: [PATCH 3/4] Don't remove app-verison script --- scripts/deploy/deploy.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/deploy/deploy.sh b/scripts/deploy/deploy.sh index b0b5e8507c..9f8cf5cd14 100644 --- a/scripts/deploy/deploy.sh +++ b/scripts/deploy/deploy.sh @@ -6,3 +6,7 @@ echo "Deploying to S3" aws s3 sync build/ s3://"${BUCKET}"/ --acl public-read --follow-symlinks --delete --exclude .env-cmdrc.json echo "Deployed to S3" + +# If the above step succeeds, run this step +echo "Exporting REACT_APP_VERSION variable" +./scripts/deploy/app-version.sh From 04b47fde52d528d6bf0742a7680784dc47984205 Mon Sep 17 00:00:00 2001 From: Sophie Stadler Date: Thu, 19 Oct 2023 16:29:38 -0400 Subject: [PATCH 4/4] Add app version to index.html --- index.html | 3 ++- package.json | 2 +- scripts/deploy/app-version.sh | 18 ------------------ scripts/deploy/deploy.sh | 4 ---- vite.config.ts | 1 + 5 files changed, 4 insertions(+), 24 deletions(-) delete mode 100755 scripts/deploy/app-version.sh diff --git a/index.html b/index.html index 3f1acf0f6b..fa387137ec 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,8 @@ - + +