@sentry/browser
@sentry/node
raven-js
raven-node
_(๋
ธ๋์ฉ ๋ ์ด๋ธ)_@sentry/browser": "4.4.2"
์๋
ํ์ธ์ ์ฌ๋ฌ๋ถ,
์์์ ์ค๋ช
ํ ๊ฒ์ฒ๋ผ Angular6 + Ngrx6์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
๋ด๊ฐํ๊ณ ์ถ์ ๊ฒ์ webApp์ด API ํธ์ถ์ ์คํจํ์ ๋ Sentry์ ์ค๋ฅ๋ฅผ ๋ณด๋ด๋ ๊ฒ์
๋๋ค.
์กด์ฌํ์ง ์๋ /abc/3
๋ผ๋ API๋ฅผ ํธ์ถํ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค.
๊ทธ๋ฐ ๋ค์ ํด๋ผ์ด์ธํธ์ 404 Not Found
์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ @sentry/browser
๋ฅผ ํตํด Sentry์ ๋ณด๋ด๊ณ ์ถ์ ๊ฒ์
๋๋ค.
๊ฐ๋จํ ์๋น์ค๋ฅผ ๋ง๋ค์์ต๋๋ค.
@Injectable({
providedIn: 'root'
})
export class SentryService {
constructor() { }
captureException(error: any) {
Sentry.captureException(error.originalError || error);
throw error;
}
}
Angular์ ErrorHandler
๋ฅผ ํ์ฅํ๋ SentryErrorHandler
๋ฅผ ๋ง๋ค์์ต๋๋ค.
@Injectable()
export class SentryErrorHandler implements ErrorHandler {
constructor(private sentry: SentryService) {}
handleError(error: any): void {
this.sentry.captureException(error);
throw error;
}
}
์ด ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ ์ผ๋ฐ์ ์ธ js ์ค๋ฅ๋ฅผ ์ ๊ฐ์งํฉ๋๋ค.
abcdefg(); // <- this function doesn't exist so it occurs an error and sent to Sentry.
๊ทธ๋ฐ๋ฐ ์์ ์ฝ๋๊ฐ ๋คํธ์ํฌ ์ค๋ฅ๋ฅผ ๊ฐ์งํ์ง ๋ชปํ๋ค๋ ๊ฒ์ ์๊ฒ ๋์์ต๋๋ค. ( ๋ด๊ฐ ๋งํ๋ฏ์ด /abc/3
)
๊ทธ๋์ Angular์ HttpInterceptor
ErrorInterceptor
๋ฅผ ๋ง๋ค์์ต๋๋ค.
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
constructor(
private _injector: Injector,
private sentry: SentryService
) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req)
.pipe(
tap(event => {}, error => {
if (error) {
this.sentry.captureException(error);
}
})
);
}
}
๊ทธ๋ฐ ๋ค์ ๋คํธ์ํฌ ์ค๋ฅ๋ฅผ ์ก์ ์ ์์ต๋๋ค.
ํ์ง๋ง ๋ฌธ์ ๋ ๋ด Sentry ๋์๋ณด๋์์ ์๋ฌด๊ฒ๋ ๋ณผ ์ ์๋ค๋ ๊ฒ์
๋๋ค.
๋ด Chrome ๋คํธ์ํฌ ํญ์ ํ์ธํ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ค์๊ณผ ๊ฐ์ ๋ฉ์์ง๋ฅผ ์ฐพ์ ์ ์์์ต๋๋ค.
"ํค๋ก ์บก์ฒ๋ ์ค๋ฅ๊ฐ ์๋ ์์ธ: ์ค๋ฅ, ํค๋, ๋ฉ์์ง, ์ด๋ฆ, ํ์ธ..."
๊ทธ๋์ @sentry/browser๋ ์ด๊ฒ์ด ์ค๋ฅ๋ผ๊ณ ์๊ฐํ์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋๋ ๋ํ Non-Error exception captured with keys: error, headers, message, name, okโฆ
์ ๋ํด ์ด์ผ๊ธฐํ๋ ๊ฒ์ ๋ฐ๊ฒฌ ํ์ต๋๋ค .
์ฌ๊ธฐ ๋ด ์ง๋ฌธ์ด ์์ต๋๋ค.
๊ฐ์ฌ ํด์!
@Taewa Angular๊ฐ ๋์ง ์ค๋ฅ ๊ฐ์ฒด๋ SentryEvent
์ ๊ฐ์ ํ์์ด ์๋๋๋ค.
ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ผ๋ถ ์ค๋ฅ ์ ๋ณด์ ํจ๊ป captureMessage(message: string)
๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค. ๊ทธ๊ฒ์ ๋ด๊ฐ ์ ํํ ๋ ๊ฐ๋จํ ๋ฐฉ๋ฒ์
๋๋ค. https://github.com/pascaliske/ngx-sentry/blob/master/projects/ngx-sentry/src/lib/sentry.interceptor.ts
๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ Sentry ์ด๋ฒคํธ ๊ฐ์ฒด๋ฅผ ์ง์ ๋ง๋ค๊ณ captureEvent(event: SentryEvent)
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ Sentry๋ก ๋ณด๋ด๋ ๊ฒ์
๋๋ค.
๋์์ด ๋์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ๐
@pascaliske ๊ฐ์ฌํฉ๋๋ค
๋๋ ์ค์ ๋ก ๋น์ ์ด ์ธ๊ธ ํ captureMessage(message: string)
๋ฅผ ์ฌ์ฉํ์ฌ ํด๊ฒฐํ์ต๋๋ค.
์์ผ๋ก ์ฐพ์์ค์๋ ๋ถ๋ค์๊ฒ ๋์์ด ๋ ๊ฒ ๊ฐ์ต๋๋ค :)
์ด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋ ๊ฒ ๊ฐ์์ ์ข ๋ฃํฉ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
@Taewa Angular๊ฐ ๋์ง ์ค๋ฅ ๊ฐ์ฒด๋
SentryEvent
์ ๊ฐ์ ํ์์ด ์๋๋๋ค.ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ผ๋ถ ์ค๋ฅ ์ ๋ณด์ ํจ๊ป
captureMessage(message: string)
๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค. ๊ทธ๊ฒ์ ๋ด๊ฐ ์ ํํ ๋ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ๋๋ค. https://github.com/pascaliske/ngx-sentry/blob/master/projects/ngx-sentry/src/lib/sentry.interceptor.ts๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ Sentry ์ด๋ฒคํธ ๊ฐ์ฒด๋ฅผ ์ง์ ๋ง๋ค๊ณ
captureEvent(event: SentryEvent)
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ Sentry๋ก ๋ณด๋ด๋ ๊ฒ์ ๋๋ค.๋์์ด ๋์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ๐