mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
fix(edge): fire-and-forget Sentry, 2s timeout, response check (#2559)
* fix(edge): fire-and-forget Sentry reporting, add 2s timeout and response check - Remove await from captureEdgeException call sites so Sentry never blocks the response path when already on an error - Add AbortSignal.timeout(2000) to bound latency on Sentry outage or slow edge egress - Check response.ok and emit console.warn on non-2xx so misconfigured DSN or auth key is diagnosable rather than silently missing * fix(sentry): add allowUrls to block DSN pollution from foreign origins A foreign app (conservation-dash.web.app, biosentinel@2.4.0) was sending errors to our Sentry project by reusing the public DSN. allowUrls drops events from non-worldmonitor origins at the SDK level before ingestion. * fix(edge): void fire-and-forget calls, improve non-2xx Sentry diagnostics
This commit is contained in:
@@ -28,8 +28,9 @@ export async function captureEdgeException(err, context = {}) {
|
||||
const errMsg = err instanceof Error ? err.message : String(err);
|
||||
const errType = err instanceof Error ? err.constructor.name : 'Error';
|
||||
try {
|
||||
await fetch(_storeUrl, {
|
||||
const res = await fetch(_storeUrl, {
|
||||
method: 'POST',
|
||||
signal: AbortSignal.timeout(2000),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Sentry-Auth': `Sentry sentry_version=7, sentry_key=${_key}`,
|
||||
@@ -45,5 +46,15 @@ export async function captureEdgeException(err, context = {}) {
|
||||
tags: { runtime: 'edge' },
|
||||
}),
|
||||
});
|
||||
} catch {}
|
||||
if (!res.ok) {
|
||||
const hint = res.status === 401 || res.status === 403
|
||||
? ' — check VITE_SENTRY_DSN and auth key'
|
||||
: res.status === 429
|
||||
? ' — rate limited by Sentry'
|
||||
: ' — Sentry outage or transient error';
|
||||
console.warn(`[sentry-edge] non-2xx response ${res.status}${hint}`);
|
||||
}
|
||||
} catch (fetchErr) {
|
||||
console.warn('[sentry-edge] failed to deliver event:', fetchErr instanceof Error ? fetchErr.message : fetchErr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ export default async function handler(req: Request): Promise<Response> {
|
||||
return json(data, 200, corsHeaders);
|
||||
} catch (err) {
|
||||
console.error('[notification-channels] GET error:', err);
|
||||
await captureEdgeException(err, { handler: 'notification-channels', method: 'GET' });
|
||||
void captureEdgeException(err, { handler: 'notification-channels', method: 'GET' });
|
||||
return json({ error: 'Failed to fetch' }, 500, corsHeaders);
|
||||
}
|
||||
}
|
||||
@@ -187,7 +187,7 @@ export default async function handler(req: Request): Promise<Response> {
|
||||
return json({ error: 'Unknown action' }, 400, corsHeaders);
|
||||
} catch (err) {
|
||||
console.error('[notification-channels] POST error:', err);
|
||||
await captureEdgeException(err, { handler: 'notification-channels', method: 'POST' });
|
||||
void captureEdgeException(err, { handler: 'notification-channels', method: 'POST' });
|
||||
return json({ error: 'Operation failed' }, 500, corsHeaders);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@ Sentry.init({
|
||||
: location.hostname.includes('vercel.app') ? 'preview'
|
||||
: 'development',
|
||||
enabled: Boolean(sentryDsn) && !location.hostname.startsWith('localhost') && !('__TAURI_INTERNALS__' in window),
|
||||
allowUrls: [
|
||||
/https?:\/\/(www\.|tech\.|finance\.|commodity\.|happy\.)?worldmonitor\.app/,
|
||||
/https?:\/\/.*\.vercel\.app/,
|
||||
],
|
||||
sendDefaultPii: true,
|
||||
tracesSampleRate: 0.1,
|
||||
ignoreErrors: [
|
||||
|
||||
Reference in New Issue
Block a user