Skip to content

Commit 0da9f20

Browse files
authored
feat: migrate desktop/mobile error tracking to posthog (#4858)
* feat: migrate desktop and mobile error tracking to PostHog * fix(mobile): remove unsupported tab bar minimize API * Revert "fix(mobile): remove unsupported tab bar minimize API" This reverts commit e234dda.
1 parent 47a56c5 commit 0da9f20

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+171
-1399
lines changed

apps/desktop/configs/vite.render.config.ts

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { readFileSync } from "node:fs"
22
import { fileURLToPath } from "node:url"
33

4-
import { sentryVitePlugin } from "@sentry/vite-plugin"
54
import react from "@vitejs/plugin-react"
65
import { codeInspectorPlugin } from "code-inspector-plugin"
76
import { dirname, resolve } from "pathe"
@@ -17,9 +16,6 @@ import i18nCompleteness from "../plugins/vite/utils/i18n-completeness"
1716

1817
const pkgDir = resolve(dirname(fileURLToPath(import.meta.url)), "..")
1918
const pkg = JSON.parse(readFileSync(resolve(pkgDir, "./package.json"), "utf8"))
20-
const isCI = process.env.CI === "true" || process.env.CI === "1"
21-
const mode = process.argv.find((arg) => arg.startsWith("--mode"))?.split("=")[1]
22-
const isStaging = mode === "staging"
2319

2420
const getChangelogFileContent = () => {
2521
const { version: pkgVersion } = pkg
@@ -76,36 +72,6 @@ export const viteRenderBaseConfig = {
7672
}),
7773
circularImportRefreshPlugin(),
7874

79-
sentryVitePlugin({
80-
org: "follow-rg",
81-
project: "follow",
82-
disable: !isCI,
83-
bundleSizeOptimizations: {
84-
excludeDebugStatements: true,
85-
86-
// Only relevant if you added `replayIntegration`
87-
excludeReplayIframe: true,
88-
excludeReplayShadowDom: true,
89-
excludeReplayWorker: true,
90-
},
91-
moduleMetadata: {
92-
appVersion: process.env.NODE_ENV === "development" ? "dev" : pkg.version,
93-
electron: false,
94-
},
95-
sourcemaps: {
96-
filesToDeleteAfterUpload: isStaging
97-
? []
98-
: [
99-
"out/web/assets/*.js.map",
100-
"out/web/vendor/*.js.map",
101-
"out/rn-web/assets/*.js.map",
102-
"out/rn-web/vendor/*.js.map",
103-
"dist/renderer/assets/*.js.map",
104-
"dist/renderer/vendor/*.css.map",
105-
],
106-
},
107-
}),
108-
10975
astPlugin,
11076
customI18nHmrPlugin(),
11177
],

apps/desktop/layer/main/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
"@follow/shared": "workspace:*",
2929
"@follow/utils": "workspace:*",
3030
"@openpanel/web": "1.0.7",
31-
"@sentry/electron": "7.2.0",
3231
"builder-util-runtime": "9.5.1",
3332
"electron-context-menu": "4.1.1",
3433
"electron-ipc-decorator": "0.2.0",
Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
import { app, protocol } from "electron"
22
import path from "pathe"
33

