From 5ad3bfc83bfb174f6f3b72e179de6a0cf955f840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D0=B8=D0=B9=20=D0=95=D0=BB?= =?UTF-8?q?=D0=B8=D1=81=D0=B5=D0=B5=D0=B2?= Date: Fri, 5 Jun 2026 18:08:00 +0600 Subject: [PATCH 1/2] feat: integrate sentry --- .gitignore | 3 +- apps/mobile/app.config.ts | 4 + apps/mobile/app/_layout.tsx | 25 ++- apps/mobile/metro.config.js | 4 +- apps/mobile/package.json | 1 + package-lock.json | 308 +++++++++++++++++++++++++++++++++++- package.json | 1 + 7 files changed, 339 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 3aba2de..f611805 100644 --- a/.gitignore +++ b/.gitignore @@ -62,4 +62,5 @@ cache/ eas.json .env.local -.eslintcache \ No newline at end of file +.eslintcache +.env.local diff --git a/apps/mobile/app.config.ts b/apps/mobile/app.config.ts index 1b5d05d..18b6a27 100644 --- a/apps/mobile/app.config.ts +++ b/apps/mobile/app.config.ts @@ -14,6 +14,10 @@ const createConfig = (): Omit & { extra: { eas: EASConfig } const extra = { eas: { projectId } as EASConfig, + sentry: { + dsn: 'https://3ae5dc8126bb61f3f6a582ea697a45d8@o4511502286716928.ingest.us.sentry.io/4511511143579648', + }, + env: appEnv.current, googleIosClientId: appEnv.select({ default: process.env.GOOGLE_IOS_CLIENT_ID_DEV, production: process.env.GOOGLE_IOS_CLIENT_ID_PROD, diff --git a/apps/mobile/app/_layout.tsx b/apps/mobile/app/_layout.tsx index 340eac5..e014b1f 100644 --- a/apps/mobile/app/_layout.tsx +++ b/apps/mobile/app/_layout.tsx @@ -17,9 +17,11 @@ import { useNetworkConnection } from '@open-webui-react-native/shared/features/n import { constants } from '@open-webui-react-native/shared/utils/config'; import { setupReactotron } from '@open-webui-react-native/shared/utils/reactotron'; import { setLanguage } from '@ronas-it/react-native-common-modules/i18n'; +import * as Sentry from '@sentry/react-native'; import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'; +import Constants from 'expo-constants'; import { useFonts } from 'expo-font'; -import { SplashScreen, Stack } from 'expo-router'; +import { SplashScreen, Stack, useNavigationContainerRef } from 'expo-router'; import { ReactElement, useEffect } from 'react'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { KeyboardProvider } from 'react-native-keyboard-controller'; @@ -29,6 +31,16 @@ import 'expo-dev-client'; export { ErrorBoundary } from 'expo-router'; +const reactNavigationIntegration = Sentry.reactNavigationIntegration(); + +Sentry.init({ + dsn: Constants.expoConfig?.extra?.sentry?.dsn, + environment: Constants.expoConfig?.extra?.env, + debug: false, + integrations: [reactNavigationIntegration], + enabled: !__DEV__, +}); + const translations = { [constants.defaultLocale]: { ...require('i18n/mobile/app/en.json'), @@ -85,9 +97,16 @@ function App(): ReactElement | null { ); } -export default function RootLayout(): ReactElement | null { +function RootLayout(): ReactElement | null { useLanguage(constants.defaultLocale); const [isFontsLoaded] = useFonts(fonts); + const navigationContainerRef = useNavigationContainerRef(); + + useEffect(() => { + if (navigationContainerRef) { + reactNavigationIntegration.registerNavigationContainer(navigationContainerRef); + } + }, [navigationContainerRef]); useEffect(() => { if (isFontsLoaded) { @@ -121,3 +140,5 @@ export default function RootLayout(): ReactElement | null { ); } + +export default Sentry.wrap(RootLayout); diff --git a/apps/mobile/metro.config.js b/apps/mobile/metro.config.js index 2610146..94fdd64 100644 --- a/apps/mobile/metro.config.js +++ b/apps/mobile/metro.config.js @@ -1,4 +1,4 @@ -const { getDefaultConfig } = require('@expo/metro-config'); +const { getSentryExpoConfig } = require('@sentry/react-native/metro'); const { withNativeWind } = require('nativewind/metro'); const { withNxMetro } = require('@nx/expo'); const { mergeConfig } = require('metro-config'); @@ -6,7 +6,7 @@ const path = require('path'); const appRoot = __dirname; const monorepoRoot = path.resolve(appRoot, '../..'); -const defaultConfig = getDefaultConfig(appRoot); +const defaultConfig = getSentryExpoConfig(appRoot); const { assetExts, sourceExts } = defaultConfig.resolver; /** * Metro configuration diff --git a/apps/mobile/package.json b/apps/mobile/package.json index dda6470..dd477be 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -32,6 +32,7 @@ "@react-navigation/drawer": "^7.3.9", "@ronas-it/react-native-common-modules": "^1.1.0", "@ronas-it/rtkq-entity-api": "^0.4.10", + "@sentry/react-native": "~7.11.0", "@shopify/flash-list": "2.0.2", "@tanstack/react-query": "^5.80.6", "@tanstack/react-query-persist-client": "^5.87.4", diff --git a/package-lock.json b/package-lock.json index bacde44..f8027f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "@ronas-it/axios-api-client": "^0.1.2", "@ronas-it/react-native-common-modules": "^1.1.0", "@ronas-it/rtkq-entity-api": "^0.4.10", + "@sentry/react-native": "~7.11.0", "@shopify/flash-list": "2.0.2", "@tanstack/react-query": "^5.80.6", "@tanstack/react-query-persist-client": "^5.87.4", @@ -169,6 +170,7 @@ "@react-navigation/drawer": "^7.3.9", "@ronas-it/react-native-common-modules": "^1.1.0", "@ronas-it/rtkq-entity-api": "^0.4.10", + "@sentry/react-native": "~7.11.0", "@shopify/flash-list": "2.0.2", "@tanstack/react-query": "^5.80.6", "@tanstack/react-query-persist-client": "^5.87.4", @@ -8664,6 +8666,310 @@ "join-component": "^1.1.0" } }, + "node_modules/@sentry-internal/browser-utils": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.37.0.tgz", + "integrity": "sha512-rqdESYaVio9Ktz55lhUhtBsBUCF3wvvJuWia5YqoHDd+egyIfwWxITTAa0TSEyZl7283A4WNHNl0hyeEMblmfA==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.37.0.tgz", + "integrity": "sha512-P0PVlfrDvfvCYg2KPIS7YUG/4i6ZPf8z1MicXx09C9Cz9W9UhSBh/nii13eBdDtLav2BFMKhvaFMcghXHX03Hw==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.37.0.tgz", + "integrity": "sha512-snuk12ZaDerxesSnetNIwKoth/51R0y/h3eXD/bGtXp+hnSkeXN5HanI/RJl297llRjn4zJYRShW9Nx86Ay0Dw==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "10.37.0", + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.37.0.tgz", + "integrity": "sha512-PyIYSbjLs+L5essYV0MyIsh4n5xfv2eV7l0nhUoPJv9Bak3kattQY3tholOj0EP3SgKgb+8HSZnmazgF++Hbog==", + "license": "MIT", + "dependencies": { + "@sentry-internal/replay": "10.37.0", + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/babel-plugin-component-annotate": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-4.8.0.tgz", + "integrity": "sha512-cy/9Eipkv23MsEJ4IuB4dNlVwS9UqOzI3Eu+QPake5BVFgPYCX0uP0Tr3Z43Ime6Rb+BiDnWC51AJK9i9afHYw==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/browser": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.37.0.tgz", + "integrity": "sha512-kheqJNqGZP5TSBCPv4Vienv1sfZwXKHQDYR+xrdHHYdZqwWuZMJJW/cLO9XjYAe+B9NnJ4UwJOoY4fPvU+HQ1Q==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "10.37.0", + "@sentry-internal/feedback": "10.37.0", + "@sentry-internal/replay": "10.37.0", + "@sentry-internal/replay-canvas": "10.37.0", + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/cli": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.58.4.tgz", + "integrity": "sha512-ArDrpuS8JtDYEvwGleVE+FgR+qHaOp77IgdGSacz6SZy6Lv90uX0Nu4UrHCQJz8/xwIcNxSqnN22lq0dH4IqTg==", + "hasInstallScript": true, + "license": "FSL-1.1-MIT", + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.58.4", + "@sentry/cli-linux-arm": "2.58.4", + "@sentry/cli-linux-arm64": "2.58.4", + "@sentry/cli-linux-i686": "2.58.4", + "@sentry/cli-linux-x64": "2.58.4", + "@sentry/cli-win32-arm64": "2.58.4", + "@sentry/cli-win32-i686": "2.58.4", + "@sentry/cli-win32-x64": "2.58.4" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.58.4.tgz", + "integrity": "sha512-kbTD+P4X8O+nsNwPxCywtj3q22ecyRHWff98rdcmtRrvwz8CKi/T4Jxn/fnn2i4VEchy08OWBuZAqaA5Kh2hRQ==", + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.58.4.tgz", + "integrity": "sha512-rdQ8beTwnN48hv7iV7e7ZKucPec5NJkRdrrycMJMZlzGBPi56LqnclgsHySJ6Kfq506A2MNuQnKGaf/sBC9REA==", + "cpu": [ + "arm" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.58.4.tgz", + "integrity": "sha512-0g0KwsOozkLtzN8/0+oMZoOuQ0o7W6O+hx+ydVU1bktaMGKEJLMAWxOQNjsh1TcBbNIXVOKM/I8l0ROhaAb8Ig==", + "cpu": [ + "arm64" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.58.4.tgz", + "integrity": "sha512-NseoIQAFtkziHyjZNPTu1Gm1opeQHt7Wm1LbLrGWVIRvUOzlslO9/8i6wETUZ6TjlQxBVRgd3Q0lRBG2A8rFYA==", + "cpu": [ + "x86", + "ia32" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.58.4.tgz", + "integrity": "sha512-d3Arz+OO/wJYTqCYlSN3Ktm+W8rynQ/IMtSZLK8nu0ryh5mJOh+9XlXY6oDXw4YlsM8qCRrNquR8iEI1Y/IH+Q==", + "cpu": [ + "x64" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-arm64": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.58.4.tgz", + "integrity": "sha512-bqYrF43+jXdDBh0f8HIJU3tbvlOFtGyRjHB8AoRuMQv9TEDUfENZyCelhdjA+KwDKYl48R1Yasb4EHNzsoO83w==", + "cpu": [ + "arm64" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.58.4.tgz", + "integrity": "sha512-3triFD6jyvhVcXOmGyttf+deKZcC1tURdhnmDUIBkiDPJKGT/N5xa4qAtHJlAB/h8L9jgYih9bvJnvvFVM7yug==", + "cpu": [ + "x86", + "ia32" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-x64": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.58.4.tgz", + "integrity": "sha512-cSzN4PjM1RsCZ4pxMjI0VI7yNCkxiJ5jmWncyiwHXGiXrV1eXYdQ3n1LhUYLZ91CafyprR0OhDcE+RVZ26Qb5w==", + "cpu": [ + "x64" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/core": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.37.0.tgz", + "integrity": "sha512-hkRz7S4gkKLgPf+p3XgVjVm7tAfvcEPZxeACCC6jmoeKhGkzN44nXwLiqqshJ25RMcSrhfFvJa/FlBg6zupz7g==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/react": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.37.0.tgz", + "integrity": "sha512-XLnXJOHgsCeVAVBbO+9AuGlZWnCxLQHLOmKxpIr8wjE3g7dHibtug6cv8JLx78O4dd7aoCqv2TTyyKY9FLJ2EQ==", + "license": "MIT", + "dependencies": { + "@sentry/browser": "10.37.0", + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^16.14.0 || 17.x || 18.x || 19.x" + } + }, + "node_modules/@sentry/react-native": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@sentry/react-native/-/react-native-7.11.0.tgz", + "integrity": "sha512-OiDaLCAGpRN18YG/o7IIwLhU0Xpb0tYKQ5QxkGHiwb+L3VHn+MqGCGfITYNdhqr06HHMvu9Lysm+UJxaNmGaJg==", + "license": "MIT", + "dependencies": { + "@sentry/babel-plugin-component-annotate": "4.8.0", + "@sentry/browser": "10.37.0", + "@sentry/cli": "2.58.4", + "@sentry/core": "10.37.0", + "@sentry/react": "10.37.0", + "@sentry/types": "10.37.0" + }, + "bin": { + "sentry-expo-upload-sourcemaps": "scripts/expo-upload-sourcemaps.js" + }, + "peerDependencies": { + "expo": ">=49.0.0", + "react": ">=17.0.0", + "react-native": ">=0.65.0" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true + } + } + }, + "node_modules/@sentry/types": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-10.37.0.tgz", + "integrity": "sha512-umpnUKRC0AAbJrADg6SlFtqN2yzf7NHciCF9lkHau+ax2PIZ/NDmoG4RQujFVflVaVoD60Ly2t+CcPnYIWMPlw==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@shopify/flash-list": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@shopify/flash-list/-/flash-list-2.0.2.tgz", @@ -10933,7 +11239,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, "license": "MIT", "dependencies": { "debug": "4" @@ -19311,7 +19616,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "6", diff --git a/package.json b/package.json index a5b795e..81450d9 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "@ronas-it/axios-api-client": "^0.1.2", "@ronas-it/react-native-common-modules": "^1.1.0", "@ronas-it/rtkq-entity-api": "^0.4.10", + "@sentry/react-native": "~7.11.0", "@shopify/flash-list": "2.0.2", "@tanstack/react-query": "^5.80.6", "@tanstack/react-query-persist-client": "^5.87.4", From 5ddc2ff8d51fb9971ff9038997af126f21e475d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D0=B8=D0=B9=20=D0=95=D0=BB?= =?UTF-8?q?=D0=B8=D1=81=D0=B5=D0=B5=D0=B2?= Date: Fri, 5 Jun 2026 18:17:29 +0600 Subject: [PATCH 2/2] chore: move sentry dsn to env --- apps/mobile/.env.template | 3 ++- apps/mobile/app.config.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/mobile/.env.template b/apps/mobile/.env.template index fd1fa7c..3177b72 100644 --- a/apps/mobile/.env.template +++ b/apps/mobile/.env.template @@ -5,4 +5,5 @@ EXPO_PUBLIC_APP_OWNER= EXPO_PIBLIC_APP_SCHEME= EXPO_PUBLIC_APP_NAME= EXPO_PUBLIC_APP_SLUG= -EXPO_PUBLIC_IS_INTERNAL_RELEASE= \ No newline at end of file +EXPO_PUBLIC_IS_INTERNAL_RELEASE= +SENTRY_DSN= \ No newline at end of file diff --git a/apps/mobile/app.config.ts b/apps/mobile/app.config.ts index 18b6a27..426915d 100644 --- a/apps/mobile/app.config.ts +++ b/apps/mobile/app.config.ts @@ -15,7 +15,7 @@ const createConfig = (): Omit & { extra: { eas: EASConfig } const extra = { eas: { projectId } as EASConfig, sentry: { - dsn: 'https://3ae5dc8126bb61f3f6a582ea697a45d8@o4511502286716928.ingest.us.sentry.io/4511511143579648', + dsn: process.env.SENTRY_DSN, }, env: appEnv.current, googleIosClientId: appEnv.select({