Skip to content

Commit

Permalink
[PB-458]:(feature) Add Sentry for main and renderer process
Browse files Browse the repository at this point in the history
  • Loading branch information
PixoDev committed May 8, 2023
1 parent ee4aaa4 commit 47497a0
Show file tree
Hide file tree
Showing 8 changed files with 378 additions and 99 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ NEW_API_URL=
NEW_DRIVE_URL=
RUDDERSTACK_KEY=
RUDDERSTACK_DATA_PLANE_URL=
SENTRY_DSN=
43 changes: 22 additions & 21 deletions env.d.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
declare global {
namespace NodeJS {
interface ProcessEnv {
CRYPTO_KEY: string;
MAGIC_IV: string;
MAGIC_SALT: string;
NEW_CRYPTO_KEY: string;
API_URL: string;
DRIVE_URL: string;
BRIDGE_URL: string;
APP_SEGMENT_KEY: string;
APP_SEGMENT_KEY_TEST: string;
BUG_REPORTING_URL: string;
platform: string;
NOTIFICATIONS_URL: string;
LOCK_REFRESH_INTERVAL: string;
PHOTOS_URL: string;
RUDDERSTACK_KEY: string;
RUDDERSTACK_DATA_PLANE_URL: string;
DRIVE_API_URL: string;
}
}
namespace NodeJS {
interface ProcessEnv {
CRYPTO_KEY: string;
MAGIC_IV: string;
MAGIC_SALT: string;
NEW_CRYPTO_KEY: string;
API_URL: string;
DRIVE_URL: string;
BRIDGE_URL: string;
APP_SEGMENT_KEY: string;
APP_SEGMENT_KEY_TEST: string;
BUG_REPORTING_URL: string;
platform: string;
NOTIFICATIONS_URL: string;
LOCK_REFRESH_INTERVAL: string;
PHOTOS_URL: string;
RUDDERSTACK_KEY: string;
RUDDERSTACK_DATA_PLANE_URL: string;
DRIVE_API_URL: string;
SENTRY_DSN: string;
}
}
}

export {};
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@
"@internxt/eslint-config-internxt": "^1.0.9",
"@playwright/test": "1.26.1",
"@pmmmwh/react-refresh-webpack-plugin": "0.5.4",
"@sentry/webpack-plugin": "^1.20.1",
"@svgr/webpack": "^6.1.2",
"@teamsupercell/typings-for-css-modules-loader": "^2.5.1",
"@testing-library/jest-dom": "^5.16.1",
Expand Down Expand Up @@ -250,6 +251,8 @@
"@internxt/inxt-js": "^2.0.7",
"@internxt/lib": "^1.1.6",
"@internxt/sdk": "^1.4.22",
"@sentry/electron": "^4.5.0",
"@sentry/react": "^7.51.0",
"async": "^3.2.4",
"axios": "^1.1.3",
"bytes": "^3.1.1",
Expand Down
104 changes: 60 additions & 44 deletions src/main/bug-report/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,70 +9,86 @@ import packageJson from '../../../package.json';
import { ErrorDetails } from '../../workers/types';
import { obtainToken } from '../auth/service';
import { BugReportResult } from './BugReportResult';
import * as Sentry from '@sentry/electron/main';

/**
* Reports an error to Sentry from the main process
*
* @param error The error to be reported
* @param context The context to attach to the error such the userId, tags, boolean values...
*/
export const reportError = (
error: Error,
context: Record<string, string> = {}
) => {
Sentry.captureException(error, context);
};

export async function sendReport({
errorDetails,
userComment,
includeLogs,
errorDetails,
userComment,
includeLogs,
}: {
errorDetails: ErrorDetails;
userComment: string;
includeLogs: boolean;
errorDetails: ErrorDetails;
userComment: string;
includeLogs: boolean;
}): Promise<BugReportResult> {
const form = new FormData();
const form = new FormData();

const reportBody = {
...errorDetails,
userComment,
version: packageJson.version,
};
const reportBody = {
...errorDetails,
userComment,
version: packageJson.version,
};

form.append('reportBody', JSON.stringify(reportBody));
form.append('reportBody', JSON.stringify(reportBody));

if (includeLogs) {
form.append('logs', await readLog());
}
if (includeLogs) {
form.append('logs', await readLog());
}

const res = await fetch(process.env.BUG_REPORTING_URL, {
method: 'POST',
body: form,
headers: { Authorization: `Bearer ${obtainToken('bearerToken')}` },
});
const res = await fetch(process.env.BUG_REPORTING_URL, {
method: 'POST',
body: form,
headers: { Authorization: `Bearer ${obtainToken('bearerToken')}` },
});

if (res.ok) {
return { state: 'OK' };
}
if (res.ok) {
return { state: 'OK' };
}

log.error(`Report status: ${res.status}`);
log.error(`Report status: ${res.status}`);

if (res.status === 429) {
return { state: 'TOO_MANY_REPORTS' };
}
if (res.status === 429) {
return { state: 'TOO_MANY_REPORTS' };
}

log.error(`[BUG-REPORT] Request to report bug failed with status: ${res.status}`);
log.error(
`[BUG-REPORT] Request to report bug failed with status: ${res.status}`
);

return { state: 'ERROR' };
return { state: 'ERROR' };
}

