refactor: remove Sentry test error handling from main and renderer processes

This commit is contained in:
sudipnext 2026-04-12 19:33:40 +05:45
parent 5c0c09e623
commit fd16768945
9 changed files with 1 additions and 379 deletions

View file

@ -16,7 +16,7 @@ import { getPuppeteerExecutablePath, isChromeInstalled } from "./utils/puppeteer
import { getLiteParseRunnerPath } from "./utils/liteparse-check";
import { getImageMagickBinaryPath, isImageMagickInstalled } from "./utils/imagemagick-check";
import { startUpdateChecker, stopUpdateChecker } from "./utils/update-checker";
import { captureMainSentryTestError, initMainSentry } from "./sentry/main";
import { initMainSentry } from "./sentry/main";
var win: BrowserWindow | undefined;
@ -31,9 +31,6 @@ const startupStatus: Record<string, string> = {
// Allow renderer to query initial startup status as soon as it loads.
ipcMain.handle("startup:get-status", () => startupStatus);
ipcMain.handle("sentry:test-main-error", (_event, message?: string) => {
return captureMainSentryTestError(message);
});
initMainSentry();

View file

@ -1,5 +1,4 @@
import { contextBridge, ipcRenderer } from 'electron';
import { captureRendererSentryTestError } from './sentry';
contextBridge.exposeInMainWorld('env', {
NEXT_PUBLIC_FAST_API: process.env.NEXT_PUBLIC_FAST_API || '',
@ -36,6 +35,4 @@ contextBridge.exposeInMainWorld('electron', {
onStartupStatus: (callback: (payload: { name: string; status: string }) => void) =>
ipcRenderer.on("startup:status", (_event, payload) => callback(payload)),
getStartupStatus: () => ipcRenderer.invoke("startup:get-status"),
captureSentryRendererTestError: (message?: string) => captureRendererSentryTestError(message),
captureSentryMainTestError: (message?: string) => ipcRenderer.invoke("sentry:test-main-error", message),
});

View file

@ -74,13 +74,4 @@ export function initRendererSentry(): void {
Sentry.setTag('process.type', 'renderer');
}
export function captureRendererSentryTestError(message?: string): string | null {
if (!isSentryInitialized) {
return null;
}
const error = new Error(message || 'Sentry test error in renderer process');
return Sentry.captureException(error);
}
initRendererSentry();

View file

@ -81,12 +81,3 @@ export function initMainSentry(): void {
console.error("[Sentry] Failed to initialize in Electron main process:", error);
}
}
export function captureMainSentryTestError(message?: string): string | null {
if (!isSentryInitialized) {
return null;
}
const error = new Error(message || "Sentry test error in main process");
return Sentry.captureException(error);
}

View file

@ -83,8 +83,3 @@ app.add_middleware(
)
app.add_middleware(UserConfigEnvUpdateMiddleware)
@app.get("/sentry-debug")
async def trigger_error():
return {"division_by_zero": 1 / 0}

View file

@ -2,17 +2,11 @@
import React, { useEffect, useState } from "react";
import { Switch } from "@/components/ui/switch";
import { setTelemetryEnabled } from "@/utils/mixpanel";
import { getFastAPIUrl } from "@/utils/api";
import { Loader2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { notify } from "@/components/ui/sonner";
const PrivacySettings = () => {
const [trackingEnabled, setTrackingEnabled] = useState<boolean | null>(null);
const [saving, setSaving] = useState(false);
const [testingMainSentry, setTestingMainSentry] = useState(false);
const [testingNextjsSentry, setTestingNextjsSentry] = useState(false);
const [testingFastapiSentry, setTestingFastapiSentry] = useState(false);
useEffect(() => {
async function fetchStatus() {
@ -58,73 +52,6 @@ const PrivacySettings = () => {
}
};
const handleSentryMainTest = async () => {
if (!window.electron?.captureSentryMainTestError) {
notify.error(
"Sentry test unavailable",
"Electron preload API is missing. Restart the desktop app and try again.",
);
return;
}
setTestingMainSentry(true);
try {
const eventId = await window.electron.captureSentryMainTestError("test error");
if (eventId) {
notify.success(
"Sentry test sent",
`Main process test event submitted. Event ID: ${eventId}`,
);
} else {
notify.info(
"Sentry test attempted",
"No event ID returned. Check main-process Sentry initialization logs.",
);
}
} catch (error) {
const message =
error instanceof Error ? error.message : "Could not send Sentry test event.";
notify.error("Sentry test failed", message);
} finally {
setTestingMainSentry(false);
}
};
const handleSentryNextjsTest = async () => {
setTestingNextjsSentry(true);
try {
await fetch("/api/sentry-example-api", { cache: "no-store" });
notify.info(
"Next.js test triggered",
"If Sentry is configured, the Next.js API error event should appear shortly.",
);
} catch (error) {
const message =
error instanceof Error ? error.message : "Could not call Next.js Sentry test route.";
notify.error("Next.js test failed", message);
} finally {
setTestingNextjsSentry(false);
}
};
const handleSentryFastapiTest = async () => {
setTestingFastapiSentry(true);
try {
const baseUrl = getFastAPIUrl();
await fetch(`${baseUrl}/sentry-debug`, { cache: "no-store" });
notify.info(
"FastAPI test triggered",
"If Sentry is configured, the FastAPI error event should appear shortly.",
);
} catch (error) {
const message =
error instanceof Error ? error.message : "Could not call FastAPI Sentry test route.";
notify.error("FastAPI test failed", message);
} finally {
setTestingFastapiSentry(false);
}
};
if (trackingEnabled === null) {
return (
<div className="w-full bg-[#F9F8F8] p-7 rounded-[20px] flex items-center justify-center min-h-[200px]">
@ -170,27 +97,6 @@ const PrivacySettings = () => {
</div>
</div>
</div>
<div className="bg-[#F9F8F8] p-7 rounded-[20px]">
<h4 className="text-sm font-semibold text-[#191919] mb-1">
Sentry Integration Test
</h4>
<p className="text-xs text-[#6B7280] mb-6 leading-relaxed max-w-lg">
Trigger test failures from Electron main, Next.js, and FastAPI to verify
all Sentry pipelines are reporting events.
</p>
<div className="flex flex-wrap gap-3">
<Button onClick={handleSentryMainTest} disabled={testingMainSentry}>
{testingMainSentry ? "Sending Main Event..." : "Test Electron Main"}
</Button>
<Button onClick={handleSentryNextjsTest} disabled={testingNextjsSentry} variant="outline">
{testingNextjsSentry ? "Triggering Next.js..." : "Test Next.js"}
</Button>
<Button onClick={handleSentryFastapiTest} disabled={testingFastapiSentry} variant="outline">
{testingFastapiSentry ? "Triggering FastAPI..." : "Test FastAPI"}
</Button>
</div>
</div>
</div>
);
};

View file

@ -1,16 +0,0 @@
import * as Sentry from "@sentry/nextjs";
class SentryExampleAPIError extends Error {
constructor(message: string | undefined) {
super(message);
this.name = "SentryExampleAPIError";
}
}
// A faulty API route to test Sentry's error monitoring
export function GET() {
Sentry.logger.info("Sentry example API called");
throw new SentryExampleAPIError(
"This error is raised on the backend called by the example page.",
);
}

View file

@ -1,237 +0,0 @@
"use client";
import * as Sentry from "@sentry/nextjs";
import Head from "next/head";
import { useEffect, useState } from "react";
class SentryExampleFrontendError extends Error {
constructor(message: string | undefined) {
super(message);
this.name = "SentryExampleFrontendError";
}
}
export default function Page() {
const [hasSentError, setHasSentError] = useState(false);
const [isConnected, setIsConnected] = useState(true);
useEffect(() => {
Sentry.logger.info("Sentry example page loaded");
async function checkConnectivity() {
const result = await Sentry.diagnoseSdkConnectivity();
setIsConnected(result !== "sentry-unreachable");
}
checkConnectivity();
}, []);
return (
<div>
<Head>
<title>sentry-example-page</title>
<meta name="description" content="Test Sentry for your Next.js app!" />
</Head>
<main>
<div className="flex-spacer" />
<svg
height="40"
width="40"
fill="none"
xmlns="http://www.w3.org/2000/svg"
role="img"
aria-label="Sentry logo"
>
<path
d="M21.85 2.995a3.698 3.698 0 0 1 1.353 1.354l16.303 28.278a3.703 3.703 0 0 1-1.354 5.053 3.694 3.694 0 0 1-1.848.496h-3.828a31.149 31.149 0 0 0 0-3.09h3.815a.61.61 0 0 0 .537-.917L20.523 5.893a.61.61 0 0 0-1.057 0l-3.739 6.494a28.948 28.948 0 0 1 9.63 10.453 28.988 28.988 0 0 1 3.499 13.78v1.542h-9.852v-1.544a19.106 19.106 0 0 0-2.182-8.85 19.08 19.08 0 0 0-6.032-6.829l-1.85 3.208a15.377 15.377 0 0 1 6.382 12.484v1.542H3.696A3.694 3.694 0 0 1 0 34.473c0-.648.17-1.286.494-1.849l2.33-4.074a8.562 8.562 0 0 1 2.689 1.536L3.158 34.17a.611.611 0 0 0 .538.917h8.448a12.481 12.481 0 0 0-6.037-9.09l-1.344-.772 4.908-8.545 1.344.77a22.16 22.16 0 0 1 7.705 7.444 22.193 22.193 0 0 1 3.316 10.193h3.699a25.892 25.892 0 0 0-3.811-12.033 25.856 25.856 0 0 0-9.046-8.796l-1.344-.772 5.269-9.136a3.698 3.698 0 0 1 3.2-1.849c.648 0 1.285.17 1.847.495Z"
fill="currentcolor"
/>
</svg>
<h1>sentry-example-page</h1>
<p className="description">
Click the button below, and view the sample error on the Sentry{" "}
<a
target="_blank"
rel="noopener"
href="https://sudipnext.sentry.io/issues/?project=4511154543919184"
>
Issues Page
</a>
. For more details about setting up Sentry,{" "}
<a
target="_blank"
rel="noopener"
href="https://docs.sentry.io/platforms/javascript/guides/nextjs/"
>
read our docs
</a>
.
</p>
<button
type="button"
onClick={async () => {
Sentry.logger.info("User clicked the button, throwing a sample error");
await Sentry.startSpan(
{
name: "Example Frontend/Backend Span",
op: "test",
},
async () => {
const res = await fetch("/api/sentry-example-api");
if (!res.ok) {
setHasSentError(true);
}
},
);
throw new SentryExampleFrontendError(
"This error is raised on the frontend of the example page.",
);
}}
disabled={!isConnected}
>
<span>Throw Sample Error</span>
</button>
{hasSentError ? (
<p className="success">Error sent to Sentry.</p>
) : !isConnected ? (
<div className="connectivity-error">
<p>
It looks like network requests to Sentry are being blocked, which
will prevent errors from being captured. Try disabling your
ad-blocker to complete the test.
</p>
</div>
) : (
<div className="success_placeholder" />
)}
<div className="flex-spacer" />
</main>
<style>{`
main {
display: flex;
min-height: 100vh;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 16px;
padding: 16px;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
}
h1 {
padding: 0px 4px;
border-radius: 4px;
background-color: rgba(24, 20, 35, 0.03);
font-family: monospace;
font-size: 20px;
line-height: 1.2;
}
p {
margin: 0;
font-size: 20px;
}
a {
color: #6341F0;
text-decoration: underline;
cursor: pointer;
@media (prefers-color-scheme: dark) {
color: #B3A1FF;
}
}
button {
border-radius: 8px;
color: white;
cursor: pointer;
background-color: #553DB8;
border: none;
padding: 0;
margin-top: 4px;
& > span {
display: inline-block;
padding: 12px 16px;
border-radius: inherit;
font-size: 20px;
font-weight: bold;
line-height: 1;
background-color: #7553FF;
border: 1px solid #553DB8;
transform: translateY(-4px);
}
&:hover > span {
transform: translateY(-8px);
}
&:active > span {
transform: translateY(0);
}
&:disabled {
cursor: not-allowed;
opacity: 0.6;
& > span {
transform: translateY(0);
border: none
}
}
}
.description {
text-align: center;
color: #6E6C75;
max-width: 500px;
line-height: 1.5;
font-size: 20px;
@media (prefers-color-scheme: dark) {
color: #A49FB5;
}
}
.flex-spacer {
flex: 1;
}
.success {
padding: 12px 16px;
border-radius: 8px;
font-size: 20px;
line-height: 1;
background-color: #00F261;
border: 1px solid #00BF4D;
color: #181423;
}
.success_placeholder {
height: 46px;
}
.connectivity-error {
padding: 12px 16px;
background-color: #E50045;
border-radius: 8px;
width: 500px;
color: #FFFFFF;
border: 1px solid #A80033;
text-align: center;
margin: 0;
}
.connectivity-error a {
color: #FFFFFF;
text-decoration: underline;
}
`}</style>
</div>
);
}

View file

@ -33,8 +33,6 @@ interface ElectronAPI {
hasRequiredKey: () => Promise<{ hasKey: boolean }>;
telemetryStatus: () => Promise<{ telemetryEnabled: boolean }>;
getTemplates: () => Promise<Array<{ templateName: string; templateID: string; files: string[]; settings: any }>>;
captureSentryRendererTestError: (message?: string) => Promise<string | null> | string | null;
captureSentryMainTestError: (message?: string) => Promise<string | null>;
}
interface Window {