mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 13:02:07 +03:00
Sentry React integration (#8086)
- Closes https://github.com/enso-org/cloud-v2/issues/720 - Integrate Sentry with React and React Router. # Important Notes This is currently BROKEN as it requires the Sentry DSN, otherwise no requests are part of a transaction. Not sure how feasible this is unfortunately, especially as (I'm assuming) it will be different for each backend... ... I guess worst case it can be configured via an environment variable like some other build-time defines. Also the sampling rates should be checked.
This commit is contained in:
parent
00341cd89b
commit
8e20fc66dc
@ -17,6 +17,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@heroicons/react": "^2.0.15",
|
"@heroicons/react": "^2.0.15",
|
||||||
|
"@sentry/react": "^7.74.0",
|
||||||
"@types/node": "^18.17.5",
|
"@types/node": "^18.17.5",
|
||||||
"@types/react": "^18.0.27",
|
"@types/react": "^18.0.27",
|
||||||
"@types/react-dom": "^18.0.10",
|
"@types/react-dom": "^18.0.10",
|
||||||
|
@ -7,6 +7,8 @@ import * as React from 'react'
|
|||||||
import * as router from 'react-router-dom'
|
import * as router from 'react-router-dom'
|
||||||
import * as toast from 'react-toastify'
|
import * as toast from 'react-toastify'
|
||||||
|
|
||||||
|
import * as sentry from '@sentry/react'
|
||||||
|
|
||||||
import * as app from '../../components/app'
|
import * as app from '../../components/app'
|
||||||
import type * as authServiceModule from '../service'
|
import type * as authServiceModule from '../service'
|
||||||
import * as backendModule from '../../dashboard/backend'
|
import * as backendModule from '../../dashboard/backend'
|
||||||
@ -201,6 +203,7 @@ export function AuthProvider(props: AuthProviderProps) {
|
|||||||
|
|
||||||
const goOfflineInternal = React.useCallback(() => {
|
const goOfflineInternal = React.useCallback(() => {
|
||||||
setInitialized(true)
|
setInitialized(true)
|
||||||
|
sentry.setUser(null)
|
||||||
setUserSession(OFFLINE_USER_SESSION)
|
setUserSession(OFFLINE_USER_SESSION)
|
||||||
if (supportsLocalBackend) {
|
if (supportsLocalBackend) {
|
||||||
setBackendWithoutSavingType(new localBackend.LocalBackend(projectManagerUrl))
|
setBackendWithoutSavingType(new localBackend.LocalBackend(projectManagerUrl))
|
||||||
@ -253,6 +256,7 @@ export function AuthProvider(props: AuthProviderProps) {
|
|||||||
} else if (session == null) {
|
} else if (session == null) {
|
||||||
setInitialized(true)
|
setInitialized(true)
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
|
sentry.setUser(null)
|
||||||
setUserSession(null)
|
setUserSession(null)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -307,11 +311,19 @@ export function AuthProvider(props: AuthProviderProps) {
|
|||||||
}
|
}
|
||||||
let newUserSession: UserSession
|
let newUserSession: UserSession
|
||||||
if (organization == null) {
|
if (organization == null) {
|
||||||
|
sentry.setUser({ email: session.email })
|
||||||
newUserSession = {
|
newUserSession = {
|
||||||
type: UserSessionType.partial,
|
type: UserSessionType.partial,
|
||||||
...session,
|
...session,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
sentry.setUser({
|
||||||
|
id: organization.id,
|
||||||
|
email: organization.email,
|
||||||
|
username: organization.name,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
|
ip_address: '{{auto}}',
|
||||||
|
})
|
||||||
newUserSession = {
|
newUserSession = {
|
||||||
type: UserSessionType.full,
|
type: UserSessionType.full,
|
||||||
...session,
|
...session,
|
||||||
@ -493,6 +505,7 @@ export function AuthProvider(props: AuthProviderProps) {
|
|||||||
const signOut = async () => {
|
const signOut = async () => {
|
||||||
deinitializeSession()
|
deinitializeSession()
|
||||||
setInitialized(false)
|
setInitialized(false)
|
||||||
|
sentry.setUser(null)
|
||||||
setUserSession(null)
|
setUserSession(null)
|
||||||
localStorage.clearUserSpecificEntries()
|
localStorage.clearUserSpecificEntries()
|
||||||
// This should not omit success and error toasts as it is not possible
|
// This should not omit success and error toasts as it is not possible
|
||||||
|
@ -3,10 +3,14 @@
|
|||||||
* This module declares the main DOM structure for the authentication/dashboard app. */
|
* This module declares the main DOM structure for the authentication/dashboard app. */
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import * as reactDOM from 'react-dom/client'
|
import * as reactDOM from 'react-dom/client'
|
||||||
|
import * as reactRouter from 'react-router-dom'
|
||||||
|
|
||||||
|
import * as sentry from '@sentry/react'
|
||||||
|
|
||||||
import * as detect from 'enso-common/src/detect'
|
import * as detect from 'enso-common/src/detect'
|
||||||
|
|
||||||
import type * as app from './components/app'
|
import type * as app from './components/app'
|
||||||
|
import * as config from './config'
|
||||||
import App from './components/app'
|
import App from './components/app'
|
||||||
|
|
||||||
// =================
|
// =================
|
||||||
@ -15,6 +19,8 @@ import App from './components/app'
|
|||||||
|
|
||||||
/** The `id` attribute of the root element that the app will be rendered into. */
|
/** The `id` attribute of the root element that the app will be rendered into. */
|
||||||
const ROOT_ELEMENT_ID = 'enso-dashboard'
|
const ROOT_ELEMENT_ID = 'enso-dashboard'
|
||||||
|
/** The fraction of non-erroring interactions that should be sampled by Sentry. */
|
||||||
|
const SENTRY_SAMPLE_RATE = 0.005
|
||||||
|
|
||||||
// ===========
|
// ===========
|
||||||
// === run ===
|
// === run ===
|
||||||
@ -31,6 +37,26 @@ export // This export declaration must be broken up to satisfy the `require-jsdo
|
|||||||
function run(props: app.AppProps) {
|
function run(props: app.AppProps) {
|
||||||
const { logger, supportsDeepLinks } = props
|
const { logger, supportsDeepLinks } = props
|
||||||
logger.log('Starting authentication/dashboard UI.')
|
logger.log('Starting authentication/dashboard UI.')
|
||||||
|
sentry.init({
|
||||||
|
dsn: 'https://0dc7cb80371f466ab88ed01739a7822f@o4504446218338304.ingest.sentry.io/4506070404300800',
|
||||||
|
environment: config.ENVIRONMENT,
|
||||||
|
integrations: [
|
||||||
|
new sentry.BrowserTracing({
|
||||||
|
routingInstrumentation: sentry.reactRouterV6Instrumentation(
|
||||||
|
React.useEffect,
|
||||||
|
reactRouter.useLocation,
|
||||||
|
reactRouter.useNavigationType,
|
||||||
|
reactRouter.createRoutesFromChildren,
|
||||||
|
reactRouter.matchRoutes
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
new sentry.Replay(),
|
||||||
|
],
|
||||||
|
tracesSampleRate: SENTRY_SAMPLE_RATE,
|
||||||
|
tracePropagationTargets: [config.ACTIVE_CONFIG.apiUrl.split('//')[1] ?? ''],
|
||||||
|
replaysSessionSampleRate: SENTRY_SAMPLE_RATE,
|
||||||
|
replaysOnErrorSampleRate: 1.0,
|
||||||
|
})
|
||||||
/** The root element into which the authentication/dashboard app will be rendered. */
|
/** The root element into which the authentication/dashboard app will be rendered. */
|
||||||
const root = document.getElementById(ROOT_ELEMENT_ID)
|
const root = document.getElementById(ROOT_ELEMENT_ID)
|
||||||
if (root == null) {
|
if (root == null) {
|
||||||
@ -40,13 +66,15 @@ function run(props: app.AppProps) {
|
|||||||
// via the browser.
|
// via the browser.
|
||||||
const actuallySupportsDeepLinks = supportsDeepLinks && detect.isOnElectron()
|
const actuallySupportsDeepLinks = supportsDeepLinks && detect.isOnElectron()
|
||||||
reactDOM.createRoot(root).render(
|
reactDOM.createRoot(root).render(
|
||||||
detect.IS_DEV_MODE ? (
|
<sentry.ErrorBoundary>
|
||||||
<React.StrictMode>
|
{detect.IS_DEV_MODE ? (
|
||||||
<App {...props} />
|
<React.StrictMode>
|
||||||
</React.StrictMode>
|
<App {...props} />
|
||||||
) : (
|
</React.StrictMode>
|
||||||
<App {...props} supportsDeepLinks={actuallySupportsDeepLinks} />
|
) : (
|
||||||
)
|
<App {...props} supportsDeepLinks={actuallySupportsDeepLinks} />
|
||||||
|
)}
|
||||||
|
</sentry.ErrorBoundary>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
99
package-lock.json
generated
99
package-lock.json
generated
@ -237,6 +237,7 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@heroicons/react": "^2.0.15",
|
"@heroicons/react": "^2.0.15",
|
||||||
|
"@sentry/react": "^7.74.0",
|
||||||
"@types/node": "^18.17.5",
|
"@types/node": "^18.17.5",
|
||||||
"@types/react": "^18.0.27",
|
"@types/react": "^18.0.27",
|
||||||
"@types/react-dom": "^18.0.10",
|
"@types/react-dom": "^18.0.10",
|
||||||
@ -3261,6 +3262,96 @@
|
|||||||
"npm": ">=7.0.0"
|
"npm": ">=7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@sentry-internal/tracing": {
|
||||||
|
"version": "7.77.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.77.0.tgz",
|
||||||
|
"integrity": "sha512-8HRF1rdqWwtINqGEdx8Iqs9UOP/n8E0vXUu3Nmbqj4p5sQPA7vvCfq+4Y4rTqZFc7sNdFpDsRION5iQEh8zfZw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry/core": "7.77.0",
|
||||||
|
"@sentry/types": "7.77.0",
|
||||||
|
"@sentry/utils": "7.77.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sentry/browser": {
|
||||||
|
"version": "7.77.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.77.0.tgz",
|
||||||
|
"integrity": "sha512-nJ2KDZD90H8jcPx9BysQLiQW+w7k7kISCWeRjrEMJzjtge32dmHA8G4stlUTRIQugy5F+73cOayWShceFP7QJQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry-internal/tracing": "7.77.0",
|
||||||
|
"@sentry/core": "7.77.0",
|
||||||
|
"@sentry/replay": "7.77.0",
|
||||||
|
"@sentry/types": "7.77.0",
|
||||||
|
"@sentry/utils": "7.77.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sentry/core": {
|
||||||
|
"version": "7.77.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.77.0.tgz",
|
||||||
|
"integrity": "sha512-Tj8oTYFZ/ZD+xW8IGIsU6gcFXD/gfE+FUxUaeSosd9KHwBQNOLhZSsYo/tTVf/rnQI/dQnsd4onPZLiL+27aTg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry/types": "7.77.0",
|
||||||
|
"@sentry/utils": "7.77.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sentry/react": {
|
||||||
|
"version": "7.77.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.77.0.tgz",
|
||||||
|
"integrity": "sha512-Q+htKzib5em0MdaQZMmPomaswaU3xhcVqmLi2CxqQypSjbYgBPPd+DuhrXKoWYLDDkkbY2uyfe4Lp3yLRWeXYw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry/browser": "7.77.0",
|
||||||
|
"@sentry/types": "7.77.0",
|
||||||
|
"@sentry/utils": "7.77.0",
|
||||||
|
"hoist-non-react-statics": "^3.3.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "15.x || 16.x || 17.x || 18.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sentry/replay": {
|
||||||
|
"version": "7.77.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.77.0.tgz",
|
||||||
|
"integrity": "sha512-M9Ik2J5ekl+C1Och3wzLRZVaRGK33BlnBwfwf3qKjgLDwfKW+1YkwDfTHbc2b74RowkJbOVNcp4m8ptlehlSaQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry-internal/tracing": "7.77.0",
|
||||||
|
"@sentry/core": "7.77.0",
|
||||||
|
"@sentry/types": "7.77.0",
|
||||||
|
"@sentry/utils": "7.77.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sentry/types": {
|
||||||
|
"version": "7.77.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.77.0.tgz",
|
||||||
|
"integrity": "sha512-nfb00XRJVi0QpDHg+JkqrmEBHsqBnxJu191Ded+Cs1OJ5oPXEW6F59LVcBScGvMqe+WEk1a73eH8XezwfgrTsA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sentry/utils": {
|
||||||
|
"version": "7.77.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.77.0.tgz",
|
||||||
|
"integrity": "sha512-NmM2kDOqVchrey3N5WSzdQoCsyDkQkiRxExPaNI2oKQ/jMWHs9yt0tSy7otPBcXs0AP59ihl75Bvm1tDRcsp5g==",
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry/types": "7.77.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@sinclair/typebox": {
|
"node_modules/@sinclair/typebox": {
|
||||||
"version": "0.27.8",
|
"version": "0.27.8",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@ -9713,6 +9804,14 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hoist-non-react-statics": {
|
||||||
|
"version": "3.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
||||||
|
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
|
||||||
|
"dependencies": {
|
||||||
|
"react-is": "^16.7.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hosted-git-info": {
|
"node_modules/hosted-git-info": {
|
||||||
"version": "2.8.9",
|
"version": "2.8.9",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
Loading…
Reference in New Issue
Block a user