function readLog(): Promise<string> {
return new Promise(async (resolve, reject) => {
const logDir = path.parse(log.transports.file.getFile().path).dir;
const logPath = path.join(logDir, 'renderer.log');
return new Promise(async (resolve, reject) => {
const logDir = path.parse(log.transports.file.getFile().path).dir;
const logPath = path.join(logDir, 'renderer.log');

const MAX_SIZE = 1024 * 1024 * 5;
const MAX_SIZE = 1024 * 1024 * 5;

const { size } = await fs.lstat(logPath);
const { size } = await fs.lstat(logPath);

const start = size > MAX_SIZE ? size - MAX_SIZE : 0;
const start = size > MAX_SIZE ? size - MAX_SIZE : 0;

const stream = createReadStream(logPath, { start });
const stream = createReadStream(logPath, { start });

const rawFile: string[] = [];
const rawFile: string[] = [];

stream.on('data', (buf: string) => rawFile.push(buf));
stream.on('close', () => {
resolve(rawFile.join());
});
stream.on('error', reject);
});
stream.on('data', (buf: string) => rawFile.push(buf));
stream.on('close', () => {
resolve(rawFile.join());
});
stream.on('error', reject);
});
}
68 changes: 40 additions & 28 deletions src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,61 +32,73 @@ import { autoUpdater } from 'electron-updater';

import packageJson from '../../package.json';
import eventBus from './event-bus';
import * as Sentry from '@sentry/electron';
import { reportError } from './bug-report/service';

Logger.log(`Running ${packageJson.version}`);

Logger.log('Initializing Sentry for main process');
if (process.env.SENTRY_DSN) {
Sentry.init({
dsn: process.env.SENTRY_DSN,
});
Logger.log('Sentry is ready for main process');
} else {
Logger.error('Sentry DSN not found, cannot initialize Sentry');
}

function checkForUpdates() {
autoUpdater.logger = Logger;
autoUpdater.checkForUpdatesAndNotify();
autoUpdater.logger = Logger;
autoUpdater.checkForUpdatesAndNotify();
}

if (process.platform === 'darwin') {
app.dock.hide();
app.dock.hide();
}

if (process.env.NODE_ENV === 'production') {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const sourceMapSupport = require('source-map-support');
sourceMapSupport.install();
const sourceMapSupport = require('source-map-support');
sourceMapSupport.install();
}

if (process.env.NODE_ENV === 'development') {
// eslint-disable-next-line @typescript-eslint/no-var-requires
require('electron-debug')({ showDevTools: false });
// eslint-disable-next-line @typescript-eslint/no-var-requires
require('./dev/handlers');
require('electron-debug')({ showDevTools: false });
// eslint-disable-next-line @typescript-eslint/no-var-requires
require('./dev/handlers');
}

const installExtensions = async () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const installer = require('electron-devtools-installer');
const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
const extensions = ['REACT_DEVELOPER_TOOLS'];
const installer = require('electron-devtools-installer');
const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
const extensions = ['REACT_DEVELOPER_TOOLS'];

return installer
.default(
extensions.map((name) => installer[name]),
forceDownload
)
.catch(console.log);
return installer
.default(
extensions.map((name) => installer[name]),
forceDownload
)
.catch(console.log);
};

app.on('window-all-closed', () => {
app.quit();
app.quit();
});

ipcMain.on('user-quit', () => {
app.quit();
app.quit();
});

app
.whenReady()
.then(async () => {
eventBus.emit('APP_IS_READY');
.whenReady()
.then(async () => {
eventBus.emit('APP_IS_READY');

if (process.env.NODE_ENV === 'development') {
await installExtensions();
}
checkForUpdates();
})
.catch(Logger.error);
if (process.env.NODE_ENV === 'development') {
await installExtensions();
}
checkForUpdates();
})
.catch(Logger.error);
23 changes: 22 additions & 1 deletion src/renderer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
import { render } from 'react-dom';

import App from './App';
import { init } from '@sentry/electron/renderer';
import { init as reactInit } from '@sentry/react';

// Initialize Sentry for the Renderer process
// eslint-disable-next-line no-console
console.info('Initializing Sentry for renderer process');
if (process.env.SENTRY_DSN) {
init(
{
dsn: process.env.SENTRY_DSN,
debug: true,
},
reactInit
);
// eslint-disable-next-line no-console
console.info('Sentry is ready for renderer process');
} else {
// eslint-disable-next-line no-console
console.error(
'Sentry DSN not found, cannot initialize Sentry in renderer process'
);
}

render(<App />, document.getElementById('root'));
14 changes: 14 additions & 0 deletions src/renderer/utils/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as Sentry from '@sentry/electron/renderer';

/**
* Reports an error to Sentry from the renderer process
*
* @param error The error to be reported
* @param context The context to attach to the error such the userId, tags, boolean values...
*/
export const reportError = (
error: Error,
context: Record<string, string> = {}
) => {
Sentry.captureException(error, context);
};
Loading

0 comments on commit 47497a0

Please sign in to comment.