feat(telemetry): implement glitchtip/sentry integration with smart proxy
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 10s
Build & Deploy / 🧪 QA (push) Failing after 2m43s
Build & Deploy / 🏗️ Build (push) Failing after 5m34s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🩺 Health Check (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s

- Added Sentry/GlitchTip relay route handler
- Configured Sentry for client (with tunnel), server, and edge runtimes
- Refactored GlitchTip adapter to use official @sentry/nextjs SDK
- Fixed ComparisonRow type issues and Analytics Suspense bailout
- Integrated Sentry instrumentation into the boot sequence
This commit is contained in:
2026-02-16 23:09:50 +01:00
parent 2038b8fe47
commit 4db820214b
10 changed files with 152 additions and 78 deletions

View File

@@ -1,76 +1,48 @@
/**
* GlitchTip Error Tracking Adapter
* GlitchTip is Sentry-compatible.
* This version uses the official @sentry/nextjs SDK.
*/
import type { ErrorTrackingAdapter, ErrorContext, ErrorTrackingConfig } from './interfaces';
import * as Sentry from "@sentry/nextjs";
import type {
ErrorTrackingAdapter,
ErrorContext,
ErrorTrackingConfig,
} from "./interfaces";
export class GlitchTipAdapter implements ErrorTrackingAdapter {
private dsn: string;
constructor(config: ErrorTrackingConfig) {
this.dsn = config.dsn;
this.init(config);
}
private init(config: ErrorTrackingConfig) {
if (typeof window === 'undefined') return;
// In a real scenario, we would import @sentry/nextjs or @sentry/browser
// For this implementation, we assume Sentry is available globally or
// we provide the structure that would call the SDK.
const w = window as any;
if (w.Sentry) {
w.Sentry.init({
dsn: this.dsn,
environment: config.environment || 'production',
release: config.release,
debug: config.debug || false,
});
}
constructor(_config: ErrorTrackingConfig) {
// Sentry is initialized via sentry.*.config.ts files
}
captureException(error: any, context?: ErrorContext): void {
if (typeof window === 'undefined') return;
const w = window as any;
if (w.Sentry) {
w.Sentry.captureException(error, context);
} else {
console.error('[GlitchTip] Exception captured (Sentry not loaded):', error, context);
}
Sentry.captureException(error, {
extra: context?.extra,
tags: context?.tags,
user: context?.user as any,
level: context?.level as any,
});
}
captureMessage(message: string, context?: ErrorContext): void {
if (typeof window === 'undefined') return;
const w = window as any;
if (w.Sentry) {
w.Sentry.captureMessage(message, context);
} else {
console.log('[GlitchTip] Message captured (Sentry not loaded):', message, context);
}
Sentry.captureMessage(message, {
extra: context?.extra,
tags: context?.tags,
user: context?.user as any,
level: context?.level as any,
});
}
setUser(user: ErrorContext['user']): void {
if (typeof window === 'undefined') return;
const w = window as any;
if (w.Sentry) {
w.Sentry.setUser(user);
}
setUser(user: ErrorContext["user"]): void {
Sentry.setUser(user as any);
}
setTag(key: string, value: string): void {
if (typeof window === 'undefined') return;
const w = window as any;
if (w.Sentry) {
w.Sentry.setTag(key, value);
}
Sentry.setTag(key, value);
}
setExtra(key: string, value: any): void {
if (typeof window === 'undefined') return;
const w = window as any;
if (w.Sentry) {
w.Sentry.setExtra(key, value);
}
Sentry.setExtra(key, value);
}
}