Skip to content
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

frontend: Bugsnag setup #2766

Merged
merged 9 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
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
31 changes: 31 additions & 0 deletions docs/development/frontend/bugsnag.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
title: BugSnag
{{ .EditURL }}
---

The frontend code in Clutch allows a user to utilize BugSnag for their bug catching abilities. The setup when using a Gateway or the normal clutch app is quite simple as it just requires the usage of environment variables.

An example is below

## Structure
```
frontend
├─ package.json
├─ .env.production
├─ ...
```

### Example Script in package.json
```json
"upload-sourcemaps": "yarn workspace @clutch-sh/tools uploadSourcemaps $PWD build/static .env.production --"
```

### Example .env.production
```bash
REACT_APP_SERVICE_NAME=<app>
REACT_APP_BUGSNAG_API_TOKEN=....
REACT_APP_BASE_URL=https://<app>.net
APPLICATION_ENV=production
```

And thats it, after setting up these few items Clutch will wrap the application in a BugSnag error boundary and report errors as it catches them.
1 change: 1 addition & 0 deletions docs/sidebars.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"items": [
"development/frontend/overview",
"development/frontend/storybook",
"development/frontend/bugsnag",
{
"type": "link",
"label": "Clutch's Storybook",
Expand Down
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"last 1 safari version"
]
},
"dependencies": {},
"devDependencies": {
"@babel/core": "^7.16.0",
"@mui/material": "^5.8.5",
Expand Down
2 changes: 2 additions & 0 deletions frontend/packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
"@mui/base": "5.0.0-alpha.86"
},
"dependencies": {
"@bugsnag/js": "^7.21.0",
"@bugsnag/plugin-react": "^7.19.0",
"@clutch-sh/api": "^2.0.0-beta",
"@date-io/core": "^1.3.6",
"@emotion/jest": "^11.0.0",
Expand Down
25 changes: 24 additions & 1 deletion frontend/packages/core/src/AppProvider/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from "react";
import { BrowserRouter as Router, Outlet, Route, Routes } from "react-router-dom";
import Bugsnag from "@bugsnag/js";
import BugsnagPluginReact from "@bugsnag/plugin-react";

import AppLayout from "../AppLayout";
import { ApplicationContext, ShortLinkContext } from "../Contexts";
Expand Down Expand Up @@ -205,4 +207,25 @@ const ClutchApp: React.FC<ClutchAppProps> = ({
);
};

export default ClutchApp;
const BugSnagApp = props => {
if (process.env.REACT_APP_BUGSNAG_API_TOKEN) {
// eslint-disable-next-line no-underscore-dangle
if (!(Bugsnag as any)._client) {
Bugsnag.start({
apiKey: process.env.REACT_APP_BUGSNAG_API_TOKEN,
plugins: [new BugsnagPluginReact()],
releaseStage: process.env.APPLICATION_ENV || "production",
});
}
const BugsnagBoundary = Bugsnag.getPlugin("react").createErrorBoundary(React);
return (
<BugsnagBoundary>
<ClutchApp {...props} />
</BugsnagBoundary>
);
}

return <ClutchApp {...props} />;
};

export default BugSnagApp;
5 changes: 4 additions & 1 deletion frontend/packages/tools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"lint": "eslint --ext .js,.jsx,.ts,.tsx .",
"lint:fix": "yarn run lint --fix",
"publishBeta": "../../../tools/publish-frontend.sh tools",
"registerWorkflows": "node workflow-registrar.js"
"registerWorkflows": "node workflow-registrar.js",
"uploadSourcemaps": "node upload-sourcemaps.js"
},
"dependencies": {
"@babel/cli": "^7.7.5",
Expand All @@ -22,6 +23,7 @@
"@babel/preset-env": "^7.16.4",
"@babel/preset-react": "^7.16.0",
"@babel/preset-typescript": "^7.16.0",
"@bugsnag/source-maps": "^2.3.1",
"@types/enzyme": "^3.10.8",
"@types/jest": "^29.0.0",
"@types/mocha": "^10.0.0",
Expand All @@ -34,6 +36,7 @@
"babel-jest": "^27.4.2",
"babel-plugin-module-resolver": "^4.0.0",
"cypress": "9.7.0",
"dotenv": "^16.3.1",
"enzyme": "^3.11.0",
"esbuild": "^0.18.0",
"eslint": "^8.3.0",
Expand Down
49 changes: 49 additions & 0 deletions frontend/packages/tools/upload-sourcemaps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* eslint-disable no-console */
const { browser } = require("@bugsnag/source-maps");
const { config } = require("dotenv");

const srcDir = process.argv[2];
const buildDir = process.argv[3];
const envFile = process.argv[4];

const dotEnvFile = `${srcDir}/${envFile}`;

config({ path: dotEnvFile });

const uploadToBugsnag = async ({ apiKey, baseUrl, distDir: directory }) => {
try {
await browser.uploadMultiple({
apiKey,
baseUrl,
directory,
overwrite: true,
});
console.info(`[BugSnag] Successfully uploaded source maps ${directory} to BugSnag`);
} catch (err) {
console.error(`[BugSnag] Error uploading source maps to BugSnag: ${err}`);
}
};

const uploadBugsnagSourcemaps = () => {
const apiKey = process.env.REACT_APP_BUGSNAG_API_TOKEN || "";
const baseUrl = process.env.REACT_APP_BASE_URL || "";
if (!apiKey || apiKey === "") {
jdslaugh marked this conversation as resolved.
Show resolved Hide resolved
console.error(`[BugSnag] No API token found in ${dotEnvFile} file. Skipping upload.`);
return Promise.reject(new Error("[BugSnag] API Key missing"));
}

if (!baseUrl || baseUrl === "") {
jdslaugh marked this conversation as resolved.
Show resolved Hide resolved
console.error(
`[BugSnag] No BaseUrl defined in process.env.BASE_URL in ${dotEnvFile}. Skipping Upload`
);
return Promise.reject(new Error("[BugSnag] BaseUrl missing"));
}

return uploadToBugsnag({
apiKey,
baseUrl: `${baseUrl}${process.env.REACT_APP_BASE_URL_PATH ?? "/static/js/"}`,
distDir: process.env.SOURCEMAPS_DIR || `${srcDir}/${buildDir}`,
});
};

uploadBugsnagSourcemaps();
Loading