-
Notifications
You must be signed in to change notification settings - Fork 1
chore: 에러 모니터링 환경 구축을 위한 Sentry 도입 #89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,3 +32,6 @@ yarn-error.log* | |
|
|
||
| # vercel | ||
| .vercel | ||
|
|
||
| # Sentry Config File | ||
| .env.sentry-build-plugin | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,25 +1,44 @@ | ||
| 'use client' | ||
|
|
||
| import Link from 'next/link' | ||
| import { useEffect } from 'react' | ||
| import * as Sentry from '@sentry/nextjs' | ||
| import { Text } from '@repo/ui/components/Text' | ||
| import { Icon } from '@repo/ui/components/Icon' | ||
| import { Button } from '@repo/ui/components/Button' | ||
| import { Column } from '@repo/ui/components/Layout' | ||
| import { CLIENT_PATH } from '@/_constants/path' | ||
|
|
||
| export default function ErrorPage() { | ||
| type Props = { | ||
| error: Error & { digest?: string } | ||
| reset: VoidFunction | ||
| } | ||
|
|
||
| export default function ErrorPage({ error, reset }: Props) { | ||
| useEffect(() => { | ||
| Sentry.captureException(error) | ||
| }, [error]) | ||
|
|
||
| return ( | ||
| <Column className={'flex-1 items-center justify-center gap-20'}> | ||
| <Column className={'gap-30 flex-1 items-center justify-center'}> | ||
| <Column className={'items-center gap-2'}> | ||
| <Icon type={'logo'} size={150} /> | ||
| <div className={'text-center'}> | ||
| <Text fontSize={'lg'}>에러가 발생했어요</Text> | ||
| <Text fontSize={'lg'}>페이지를 새로고침해주세요</Text> | ||
| </div> | ||
| </Column> | ||
| <Button as={Link} size={'medium'} href={CLIENT_PATH.MAIN}> | ||
| 홈으로 | ||
| </Button> | ||
| <Column className={'items-center gap-2'}> | ||
| <Button size={'medium'} onClick={reset} className='mb-2'> | ||
| 다시 시도 | ||
| </Button> | ||
| <Link | ||
| href={CLIENT_PATH.MAIN} | ||
| className='text-sm text-gray-400 underline' | ||
| > | ||
| 홈으로 이동 | ||
| </Link> | ||
| </Column> | ||
| </Column> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| 'use client' | ||
|
|
||
| import * as Sentry from '@sentry/nextjs' | ||
| import { useEffect } from 'react' | ||
| import { Column } from '@repo/ui/components/Layout' | ||
| import { Text } from '@repo/ui/components/Text' | ||
| import { Button } from '@repo/ui/components/Button' | ||
|
|
||
| export default function GlobalError({ | ||
| error, | ||
| }: { | ||
| error: Error & { digest?: string } | ||
| }) { | ||
| useEffect(() => { | ||
| Sentry.captureException(error) | ||
| }, [error]) | ||
|
|
||
| return ( | ||
| <html lang='ko'> | ||
| <body> | ||
| <div className='flex h-screen w-full items-center justify-center bg-white'> | ||
| <Column className={'items-center gap-10'}> | ||
| <div className={'text-center'}> | ||
| <Text fontSize={'2xl'} fontWeight='bold'> | ||
| 시스템에 문제가 발생했습니다 | ||
| </Text> | ||
| <Text className='mt-2 text-gray-500'> | ||
| 잠시 후 다시 시도해주세요. | ||
| </Text> | ||
| </div> | ||
| <Button size={'medium'} onClick={() => window.location.reload()}> | ||
| 새로고침 | ||
| </Button> | ||
| </Column> | ||
| </div> | ||
| </body> | ||
| </html> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,33 @@ | ||||||
| // This file configures the initialization of Sentry on the client. | ||||||
| // 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' | ||||||
|
|
||||||
| Sentry.init({ | ||||||
| dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, | ||||||
|
|
||||||
| enabled: process.env.NODE_ENV === 'production', | ||||||
|
|
||||||
| // Add optional integrations for additional features | ||||||
| integrations: [Sentry.replayIntegration()], | ||||||
|
|
||||||
| // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. | ||||||
| tracesSampleRate: 1, | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 프로덕션 환경에서 tracesSampleRate를 낮추세요. 서버 설정과 마찬가지로 클라이언트의 🔎 권장 수정사항- tracesSampleRate: 1,
+ tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1,📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| // 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 when an error occurs. | ||||||
| replaysOnErrorSampleRate: 1.0, | ||||||
|
|
||||||
| // Enable sending user PII (Personally Identifiable Information) | ||||||
| // https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#sendDefaultPii | ||||||
| sendDefaultPii: true, | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: fd "instrumentation-client" --type fRepository: knu-matzip/Matzip-Client Length of output: 102 🏁 Script executed: cat -n apps/web/instrumentation-client.tsRepository: knu-matzip/Matzip-Client Length of output: 1566 🏁 Script executed: find . -type f -name "*instrumentation*" | head -20Repository: knu-matzip/Matzip-Client Length of output: 134 🏁 Script executed: fd "sentry" --type f -e py -e ts -e js | grep -E "(server|backend|instrumentation)" | head -20Repository: knu-matzip/Matzip-Client Length of output: 100 🏁 Script executed: find . -type f \( -name "PRIVACY*" -o -name "privacy*" -o -name "DATA_PROTECTION*" -o -name "*policy*" \) | head -10Repository: knu-matzip/Matzip-Client Length of output: 50 🏁 Script executed: cat -n apps/web/instrumentation.tsRepository: knu-matzip/Matzip-Client Length of output: 480 🏁 Script executed: cat -n apps/web/sentry.server.config.tsRepository: knu-matzip/Matzip-Client Length of output: 971 🏁 Script executed: cat -n README.md 2>/dev/null | head -50Repository: knu-matzip/Matzip-Client Length of output: 2561 🏁 Script executed: find . -type f \( -name "README*" -o -name "CHANGELOG*" \) -exec grep -l "privacy\|PII\|Sentry\|data" {} \;Repository: knu-matzip/Matzip-Client Length of output: 50 Sentry sendDefaultPii 설정의 개인정보 보호 정책 검토 필요
🤖 Prompt for AI Agents |
||||||
| }) | ||||||
|
|
||||||
| export const onRouterTransitionStart = Sentry.captureRouterTransitionStart | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| 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 === 'edge') { | ||
| await import('./sentry.edge.config') | ||
| } | ||
| } | ||
|
|
||
| export const onRequestError = Sentry.captureRequestError |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,22 @@ | ||||||||||
| // This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on). | ||||||||||
| // The config you add here will be used whenever one of the edge features is loaded. | ||||||||||
| // 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' | ||||||||||
|
|
||||||||||
| Sentry.init({ | ||||||||||
| dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, | ||||||||||
|
|
||||||||||
| enabled: process.env.NODE_ENV === 'production', | ||||||||||
|
|
||||||||||
| // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. | ||||||||||
| tracesSampleRate: 1, | ||||||||||
|
Comment on lines
+13
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 프로덕션 환경에서 tracesSampleRate를 낮춰야 합니다.
일반적으로 프로덕션에서는 0.1 (10%) 이하로 설정하는 것을 권장합니다. 🔎 권장 설정- // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.
- tracesSampleRate: 1,
+ // Adjust this value based on your traffic volume and budget
+ tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1,📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||
|
|
||||||||||
| // Enable logs to be sent to Sentry | ||||||||||
| enableLogs: true, | ||||||||||
|
|
||||||||||
| // Enable sending user PII (Personally Identifiable Information) | ||||||||||
| // https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#sendDefaultPii | ||||||||||
| sendDefaultPii: true, | ||||||||||
|
Comment on lines
+19
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cd apps/web && find . -name "sentry.edge.config.ts" -o -name "sentry*.config.ts" | head -20Repository: knu-matzip/Matzip-Client Length of output: 117 🏁 Script executed: cat -n apps/web/sentry.edge.config.tsRepository: knu-matzip/Matzip-Client Length of output: 1133 🏁 Script executed: # Search for any other Sentry configuration files or beforeSend callbacks
rg -l "beforeSend|Sentry.init" --type ts --type js | head -20Repository: knu-matzip/Matzip-Client Length of output: 166 🏁 Script executed: # Check if there are any privacy-related policies or documentation
find . -name "*privacy*" -o -name "*gdpr*" -o -name "*policy*" 2>/dev/null | grep -v node_modules | head -20Repository: knu-matzip/Matzip-Client Length of output: 50 🏁 Script executed: cat -n apps/web/sentry.server.config.tsRepository: knu-matzip/Matzip-Client Length of output: 971 🏁 Script executed: cat -n apps/web/instrumentation-client.tsRepository: knu-matzip/Matzip-Client Length of output: 1566 🏁 Script executed: # Search more broadly for beforeSend or data filtering in Sentry configs
rg "beforeSend|afterSend|integrations" apps/web/ --type ts --type js -A 3 -B 1Repository: knu-matzip/Matzip-Client Length of output: 521 🏁 Script executed: # Check if there's a package.json to see Sentry version
cat apps/web/package.json | grep -A 2 -B 2 "@sentry"Repository: knu-matzip/Matzip-Client Length of output: 240 sendDefaultPii 설정에 대한 개인정보 보호 및 준수 사항 검토 필요
이 설정은 사용자의 IP 주소, 사용자명, 이메일, 쿠키 등 개인식별정보(PII)를 Sentry로 전송합니다. 다음 사항들을 확인해주세요:
민감한 정보 노출을 방지하기 위해 각 설정 파일에서 🤖 Prompt for AI Agents |
||||||||||
| }) | ||||||||||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,21 @@ | ||||||||
| // This file configures the initialization of Sentry on the server. | ||||||||
| // 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' | ||||||||
|
|
||||||||
| Sentry.init({ | ||||||||
| dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, | ||||||||
|
|
||||||||
| enabled: process.env.NODE_ENV === 'production', | ||||||||
|
|
||||||||
| // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. | ||||||||
| tracesSampleRate: 1, | ||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 프로덕션 환경에서 tracesSampleRate를 낮추세요.
🔎 권장 수정사항- tracesSampleRate: 1,
+ // Adjust based on your traffic - 0.1 = 10% of transactions
+ tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1,📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||
|
|
||||||||
| // Enable logs to be sent to Sentry | ||||||||
| enableLogs: true, | ||||||||
|
|
||||||||
| // Enable sending user PII (Personally Identifiable Information) | ||||||||
| // https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#sendDefaultPii | ||||||||
| sendDefaultPii: true, | ||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # Examine the target file
cat -n apps/web/sentry.server.config.tsRepository: knu-matzip/Matzip-Client Length of output: 971 🏁 Script executed: # Search for any beforeSend or other privacy-related configuration
rg -i "beforesend|filterpii|denyurls|allowurls|privacy" apps/web/ --type ts --type js -A 2 -B 2Repository: knu-matzip/Matzip-Client Length of output: 50 🏁 Script executed: # Look for privacy policy or GDPR-related documentation
fd -i "privacy\|gdpr\|ccpa\|compliance" apps/web/ -o 2>/dev/nullRepository: knu-matzip/Matzip-Client Length of output: 50 🏁 Script executed: # Check Sentry's documentation context - search for any comments or documentation in the codebase
rg -i "sentry" apps/web/sentry.server.config.ts -A 5 -B 5Repository: knu-matzip/Matzip-Client Length of output: 824 Sentry 설정에서 PII 전송에 대한 개인정보 보호 검토가 필요합니다.
권장사항:
🤖 Prompt for AI Agents |
||||||||
| }) | ||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
민감 정보 유출 위험: response data 로깅 제거 또는 필터링 필요.
error.response?.data를 Sentry에 전송하면 다음과 같은 심각한 보안 및 개인정보 보호 문제가 발생할 수 있습니다:Sentry는 외부 모니터링 서비스이므로, 민감한 데이터가 외부로 전송되지 않도록 주의해야 합니다.
🔎 권장 해결 방법
방법 1 (권장): response data 필드 완전 제거
if (error.response?.status !== 401) { Sentry.captureException(error, { extra: { url: originalRequest?.url, method: originalRequest?.method, status: error.response?.status, - data: error.response?.data, }, }) }방법 2: 민감 정보 필터링 후 로깅
또한 Sentry 설정에서
beforeSend훅을 사용하여 전역적으로 민감 정보를 필터링할 수도 있습니다.📝 Committable suggestion
🤖 Prompt for AI Agents