'use client' import * as Sentry from '@sentry/nextjs' interface BrowserEvent { name: string level?: 'info' | 'warning' | 'error' attributes?: Record } 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), }) }