-
Notifications
You must be signed in to change notification settings - Fork 0
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
[Re-Open] Sentry 연동, 코드베이스에 Exception Filter, Response Interceptor 적용 #8
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
cf28787
Chore: SENTRY_DSN 추가
J-Hoplin 8180c3e
Feature: Base Exception Filter 추가. Sentry 연동 추가 및 Custom Error에 대해 Se…
J-Hoplin 44afb09
Feature: ICommonResponse타입에 호환되는 Base Response Interceptor 추가
J-Hoplin f7efac1
Feature: Filter 설정시 Sentry 연결 여부에 따른 분리(nestFilterConfig(app))
J-Hoplin 20c046d
Fix: Response Type 수정 Composite Type으로 변경 및 적용
J-Hoplin b24ae7d
Merge branch 'development' into feature/error-handling
J-Hoplin 3a97d5f
Chore: Build workflow에서 pnpm version 명시 해제
J-Hoplin 39f1e5e
Chore: pnpm worflow 설정 변경
J-Hoplin 71cdc39
Feat: Response Config 추가
J-Hoplin 6e37402
Chore: pnpm ci 수정
J-Hoplin fba38ca
Merge branch 'development' into feature/error-handling
J-Hoplin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
MONGO_URL=mongodb+srv://linkit-dev:[email protected]/linkit-dev | ||
MONGO_URL="mongodb+srv://<UserName>:<Password>@<Host>/<DB>?<External Options>" | ||
SENTRY_DSN="Sentry DSN" | ||
JWT_SECRET="JWT Secret" | ||
JWT_EXPIRE_TIME="Expire Time" | ||
JWT_EXPIRE_TIME="Expire Time" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { ExceptionPayload } from '../types/type'; | ||
|
||
export abstract class RootException< | ||
T extends ExceptionPayload = ExceptionPayload, | ||
U extends number = number, | ||
> extends Error { | ||
constructor( | ||
public readonly payload: T, | ||
public readonly statuscode: U, | ||
public readonly name: string, | ||
) { | ||
super(); | ||
this.message = payload.message as string; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { ExceptionPayload } from '../types/type'; | ||
import { RootException } from './exception.abstract'; | ||
|
||
const codeUnknown = 'Unknown'; | ||
|
||
export const createException = ( | ||
statusCode: number, | ||
message: string, | ||
code = codeUnknown, | ||
) => { | ||
const payload: ExceptionPayload = { | ||
code: code, | ||
message: message, | ||
}; | ||
|
||
const errorContextName = | ||
code === codeUnknown ? `${codeUnknown} - ${message}` : code; | ||
return class extends RootException { | ||
constructor() { | ||
super(payload, statusCode, errorContextName); | ||
} | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './exception.abstract'; | ||
export * from './exception.factory'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { | ||
ArgumentsHost, | ||
Catch, | ||
ExceptionFilter, | ||
HttpException, | ||
} from '@nestjs/common'; | ||
import { captureException } from '@sentry/node'; | ||
import { Response } from 'express'; | ||
import { RootException, createException } from '../error'; | ||
import { ExceptionPayload, ICommonResponse } from '../types/type'; | ||
|
||
@Catch() | ||
export class RootExceptionFilter implements ExceptionFilter { | ||
private unknownCode = 'Unknown'; | ||
|
||
catch(exception: any, host: ArgumentsHost) { | ||
const context = host.switchToHttp(); | ||
const response: Response = context.getResponse<Response>(); | ||
let targetException = exception; | ||
let responseStatusCode = 500; | ||
let responseErrorPayload: ExceptionPayload = { | ||
code: this.unknownCode, | ||
message: '', | ||
}; | ||
|
||
// If exception is http exception instance | ||
if (targetException instanceof HttpException) { | ||
// Response Message | ||
const response = targetException.getResponse(); | ||
// Response Status Code | ||
responseStatusCode = targetException.getStatus(); | ||
responseErrorPayload = { | ||
code: this.unknownCode, | ||
message: response, | ||
}; | ||
} | ||
// Custom Exception | ||
else if (targetException instanceof RootException) { | ||
// Response Message | ||
const response = targetException.payload; | ||
// Response Status Code | ||
const statusCode = targetException.statuscode; | ||
responseErrorPayload = response; | ||
responseStatusCode = statusCode; | ||
} | ||
// Error | ||
else { | ||
const errorMessage = targetException.message; | ||
// Response Status Code | ||
responseStatusCode = 500; | ||
// Response Message | ||
responseErrorPayload = { | ||
code: this.unknownCode, | ||
message: errorMessage, | ||
}; | ||
targetException = new (class extends createException( | ||
responseStatusCode, | ||
errorMessage ?? exception.name, | ||
this.unknownCode, | ||
) {})(); | ||
} | ||
captureException(targetException); | ||
const exceptionResponse: ICommonResponse = { | ||
success: false, | ||
error: responseErrorPayload, | ||
}; | ||
|
||
return response.status(responseStatusCode).json(exceptionResponse); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './base.filter'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
export * from './error'; | ||
export * from './filter'; | ||
export * from './interceptor'; | ||
export * from './decorators'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './response.interceptor'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { CallHandler, ExecutionContext, NestInterceptor } from '@nestjs/common'; | ||
import { Observable, map } from 'rxjs'; | ||
import { ICommonResponse } from '../types/type'; | ||
|
||
export class CommonResponseInterceptor implements NestInterceptor { | ||
intercept( | ||
context: ExecutionContext, | ||
next: CallHandler<any>, | ||
): Observable<any> | Promise<Observable<any>> { | ||
return next.handle().pipe( | ||
map((payload = {}): ICommonResponse => { | ||
return { | ||
success: true, | ||
data: payload, | ||
}; | ||
}), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
200번대면 성공, 400, 500번대면 실패라는 싱크를 프론트와 맞춘다면 success필드를 없애고 depth를 하나 없앨 수 있겠다는 생각이 드는데 준호 생각은 어때?!
success필드나 response형태에 대해서 프론트 애들이랑 해커톤 시작 때 얘기해봐도 좋겠다는 생각이 드네!
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 관련해서는 전부터 의견이 분분한 영역인 거 같아서!
@J-Hoplin @hye-on @JonghunAn
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.
Status Code로 실패 여부 확인하는것도 괜찮을꺼같아!
success
프로퍼티를 추가한 이유는 Payload에서succes
랑 에러코드로 바로 구분하게 한다면 클라이언트에서 body만 가져와서 바로 판별 할 수 있으니까 더 편하지 않을까라는 생각으로success
필드를 추가했었어!형 그러면 response payload도 동일하게
data
,error
필드 구분 없이 한 depth로 만 payload 전송하는거를 말하는거야?? 약간 에러케이스랑 성공케이스에서 동일하게 응답 payload형태를 맞출려고ICommonResponse
타입으로 반환하는거로 작성했는데, 기본적으로 한 depth가 생기는 것에 대해 클라이언트 분들 의견을 아직 못 물어봤었어. 형이 말한 것처럼 같이 이야기 해서 맞춰보는 과정이 필요할것같아!