Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kmong-developers",
"version": "0.1.0",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "next dev",
Expand Down
39 changes: 33 additions & 6 deletions sentry.client.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,55 @@
// https://docs.sentry.io/platforms/javascript/guides/nextjs/

import * as Sentry from "@sentry/nextjs";
import packageInfo from './package.json';

Sentry.init({
dsn: "https://78244d347b94fbc2be076209148d8ab4@o4506552386715648.ingest.sentry.io/4506552392417280",
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,

// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1,

// Setting this option to true will print useful information to the console while you're setting up Sentry.
debug: false,

debug: true,
environment: process.env.NODE_ENV,
release: packageInfo.version,
replaysOnErrorSampleRate: 1.0,

// 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,

// You can remove this option if you're not planning to use the Sentry Session Replay feature:
ignoreErrors: ['밀크티'],
// denyUrls: ['sentry-example-page'],
// allowUrls: ['sentry-example-page'],
autoSessionTracking: true,
integrations: [
new Sentry.Replay({
// Additional Replay configuration goes in here, for example:
maskAllText: true,
maskAllText: false,
blockAllMedia: true,
}),
new Sentry.Integrations.Breadcrumbs({
console: false,
}),
new Sentry.BrowserTracing({
shouldCreateSpanForRequest: (url) => {
// `/sentry-example-api`로 요청하는 경우 span을 생성하지 않는다. >> Performance 대시보드에 생성되지 않음
console.log('url', url);
// console.log('isMatch?', !url.match(/\/sentry-example-api?$/));
return !url.match(/\/sentry-example-api?$/);
},
beforeNavigate(context) {
console.log('beforeNavigate', context);

if(/^\/order\/\d+$/.test(context.name)) {
return {
...context,
name: 'order/:id',
}
}

return context;
},
}),
],
});
2 changes: 1 addition & 1 deletion sentry.edge.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import * as Sentry from "@sentry/nextjs";

Sentry.init({
dsn: "https://78244d347b94fbc2be076209148d8ab4@o4506552386715648.ingest.sentry.io/4506552392417280",
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,

// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1,
Expand Down
2 changes: 1 addition & 1 deletion sentry.server.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import * as Sentry from "@sentry/nextjs";

Sentry.init({
dsn: "https://78244d347b94fbc2be076209148d8ab4@o4506552386715648.ingest.sentry.io/4506552392417280",
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,

// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1,
Expand Down
9 changes: 9 additions & 0 deletions src/app/api/sentry-example-api/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { NextResponse } from "next/server";

export const dynamic = "force-dynamic";

// A faulty API route to test Sentry's error monitoring
export function GET() {
throw new Error("Sentry Example API Route Error");
return NextResponse.json({ data: "Testing Sentry Error..." });
}
47 changes: 47 additions & 0 deletions src/app/cart/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"use client";

import styles from "@/app/order/order.module.css";
import Link from "next/link";

function CartPage() {
const handleClickPayment = async () => {
console.log('결제를 시작합니다.');

const res = await fetch("/api/sentry-example-api", { method: 'post' });
if (!res.ok) {
throw new Error("결제 API 실패");
}
}

return (
<main className={styles.main}>
<div className={styles.header}>
<Link
className={styles.link}
href={'/'}
>
</Link>
<h1 className={styles.h1}>장바구니 페이지</h1>
<Link
className={styles.link}
href={'/order'}
>
주문 페이지
</Link>
</div>
<div className={styles.text}>
<div>장바구니에 담은 것:</div>
<div>밀크티, 카페라떼, 카푸치노</div>
</div>
<button
className={styles.payment}
onClick={handleClickPayment}
>
결제
</button>
</main>
);
}

export default CartPage;
9 changes: 9 additions & 0 deletions src/app/order/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use client";

import styles from "@/app/order/order.module.css";

function OrderIdPage() {
return <main className={styles.main}>상세페이지</main>;
}

export default OrderIdPage;
96 changes: 96 additions & 0 deletions src/app/order/order.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
.main {
min-height: 100vh;
padding: 2rem;
background: #fff;
display: flex;
flex-direction: column;
justify-content: space-between;
}

.h1 {
font-size: 1.8rem;
font-weight: 700;
margin-bottom: 1rem;
text-align: center;
}

.menus {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1rem;
list-style: none;
width: 100%;
max-width: 200px;
margin: auto;
}

.menus > li {
width: 100%;
}

.button {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
outline: none;
border: none;
background: #eaeaea;
font-size: 1.2rem;
padding: .5rem;
border-radius: .5rem;
line-height: 1;
}

.button:hover {
cursor: pointer;
outline: 2px solid #ddd;
}

.payment {
max-width: 400px;
width: 100%;
margin: 0 auto;
padding: 1rem;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
background: #fdcf6f;
outline: 0;
border: 0;
font-weight: 700;
border-radius: 0.5rem;
}

.payment:hover {
cursor: pointer;
outline: 2px solid #f1c469;
}

.header {
width: 100%;
max-width: 720px;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #ddd;
}

.link {
color: #6e6e71;
}

.link:hover {
text-decoration: underline;
}

.text {
font-size: 1.2rem;
text-align: center;
line-height: 1.5;
}
81 changes: 81 additions & 0 deletions src/app/order/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"use client";
import * as Sentry from "@sentry/nextjs";
import { captureException } from "@sentry/nextjs";
import styles from "./order.module.css";
import Link from "next/link";

function OrderPage() {
const handleClickMenu = (name: string) => {
console.log(`${name}을 주문합니다.`);
Sentry.startSpan({ name: "order-span" }, (span) => {
span?.setTag("menu", name);
console.log('span~~~~~')
console.log(span);
});

const transaction = Sentry.startTransaction({ name: "order-transaction" });
try {
throw new Error(`${name}을 주문하지 못했습니다.`);
} catch (error) {
captureException(error);
} finally {
transaction.finish();
}
}

const handleClickCart = async () => {
console.log('장바구니에 담기를 클릭했습니다.');

const res = await fetch("/api/sentry-example-api", { method: 'post' });
if (!res.ok) {
throw new Error("장바구니 API 실패");
}
}

return (
<main className={styles.main}>
<div className={styles.header}>
<Link
className={styles.link}
href={'/'}
>
</Link>
<h1 className={styles.h1}>주문 페이지</h1>
<Link
className={styles.link}
href={'/cart'}
>
장바구니
</Link>
</div>
<ul className={styles.menus}>
{menus.map((menu) => (
<li key={menu}>
<button
className={styles.button}
onClick={() => handleClickMenu(menu)}
>
{menu}
</button>
</li>
))}
</ul>
<button
className={styles.payment}
onClick={handleClickCart}
>
장바구니
</button>
</main>
);
}

const menus = [
'아메리카노',
'카푸치노',
'라떼',
'밀크티',
];

export default OrderPage;
4 changes: 2 additions & 2 deletions src/app/sentry-example-page/page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ export default function Page() {
}}
onClick={() => {
Sentry.startSpan({
name: 'Example Frontend Span',
name: 'New Ignore Span',
op: 'test'
}, async () => {
const res = await fetch("/api/sentry-example-api");
if (!res.ok) {
throw new Error("Sentry Example Frontend Error");
throw new Error("New Ignore Span Error");
}
});
}}
Expand Down