Skip to content

Commit f96b453

Browse files
committed
chore : API 로깅 강화
1 parent ef74307 commit f96b453

5 files changed

Lines changed: 194 additions & 8 deletions

File tree

apps/Admission-LTS/src/apis/admission/index.ts

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useMutation } from "@tanstack/react-query"
22
import { IAdmissionRequest } from "./types"
3-
import { AdmissionUserInstance } from "@entry/util-config"
3+
import { AdmissionUserInstance, sendSubmissionSuccess, sendSubmissionCancel, getSessionId } from "@entry/util-config"
44
import { toast } from "react-toastify"
55
import { AxiosError } from "axios"
66
import { useNavigate } from "react-router"
@@ -38,23 +38,29 @@ const sendErrorReport = async (
3838

3939
export const useAdmissionSubmitPost = <T extends IAdmissionRequest>() => {
4040
const navigate = useNavigate()
41-
const sessionId = crypto.randomUUID()
41+
const sessionId = getSessionId() || crypto.randomUUID()
4242

4343
return useMutation({
4444
mutationFn: async (data: T) => {
4545
const startTime = Date.now()
4646
try {
4747
const response = await AdmissionUserInstance.post('/api/v1/applications', data)
48-
return response.data
48+
return { data: response.data, responseTime: Date.now() - startTime }
4949
} catch (error) {
5050
const responseTime = Date.now() - startTime
5151
throw { error, responseTime }
5252
}
5353
},
5454

55-
onSuccess: (data) => {
55+
onSuccess: async (result, variables) => {
5656
toast.success('원서 제출이 정상적으로 완료되었습니다.')
5757

58+
// 원서 제출 성공 전송
59+
await sendSubmissionSuccess({
60+
sessionId,
61+
submissionId: result.data.id || 0,
62+
})
63+
5864
setTimeout(() => {
5965
window.location.href = "https://entrydsm.kr/"
6066
}, 2000)
@@ -64,22 +70,66 @@ export const useAdmissionSubmitPost = <T extends IAdmissionRequest>() => {
6470
const err = errorData.error as AxiosError<any>
6571
const responseTime = errorData.responseTime || 0
6672

73+
// 에러 상세 정보 생성
74+
const errorDetails = {
75+
httpStatus: err.response?.status || 0,
76+
errorCode: err.code || "UNKNOWN_ERROR",
77+
message: err.message || "원서 제출 중 오류가 발생했습니다.",
78+
responseData: err.response?.data ? JSON.stringify(err.response.data) : "",
79+
requestData: JSON.stringify(variables),
80+
stackTrace: err.stack || "",
81+
responseTime: responseTime,
82+
endpoint: "/api/v1/applications",
83+
httpMethod: "POST",
84+
}
85+
86+
const reason = `[${errorDetails.httpStatus}] ${errorDetails.message}\n` +
87+
`ErrorCode: ${errorDetails.errorCode}\n` +
88+
`Response: ${errorDetails.responseData}\n` +
89+
`Request: ${errorDetails.requestData}\n` +
90+
`ResponseTime: ${errorDetails.responseTime}ms\n` +
91+
`Stack: ${errorDetails.stackTrace}`
92+
6793
if (err.response?.status === 409) {
6894
toast.error('동일한 계정으로 제출된 원서가 존재합니다.')
95+
96+
// 원서 제출 실패 전송
97+
await sendSubmissionCancel({
98+
sessionId,
99+
submissionId: 0,
100+
reason,
101+
})
102+
69103
await sendErrorReport(sessionId, err, variables, responseTime)
70104

71105
setTimeout(() => {
72106
window.location.href = "https://entrydsm.kr/"
73107
}, 2000)
74108
} else if (err.response?.status === 400 || err.response?.status === 500 || err.response?.status === 502 || err.response?.status === 503) {
75109
toast.error("일시적으로 처리할 수 없습니다. 다시 시도해 주세요.")
110+
111+
// 원서 제출 실패 전송
112+
await sendSubmissionCancel({
113+
sessionId,
114+
submissionId: 0,
115+
reason,
116+
})
117+
76118
await sendErrorReport(sessionId, err, variables, responseTime)
77119

78120
setTimeout(() => {
79121
window.location.href = "https://entrydsm.kr/"
80122
}, 2000)
81123
} else {
82124
toast.error("원서 제출 중 오류가 발생했습니다.")
125+
126+
// 원서 제출 실패 전송
127+
await sendSubmissionCancel({
128+
sessionId,
129+
submissionId: 0,
130+
reason,
131+
})
132+
83133
await sendErrorReport(sessionId, err, variables, responseTime)
84134

85135
setTimeout(() => {

apps/entry-user/src/pages/MyPage.tsx

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ import {
1717
changePassword,
1818
removeAccessToken,
1919
removeRefreshToken,
20+
sendCancelSuccess,
21+
sendCancelCancel,
22+
getSessionId,
2023
} from '@entry/util-config';
2124
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
2225
import { toast } from 'react-toastify';
@@ -118,16 +121,64 @@ export const MyPage = () => {
118121
});
119122

120123
const cancelApplicationMutation = useMutation({
121-
mutationFn: deleteApplication,
122-
onSuccess: () => {
124+
mutationFn: async () => {
125+
const startTime = Date.now();
126+
try {
127+
const result = await deleteApplication();
128+
return { data: result, responseTime: Date.now() - startTime };
129+
} catch (error) {
130+
const responseTime = Date.now() - startTime;
131+
throw { error, responseTime };
132+
}
133+
},
134+
onSuccess: async (result) => {
123135
toast.success('원서 접수가 취소되었습니다.');
136+
137+
const sessionId = getSessionId() || uuidv4();
138+
139+
// 원서 취소 성공 전송
140+
await sendCancelSuccess({
141+
sessionId,
142+
submissionId: applicationStatus?.id || 0,
143+
});
144+
124145
setCancelApplicationOpen(false);
125146
// 원서 상태를 다시 조회하여 UI 업데이트
126147
queryClient.invalidateQueries({ queryKey: ['applicationStatus'] });
127148
},
128-
onError: (error: any) => {
149+
onError: async (errorData: any) => {
150+
const err = errorData.error;
151+
const responseTime = errorData.responseTime || 0;
152+
153+
const sessionId = getSessionId() || uuidv4();
154+
155+
// 에러 상세 정보 생성
156+
const errorDetails = {
157+
httpStatus: err?.response?.status || 0,
158+
errorCode: err?.code || 'UNKNOWN_ERROR',
159+
message: err?.response?.data?.message || err?.message || '원서 취소 중 오류가 발생했습니다.',
160+
responseData: err?.response?.data ? JSON.stringify(err.response.data) : '',
161+
stackTrace: err?.stack || '',
162+
responseTime: responseTime,
163+
endpoint: '/api/v1/applications',
164+
httpMethod: 'DELETE',
165+
};
166+
167+
const reason = `[${errorDetails.httpStatus}] ${errorDetails.message}\n` +
168+
`ErrorCode: ${errorDetails.errorCode}\n` +
169+
`Response: ${errorDetails.responseData}\n` +
170+
`ResponseTime: ${errorDetails.responseTime}ms\n` +
171+
`Stack: ${errorDetails.stackTrace}`;
172+
173+
// 원서 취소 실패 전송
174+
await sendCancelCancel({
175+
sessionId,
176+
submissionId: applicationStatus?.id || 0,
177+
reason,
178+
});
179+
129180
toast.error(
130-
error.response?.data?.message || '원서 취소 중 오류가 발생했습니다.'
181+
err?.response?.data?.message || '원서 취소 중 오류가 발생했습니다.'
131182
);
132183
},
133184
});

libs/util-config/src/meercat/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export * from './utils';
99
export * from './session';
1010
export * from './healthcheck';
1111
export * from './error';
12+
export * from './submission';
1213

1314
export const initializeMeercatEngine = async () => {
1415
let sessionId = getSessionId();
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import type { SubmissionSuccessRequest, SubmissionCancelRequest, CancelSuccessRequest, CancelCancelRequest } from './types';
2+
import { MEERCAT_API_BASE } from './constants';
3+
4+
/**
5+
* 원서 접수 성공 기록
6+
*/
7+
export const sendSubmissionSuccess = async (data: SubmissionSuccessRequest): Promise<void> => {
8+
try {
9+
await fetch(`${MEERCAT_API_BASE}/submission/submission/success`, {
10+
method: 'POST',
11+
headers: { 'Content-Type': 'application/json' },
12+
body: JSON.stringify(data),
13+
});
14+
} catch (error) {
15+
console.error('Submission success reporting failed:', error);
16+
}
17+
};
18+
19+
/**
20+
* 원서 접수 실패 (취소) 기록
21+
*/
22+
export const sendSubmissionCancel = async (data: SubmissionCancelRequest): Promise<void> => {
23+
try {
24+
await fetch(`${MEERCAT_API_BASE}/submission/submission/cancel`, {
25+
method: 'POST',
26+
headers: { 'Content-Type': 'application/json' },
27+
body: JSON.stringify(data),
28+
});
29+
} catch (error) {
30+
console.error('Submission cancel reporting failed:', error);
31+
}
32+
};
33+
34+
/**
35+
* 원서 접수 취소 성공 기록
36+
*/
37+
export const sendCancelSuccess = async (data: CancelSuccessRequest): Promise<void> => {
38+
try {
39+
await fetch(`${MEERCAT_API_BASE}/submission/cancel/success`, {
40+
method: 'POST',
41+
headers: { 'Content-Type': 'application/json' },
42+
body: JSON.stringify(data),
43+
});
44+
} catch (error) {
45+
console.error('Cancel success reporting failed:', error);
46+
}
47+
};
48+
49+
/**
50+
* 원서 접수 취소 실패 (취소의 취소) 기록
51+
*/
52+
export const sendCancelCancel = async (data: CancelCancelRequest): Promise<void> => {
53+
try {
54+
await fetch(`${MEERCAT_API_BASE}/submission/cancel/cancel`, {
55+
method: 'POST',
56+
headers: { 'Content-Type': 'application/json' },
57+
body: JSON.stringify(data),
58+
});
59+
} catch (error) {
60+
console.error('Cancel cancel reporting failed:', error);
61+
}
62+
};

libs/util-config/src/meercat/types.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,25 @@ export interface CreateErrorPayloadParams {
6868
componentName?: string;
6969
userAction?: string;
7070
}
71+
72+
export interface SubmissionSuccessRequest {
73+
sessionId: string;
74+
submissionId: number;
75+
}
76+
77+
export interface SubmissionCancelRequest {
78+
sessionId: string;
79+
submissionId: number;
80+
reason?: string;
81+
}
82+
83+
export interface CancelSuccessRequest {
84+
sessionId: string;
85+
submissionId: number;
86+
}
87+
88+
export interface CancelCancelRequest {
89+
sessionId: string;
90+
submissionId: number;
91+
reason?: string;
92+
}

0 commit comments

Comments
 (0)