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