4-
import { initializeSentry } from "./sentry"
5-
64
if (import.meta.env.DEV) app.setPath("userData", path.join(app.getPath("appData"), "Folo(dev)"))
75
protocol.registerSchemesAsPrivileged([
8-
{
9-
scheme: "sentry-ipc",
10-
privileges: { bypassCSP: true, corsEnabled: true, supportFetchAPI: true, secure: true },
11-
},
126
{
137
scheme: "app",
148
privileges: {
@@ -19,5 +13,3 @@ protocol.registerSchemesAsPrivileged([
1913
},
2014
},
2115
])
22-
// Solve Sentry SDK should be initialized before the Electron app 'ready' event is fired
23-
initializeSentry()

apps/desktop/layer/main/src/sentry.ts

Lines changed: 0 additions & 41 deletions
This file was deleted.

apps/desktop/layer/renderer/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
"@radix-ui/react-popover": "1.1.15",
3939
"@radix-ui/react-slider": "1.3.6",
4040
"@radix-ui/react-slot": "1.2.4",
41-
"@sentry/react": "10.38.0",
4241
"@shikijs/transformers": "3.22.0",
4342
"@splinetool/react-spline": "4.1.0",
4443
"@tanstack/query-sync-storage-persister": "5.90.22",
@@ -88,6 +87,7 @@
8887
"react": "19.0.0",
8988
"react-blurhash": "0.3.0",
9089
"react-dom": "19.0.0",
90+
"react-error-boundary": "6.1.0",
9191
"react-fast-compare": "3.2.2",
9292
"react-fast-marquee": "1.6.5",
9393
"react-google-recaptcha-v3": "1.11.0",

apps/desktop/layer/renderer/src/components/common/AppErrorBoundary.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import type { FallbackRender } from "@sentry/react"
2-
import { ErrorBoundary } from "@sentry/react"
31
import type { FC, PropsWithChildren } from "react"
42
import { createElement, Suspense, useCallback } from "react"
53

64
import { getErrorFallback } from "../errors"
75
import type { ErrorComponentType } from "../errors/enum"
86
import PageErrorFallback from "../errors/PageError"
7+
import type { FallbackRender } from "./ErrorBoundary"
8+
import { ErrorBoundary } from "./ErrorBoundary"
99

1010
export interface AppErrorBoundaryProps extends PropsWithChildren {
1111
height?: number | string
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { tracker } from "@follow/tracker"
2+
import type { PropsWithChildren, ReactNode } from "react"
3+
import type { FallbackProps } from "react-error-boundary"
4+
import { ErrorBoundary as ReactErrorBoundary } from "react-error-boundary"
5+
6+
export type ErrorFallbackProps = Omit<FallbackProps, "resetErrorBoundary"> &
7+
FallbackProps & {
8+
resetError: () => void
9+
}
10+
export type FallbackRender = (props: ErrorFallbackProps) => ReactNode
11+
12+
interface ErrorBoundaryProps extends PropsWithChildren {
13+
fallback?: FallbackRender
14+
fallbackRender?: FallbackRender
15+
handled?: boolean
16+
beforeCapture?: (scope: unknown, error: unknown) => unknown
17+
}
18+
19+
const emptyFallback: FallbackRender = () => null
20+
21+
export const ErrorBoundary = ({
22+
children,
23+
fallback,
24+
fallbackRender,
25+
beforeCapture,
26+
}: ErrorBoundaryProps) => {
27+
const renderFallback = fallbackRender ?? fallback ?? emptyFallback
28+
29+
const handleError = (rawError: unknown, info: { componentStack?: string | null }) => {
30+
const error = rawError instanceof Error ? rawError : new Error(String(rawError))
31+
32+
if (beforeCapture?.(info, error) === false) {
33+
return
34+
}
35+
36+
void tracker.manager.captureException(error, {
37+
source: "desktop_error_boundary",
38+
component_stack: info.componentStack,
39+
})
40+
}
41+
42+
return (
43+
<ReactErrorBoundary
44+
onError={handleError}
45+
fallbackRender={(props) =>
46+
renderFallback({
47+
...props,
48+
resetError: props.resetErrorBoundary,
49+
})
50+
}
51+
>
52+
{children}
53+
</ReactErrorBoundary>
54+
)
55+
}

apps/desktop/layer/renderer/src/components/common/ErrorElement.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Button } from "@follow/components/ui/button/index.js"
2-
import { captureException } from "@sentry/react"
2+
import { tracker } from "@follow/tracker"
33
import { useEffect, useRef } from "react"
44
import { isRouteErrorResponse, useNavigate, useRouteError } from "react-router"
55
import { toast } from "sonner"
@@ -27,8 +27,9 @@ export function ErrorElement() {
2727

2828
useEffect(() => {
2929
console.error("Error handled by React Router default ErrorBoundary:", error)
30-
31-
captureException(error)
30+
void tracker.manager.captureException(error, {
31+
source: "desktop_router_error_element",
32+
})
3233
}, [error])
3334

3435
const reloadRef = useRef(false)

apps/desktop/layer/renderer/src/components/common/NotFound.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Logo } from "@follow/components/icons/logo.jsx"
22
import { Button } from "@follow/components/ui/button/index.js"
33
import { ELECTRON_BUILD } from "@follow/shared/constants"
4-
import { captureException } from "@sentry/react"
54
import { useEffect } from "react"
65
import type { Location } from "react-router"
76
import { Navigate, useLocation, useNavigate } from "react-router"
@@ -33,7 +32,7 @@ export const NotFound = () => {
3332
if (!ELECTRON_BUILD) {
3433
return
3534
}
36-
captureException(
35+
console.error(
3736
new AccessNotFoundError(
3837
"Electron app got to a 404 page, this should not happen",
3938
location.pathname,

apps/desktop/layer/renderer/src/components/ui/markdown/renderers/BlockErrorBoundary.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
import { captureException } from "@sentry/react"
1+
import { tracker } from "@follow/tracker"
22
import { useEffect } from "react"
33

44
export const BlockError = (props: { error: any; message: string }) => {
55
useEffect(() => {
6-
captureException(props.error)
7-
}, [])
6+
console.error(props.error)
7+
void tracker.manager.captureException(props.error, {
8+
source: "desktop_markdown_block_error",
9+
message: props.message,
10+
})
11+
}, [props.error, props.message])
812
return (
913
<div className="center flex min-h-12 flex-col rounded bg-red py-4 text-sm text-white">
1014
{props.message}

0 commit comments

Comments
 (0)