Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
67 lines
1.7 KiB
TypeScript
67 lines
1.7 KiB
TypeScript
'use client'
|
|
|
|
import * as Sentry from '@sentry/nextjs'
|
|
|
|
interface BrowserEvent {
|
|
name: string
|
|
level?: 'info' | 'warning' | 'error'
|
|
attributes?: Record<string, string | number | boolean | null | undefined>
|
|
}
|
|
|
|
const endpoint = process.env.NEXT_PUBLIC_OBSERVABILITY_ENDPOINT
|
|
|
|
function sendBeacon(name: string, level: BrowserEvent['level'], attributes: BrowserEvent['attributes']) {
|
|
if (!endpoint || typeof navigator === 'undefined') return false
|
|
|
|
const payload = JSON.stringify({
|
|
name,
|
|
level,
|
|
attributes,
|
|
route: typeof location === 'undefined' ? undefined : location.pathname,
|
|
release: process.env.NEXT_PUBLIC_APP_VERSION,
|
|
timestamp: new Date().toISOString(),
|
|
})
|
|
|
|
return navigator.sendBeacon(endpoint, new Blob([payload], { type: 'application/json' }))
|
|
}
|
|
|
|
export const reportBrowserEvent = ({ name, level = 'info', attributes = {} }: BrowserEvent) => {
|
|
if (level === 'error') {
|
|
Sentry.captureMessage(name, {
|
|
level: 'error',
|
|
extra: {
|
|
...attributes,
|
|
route: typeof location === 'undefined' ? undefined : location.pathname,
|
|
},
|
|
})
|
|
} else if (level === 'warning') {
|
|
Sentry.captureMessage(name, {
|
|
level: 'warning',
|
|
extra: attributes,
|
|
})
|
|
} else {
|
|
Sentry.addBreadcrumb({
|
|
category: 'browser',
|
|
message: name,
|
|
level: 'info',
|
|
data: attributes,
|
|
})
|
|
}
|
|
|
|
return sendBeacon(name, level, attributes)
|
|
}
|
|
|
|
export const reportClientError = (error: Error & { digest?: string }, boundary: string) => {
|
|
Sentry.captureException(error, {
|
|
tags: { boundary },
|
|
extra: { digest: error.digest },
|
|
})
|
|
|
|
return sendBeacon('client_error', 'error', {
|
|
boundary,
|
|
digest: error.digest,
|
|
errorName: error.name,
|
|
message: error.message.slice(0, 300),
|
|
})
|
|
}
|