diff --git a/app/global-error.tsx b/app/global-error.tsx index 9bda5fe..a8e1e71 100644 --- a/app/global-error.tsx +++ b/app/global-error.tsx @@ -1,12 +1,13 @@ "use client"; -import * as Sentry from "@sentry/nextjs"; +// import * as Sentry from "@sentry/nextjs"; import NextError from "next/error"; import { useEffect } from "react"; export default function GlobalError({ error }: { error: Error & { digest?: string } }) { useEffect(() => { - Sentry.captureException(error); + // Sentry.captureException(error); + console.error('Global error:', error); }, [error]); return ( diff --git a/app/ws-context.tsx b/app/ws-context.tsx index ca60d06..916d591 100644 --- a/app/ws-context.tsx +++ b/app/ws-context.tsx @@ -4,7 +4,7 @@ import React, { createContext, useContext, useRef, useState, ReactNode, useEffec import { Map } from 'maplibre-gl'; import { gql, useSubscription } from '@apollo/client'; import { subscribeToConnectionState, reconnectWebSocket, WSConnectionState } from '@/lib/apollo-client'; -import * as Sentry from '@sentry/nextjs'; +// import * as Sentry from '@sentry/nextjs'; // 定义WSContext的类型 interface WSContextType { @@ -58,7 +58,8 @@ export function WSProvider({ children }: MapProviderProps) { const { data, loading, error, restart } = useSubscription(SUBSCRIPTION_QUERY, { errorPolicy: 'all', onError: (error) => { - Sentry.captureException(error); + // Sentry.captureException(error); + console.error('WebSocket subscription error:', error); } }); @@ -134,13 +135,14 @@ export function WSProvider({ children }: MapProviderProps) { }, [loading, error, data, isOnline, restart, wsStatus, connectionState.status]); const forceReconnect = () => { - Sentry.startSpan({ - op: 'websocket.manual-reconnect', - name: 'Manual WebSocket Reconnection' - }, () => { + // Sentry.startSpan({ + // op: 'websocket.manual-reconnect', + // name: 'Manual WebSocket Reconnection' + // }, () => { + console.log('Force reconnecting WebSocket...'); reconnectWebSocket(); restart(); - }); + // }); }; const value: WSContextType = { diff --git a/components/map-component.tsx b/components/map-component.tsx index 887561d..af8a983 100644 --- a/components/map-component.tsx +++ b/components/map-component.tsx @@ -11,7 +11,7 @@ import { useRadarTile } from '@/hooks/use-radartile' import { format, formatInTimeZone } from 'date-fns-tz' import vertexSource from '@/app/glsl/radar/verx.glsl' import fragmentSource from '@/app/glsl/radar/frag.glsl' -import * as Sentry from '@sentry/nextjs' +// import * as Sentry from '@sentry/nextjs' import { logger, logWebGLError, logMapEvent, logPerformanceMetric } from '@/lib/logger' interface MapComponentProps { @@ -68,14 +68,14 @@ export function MapComponent({ useEffect(() => { if (!mapContainer.current) return - const span = Sentry.startInactiveSpan({ - op: "ui.component.load", - name: "Map Component Initialization", - }); + // const span = Sentry.startInactiveSpan({ + // op: "ui.component.load", + // name: "Map Component Initialization", + // }); - span.setAttribute("map.style", style); - span.setAttribute("map.center", `${location.center[0]},${location.center[1]}`); - span.setAttribute("map.zoom", location.zoom); + // span.setAttribute("map.style", style); + // span.setAttribute("map.center", `${location.center[0]},${location.center[1]}`); + // span.setAttribute("map.zoom", location.zoom); const map = new maplibregl.Map({ container: mapContainer.current, @@ -127,7 +127,7 @@ export function MapComponent({ const shader = gl.createShader(type); if (!shader) { const error = new Error('Failed to create WebGL shader'); - Sentry.captureException(error); + // Sentry.captureException(error); logWebGLError('shader_creation', 'Failed to create WebGL shader', { shaderType: type === gl.VERTEX_SHADER ? 'vertex' : 'fragment' }); return null; } @@ -138,10 +138,10 @@ export function MapComponent({ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { const errorLog = gl.getShaderInfoLog(shader) || 'Unknown shader compilation error'; const error = new Error(`Shader compilation failed: ${errorLog}`); - Sentry.captureException(error, { - tags: { component: 'MapComponent', operation: 'shader_compilation' }, - extra: { shaderType: type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', source } - }); + // Sentry.captureException(error, { + // tags: { component: 'MapComponent', operation: 'shader_compilation' }, + // extra: { shaderType: type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', source } + // }); logWebGLError('shader_compilation', errorLog, { shaderType: type === gl.VERTEX_SHADER ? 'vertex' : 'fragment' }); gl.deleteShader(shader); return null; @@ -166,10 +166,10 @@ export function MapComponent({ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { const errorLog = gl.getProgramInfoLog(program) || 'Unknown program linking error'; const error = new Error(`WebGL program linking failed: ${errorLog}`); - Sentry.captureException(error, { - tags: { component: 'MapComponent', operation: 'program_linking' }, - extra: { programLog: errorLog } - }); + // Sentry.captureException(error, { + // tags: { component: 'MapComponent', operation: 'program_linking' }, + // extra: { programLog: errorLog } + // }); logWebGLError('program_linking', errorLog); return; } @@ -184,9 +184,9 @@ export function MapComponent({ if (!tex) { const error = new Error('Failed to create WebGL texture'); - Sentry.captureException(error, { - tags: { component: 'MapComponent', operation: 'texture_creation' } - }); + // Sentry.captureException(error, { + // tags: { component: 'MapComponent', operation: 'texture_creation' } + // }); logWebGLError('texture_creation', 'Failed to create WebGL texture'); return; } @@ -482,7 +482,7 @@ export function MapComponent({ } // 结束Sentry span - span.end(); + // span.end(); } }, [mapContainer]) @@ -549,14 +549,14 @@ export function MapComponent({ // 拖动事件处理函数 const handleMouseDown = (e: React.MouseEvent) => { - Sentry.startSpan( - { - op: "ui.interaction", - name: "Colorbar Drag Start", - }, - (span: any) => { - span.setAttribute("colorbar.position.x", colorbarPosition.x); - span.setAttribute("colorbar.position.y", colorbarPosition.y); + // Sentry.startSpan( + // { + // op: "ui.interaction", + // name: "Colorbar Drag Start", + // }, + // (span: any) => { + // span.setAttribute("colorbar.position.x", colorbarPosition.x); + // span.setAttribute("colorbar.position.y", colorbarPosition.y); e.preventDefault() setIsDragging(true) @@ -568,8 +568,8 @@ export function MapComponent({ startPositionX: colorbarPosition.x, startPositionY: colorbarPosition.y } - } - ); + // } + // ); } // 全局鼠标事件监听 diff --git a/instrumentation-client.ts b/instrumentation-client.ts index 4d0e64c..acb6546 100644 --- a/instrumentation-client.ts +++ b/instrumentation-client.ts @@ -2,33 +2,33 @@ // The added config here will be used whenever a users loads a page in their browser. // https://docs.sentry.io/platforms/javascript/guides/nextjs/ -import * as Sentry from "@sentry/nextjs"; +// import * as Sentry from "@sentry/nextjs"; -Sentry.init({ - dsn: "https://109bcfcc2d1cdd643e0af61409016900@o4505647824109568.ingest.us.sentry.io/4509868655181824", +// Sentry.init({ +// dsn: "https://109bcfcc2d1cdd643e0af61409016900@o4505647824109568.ingest.us.sentry.io/4509868655181824", - // Add optional integrations for additional features - integrations: [ - Sentry.replayIntegration(), - // send console.log, console.warn, and console.error calls as logs to Sentry - Sentry.consoleLoggingIntegration({ levels: ["log", "warn", "error"] }), - ], +// // Add optional integrations for additional features +// integrations: [ +// Sentry.replayIntegration(), +// // send console.log, console.warn, and console.error calls as logs to Sentry +// Sentry.consoleLoggingIntegration({ levels: ["log", "warn", "error"] }), +// ], - // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. - tracesSampleRate: 1, - // Enable logs to be sent to Sentry - enableLogs: true, +// // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. +// tracesSampleRate: 1, +// // Enable logs to be sent to Sentry +// enableLogs: true, - // Define how likely Replay events are sampled. - // This sets the sample rate to be 10%. You may want this to be 100% while - // in development and sample at a lower rate in production - replaysSessionSampleRate: 0.1, +// // Define how likely Replay events are sampled. +// // This sets the sample rate to be 10%. You may want this to be 100% while +// // in development and sample at a lower rate in production +// replaysSessionSampleRate: 0.1, - // Define how likely Replay events are sampled when an error occurs. - replaysOnErrorSampleRate: 1.0, +// // Define how likely Replay events are sampled when an error occurs. +// replaysOnErrorSampleRate: 1.0, - // Setting this option to true will print useful information to the console while you're setting up Sentry. - debug: false, -}); +// // Setting this option to true will print useful information to the console while you're setting up Sentry. +// debug: false, +// }); -export const onRouterTransitionStart = Sentry.captureRouterTransitionStart; \ No newline at end of file +// export const onRouterTransitionStart = Sentry.captureRouterTransitionStart; \ No newline at end of file diff --git a/instrumentation.ts b/instrumentation.ts index 964f937..6dcb979 100644 --- a/instrumentation.ts +++ b/instrumentation.ts @@ -1,13 +1,13 @@ -import * as Sentry from '@sentry/nextjs'; +// import * as Sentry from '@sentry/nextjs'; export async function register() { - if (process.env.NEXT_RUNTIME === 'nodejs') { - await import('./sentry.server.config'); - } + // if (process.env.NEXT_RUNTIME === 'nodejs') { + // await import('./sentry.server.config'); + // } - if (process.env.NEXT_RUNTIME === 'edge') { - await import('./sentry.edge.config'); - } + // if (process.env.NEXT_RUNTIME === 'edge') { + // await import('./sentry.edge.config'); + // } } -export const onRequestError = Sentry.captureRequestError; +// export const onRequestError = Sentry.captureRequestError; diff --git a/lib/apollo-client.ts b/lib/apollo-client.ts index 8e1b9dc..f7bedec 100644 --- a/lib/apollo-client.ts +++ b/lib/apollo-client.ts @@ -3,7 +3,7 @@ import { getMainDefinition } from '@apollo/client/utilities'; import { setContext } from '@apollo/client/link/context'; import { GraphQLWsLink } from '@apollo/client/link/subscriptions'; import { createClient, Client } from 'graphql-ws'; -import * as Sentry from '@sentry/nextjs'; +// import * as Sentry from '@sentry/nextjs'; const TOKEN_KEY = 'auth_token'; @@ -44,6 +44,8 @@ let wsClient: Client | null = null; const createWSClient = () => { const wsUrl = process.env.NEXT_PUBLIC_GRAPHQL_BACKEND_URL?.replace('/graphql', '/ws')?.replace('http://', 'ws://') || 'ws://localhost:3050/ws'; + // console.log('Creating WebSocket client with URL:', wsUrl); + return createClient({ url: wsUrl, connectionParams: () => { @@ -58,50 +60,54 @@ const createWSClient = () => { reconnectAttempts: attempt + 1 }); - Sentry.startSpan({ - op: 'websocket.reconnect', - name: 'WebSocket Reconnection Attempt' - }, (span) => { - span.setAttribute('attempt', attempt + 1); - span.setAttribute('delay', delay); - }); + // Sentry.startSpan({ + // op: 'websocket.reconnect', + // name: 'WebSocket Reconnection Attempt' + // }, (span) => { + // span.setAttribute('attempt', attempt + 1); + // span.setAttribute('delay', delay); + // }); await new Promise(resolve => setTimeout(resolve, delay)); }, on: { connecting: () => { + // console.log('WebSocket connecting...'); updateConnectionState({ status: 'connecting' }); }, opened: () => { + // console.log('WebSocket connection opened successfully'); updateConnectionState({ status: 'connected', error: undefined, reconnectAttempts: 0 }); - Sentry.startSpan({ - op: 'websocket.connect', - name: 'WebSocket Connection Established' - }, () => { }); + // Sentry.startSpan({ + // op: 'websocket.connect', + // name: 'WebSocket Connection Established' + // }, () => { }); }, closed: (event: any) => { + // console.log('WebSocket connection closed:', event.code, event.reason); const error = event.reason ? new Error(event.reason) : undefined; updateConnectionState({ status: 'disconnected', error }); - if (error) { - Sentry.captureException(error); - } + // if (error) { + // Sentry.captureException(error); + // } }, error: (error) => { + console.error('WebSocket error:', error); updateConnectionState({ status: 'disconnected', error: error instanceof Error ? error : new Error('WebSocket error') }); - Sentry.captureException(error); + // Sentry.captureException(error); } } }); diff --git a/lib/fetchers.ts b/lib/fetchers.ts index 9120e99..9d48986 100644 --- a/lib/fetchers.ts +++ b/lib/fetchers.ts @@ -1,7 +1,7 @@ import { gql, GraphQLClient } from "graphql-request"; import type { PageData } from "@/types/page"; import { getBaseUrl } from "./gr-client"; -import * as Sentry from "@sentry/nextjs"; +// import * as Sentry from "@sentry/nextjs"; const PageQuery = gql/* GraphQL */ ` @@ -28,14 +28,14 @@ const BlockQuery = gql/* GraphQL */ ` export async function fetchPage(slug: string, jwt?: string): Promise { - return Sentry.startSpan( - { - op: "http.client", - name: `GraphQL fetchPage: ${slug}`, - }, - async (span) => { - span.setAttribute("page.slug", slug); - span.setAttribute("auth.hasJwt", !!jwt); + // return Sentry.startSpan( + // { + // op: "http.client", + // name: `GraphQL fetchPage: ${slug}`, + // }, + // async (span) => { + // span.setAttribute("page.slug", slug); + // span.setAttribute("auth.hasJwt", !!jwt); const client = new GraphQLClient(getBaseUrl()); @@ -45,34 +45,38 @@ export async function fetchPage(slug: string, jwt?: string): Promise client.request(PageQuery, { slug }) - ); + const pageResponse: any = await client.request(PageQuery, { slug }); + // const pageResponse: any = await Sentry.startSpan( + // { + // op: "http.client", + // name: "GraphQL PageQuery", + // }, + // () => client.request(PageQuery, { slug }) + // ); if (!pageResponse?.pageBySlug) { throw new Error('Page not found'); } // 获取页面块数据 - const blocksResponse: any = await Sentry.startSpan( - { - op: "http.client", - name: "GraphQL BlockQuery", - }, - () => client.request(BlockQuery, { - pageId: pageResponse.pageBySlug.id - }) - ); + const blocksResponse: any = await client.request(BlockQuery, { + pageId: pageResponse.pageBySlug.id + }); + // const blocksResponse: any = await Sentry.startSpan( + // { + // op: "http.client", + // name: "GraphQL BlockQuery", + // }, + // () => client.request(BlockQuery, { + // pageId: pageResponse.pageBySlug.id + // }) + // ); if (!blocksResponse?.pageBlocks) { throw new Error('Failed to fetch page blocks'); } - span.setAttribute("page.blocksCount", blocksResponse.pageBlocks.length); + // span.setAttribute("page.blocksCount", blocksResponse.pageBlocks.length); // 合并数据 return { @@ -81,27 +85,27 @@ export async function fetchPage(slug: string, jwt?: string): Promise { + // return Sentry.startSpan( + // { + // op: "http.client", + // name: "Fetch Site Configs", + // }, + // async (span) => { try { const baseUrl = process.env.NEXTAUTH_URL || 'http://localhost:3000'; - span.setAttribute("api.baseUrl", baseUrl); + // span.setAttribute("api.baseUrl", baseUrl); const siteConfigs = await fetch(`${baseUrl}/api/site`, { headers: { @@ -111,30 +115,30 @@ export async function getSiteConfigs() { signal: AbortSignal.timeout(5000) }); - span.setAttribute("http.status_code", siteConfigs.status); + // span.setAttribute("http.status_code", siteConfigs.status); if (!siteConfigs.ok) { const error = new Error(`Failed to fetch site configs: ${siteConfigs.status} ${siteConfigs.statusText}`); - Sentry.captureException(error, { - tags: { operation: 'getSiteConfigs' }, - extra: { status: siteConfigs.status, statusText: siteConfigs.statusText } - }); + // Sentry.captureException(error, { + // tags: { operation: 'getSiteConfigs' }, + // extra: { status: siteConfigs.status, statusText: siteConfigs.statusText } + // }); console.warn(`Failed to fetch site configs: ${siteConfigs.status} ${siteConfigs.statusText}`); return getDefaultSiteConfigs(); } const data = await siteConfigs.json(); - span.setAttribute("configs.count", data.length); + // span.setAttribute("configs.count", data.length); return data; } catch (error) { - Sentry.captureException(error, { - tags: { operation: 'getSiteConfigs' } - }); + // Sentry.captureException(error, { + // tags: { operation: 'getSiteConfigs' } + // }); console.warn('Failed to fetch site configs, using defaults:', error); return getDefaultSiteConfigs(); } - } - ); + // } + // ); } function getDefaultSiteConfigs() { diff --git a/lib/logger.ts b/lib/logger.ts index deef6e1..094b223 100644 --- a/lib/logger.ts +++ b/lib/logger.ts @@ -1,9 +1,28 @@ -import * as Sentry from "@sentry/nextjs"; +// import * as Sentry from "@sentry/nextjs"; // 获取Sentry logger实例 -const { logger } = Sentry; +// const { logger } = Sentry; // 导出logger以便在其他文件中使用 +// export { logger }; + +// Fallback logger when Sentry is disabled +const logger = { + trace: (message: string, context?: Record) => console.log(`[TRACE] ${message}`, context), + debug: (message: string, context?: Record) => console.log(`[DEBUG] ${message}`, context), + info: (message: string, context?: Record) => console.log(`[INFO] ${message}`, context), + warn: (message: string, context?: Record) => console.warn(`[WARN] ${message}`, context), + error: (message: string, context?: Record) => console.error(`[ERROR] ${message}`, context), + fatal: (message: string, context?: Record) => console.error(`[FATAL] ${message}`, context), + fmt: (strings: TemplateStringsArray, ...values: any[]) => { + let result = strings[0]; + for (let i = 0; i < values.length; i++) { + result += values[i] + strings[i + 1]; + } + return result; + } +}; + export { logger }; // 示例用法的辅助函数 diff --git a/next.config.ts b/next.config.ts index 077e5e6..d6b883e 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,4 +1,4 @@ -import {withSentryConfig} from "@sentry/nextjs"; +// import {withSentryConfig} from "@sentry/nextjs"; import type { NextConfig } from "next"; const nextConfig: NextConfig = { @@ -14,35 +14,37 @@ const nextConfig: NextConfig = { } }; -export default withSentryConfig(nextConfig, { - // For all available options, see: - // https://www.npmjs.com/package/@sentry/webpack-plugin#options +export default nextConfig; - org: "lix-nr", +// export default withSentryConfig(nextConfig, { +// // For all available options, see: +// // https://www.npmjs.com/package/@sentry/webpack-plugin#options - project: "lidar", +// org: "lix-nr", - // Only print logs for uploading source maps in CI - silent: !process.env.CI, +// project: "lidar", - // For all available options, see: - // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/ +// // Only print logs for uploading source maps in CI +// silent: !process.env.CI, - // Upload a larger set of source maps for prettier stack traces (increases build time) - widenClientFileUpload: true, +// // For all available options, see: +// // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/ - // Uncomment to route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers. - // This can increase your server load as well as your hosting bill. - // Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client- - // side errors will fail. - // tunnelRoute: "/monitoring", +// // Upload a larger set of source maps for prettier stack traces (increases build time) +// widenClientFileUpload: true, - // Automatically tree-shake Sentry logger statements to reduce bundle size - disableLogger: true, +// // Uncomment to route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers. +// // This can increase your server load as well as your hosting bill. +// // Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client- +// // side errors will fail. +// // tunnelRoute: "/monitoring", - // Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.) - // See the following for more information: - // https://docs.sentry.io/product/crons/ - // https://vercel.com/docs/cron-jobs - automaticVercelMonitors: true -}); \ No newline at end of file +// // Automatically tree-shake Sentry logger statements to reduce bundle size +// disableLogger: true, + +// // Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.) +// // See the following for more information: +// // https://docs.sentry.io/product/crons/ +// // https://vercel.com/docs/cron-jobs +// automaticVercelMonitors: true +// }); \ No newline at end of file diff --git a/sentry.edge.config.ts b/sentry.edge.config.ts index 5479ebf..15ac957 100644 --- a/sentry.edge.config.ts +++ b/sentry.edge.config.ts @@ -3,22 +3,22 @@ // Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally. // https://docs.sentry.io/platforms/javascript/guides/nextjs/ -import * as Sentry from "@sentry/nextjs"; +// import * as Sentry from "@sentry/nextjs"; -Sentry.init({ - dsn: "https://109bcfcc2d1cdd643e0af61409016900@o4505647824109568.ingest.us.sentry.io/4509868655181824", +// Sentry.init({ +// dsn: "https://109bcfcc2d1cdd643e0af61409016900@o4505647824109568.ingest.us.sentry.io/4509868655181824", - integrations: [ - // send console.log, console.warn, and console.error calls as logs to Sentry - Sentry.consoleLoggingIntegration({ levels: ["log", "warn", "error"] }), - ], +// integrations: [ +// // send console.log, console.warn, and console.error calls as logs to Sentry +// Sentry.consoleLoggingIntegration({ levels: ["log", "warn", "error"] }), +// ], - // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. - tracesSampleRate: 1, +// // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. +// tracesSampleRate: 1, - // Enable logs to be sent to Sentry - enableLogs: true, +// // Enable logs to be sent to Sentry +// enableLogs: true, - // Setting this option to true will print useful information to the console while you're setting up Sentry. - debug: false, -}); +// // Setting this option to true will print useful information to the console while you're setting up Sentry. +// debug: false, +// }); diff --git a/sentry.server.config.ts b/sentry.server.config.ts index 77f06c0..5f15699 100644 --- a/sentry.server.config.ts +++ b/sentry.server.config.ts @@ -2,22 +2,22 @@ // The config you add here will be used whenever the server handles a request. // https://docs.sentry.io/platforms/javascript/guides/nextjs/ -import * as Sentry from "@sentry/nextjs"; +// import * as Sentry from "@sentry/nextjs"; -Sentry.init({ - dsn: "https://109bcfcc2d1cdd643e0af61409016900@o4505647824109568.ingest.us.sentry.io/4509868655181824", +// Sentry.init({ +// dsn: "https://109bcfcc2d1cdd643e0af61409016900@o4505647824109568.ingest.us.sentry.io/4509868655181824", - integrations: [ - // send console.log, console.warn, and console.error calls as logs to Sentry - Sentry.consoleLoggingIntegration({ levels: ["log", "warn", "error"] }), - ], +// integrations: [ +// // send console.log, console.warn, and console.error calls as logs to Sentry +// Sentry.consoleLoggingIntegration({ levels: ["log", "warn", "error"] }), +// ], - // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. - tracesSampleRate: 1, +// // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. +// tracesSampleRate: 1, - // Enable logs to be sent to Sentry - enableLogs: true, +// // Enable logs to be sent to Sentry +// enableLogs: true, - // Setting this option to true will print useful information to the console while you're setting up Sentry. - debug: false, -}); +// // Setting this option to true will print useful information to the console while you're setting up Sentry. +// debug: false, +// });