@sentry/browser
@sentry/node
raven-js
raven-node
_(λ
Έλμ© λ μ΄λΈ)_@angular/core
5.7.1 (@sentry/browser)
8.2.11 (@angular/core)
μ μ ErrorInterceptorκ° μλ Angular μ±μ λν μ΄κΈ° μ€μ μ΄ μμ΅λλ€.
μ¬κΈ° λ΄κ° 보λ΄λ λ°©λ²
const eventId = Sentry.captureException(error.originalError || error);
Sentry.showReportDialog({ eventId });
κ·Έλ¦¬κ³ μ΄ μ€λ₯(ν€λ₯Ό μ¬μ©νμ¬ μΊ‘μ²λ λΉ μ€λ₯ μμΈ: μ€λ₯, ν€λ, λ©μμ§, μ΄λ¦, νμΈ) μ€λ₯κ° κ³μ λ°μνκ³ μ€λͺ μμ 무μμ΄ μλͺ»λμλμ§, μ΄λ»κ² μ¬ννλμ§ μ΄ν΄ν μ μμ΅λλ€.
μ΄κ²μ μ 곡νλ κ°μ²΄κ° Angular μ±μμ μ€ν μΆμ μ 보μ νλ Error
μ μΈμ€ν΄μ€κ° μλμ μλ―Έν©λλ€.
(λ©μμ§κ° κ°λ¦¬ν€λ λλ‘) νμμ λ°λΌ Sentry.captureException(error.error)
λλ Sentry.captureException(error.message)
μ¬μ©ν΄μΌ ν©λλ€.
@kamilogorek μ€μΌμ΄ ) tnx
@kamilogorek μ μ΄ μ€λ₯κ° κ³μ λ°μν©λλ€.
const exception = error.error || error.message || error.originalError || error;
const eventId = Sentry.captureException(exception);
+1, μ΄λ»κ² λ£μ΄λ μ΄ μ€λ₯κ° κ³μ λ°μν©λλ€.
sentry.error-handler.ts
export class SentryErrorHandler extends GeneralErrorHandler {
...
handleError(error) {
...
const exception = error.originalError || error.error || error
Sentry.captureException(exception)
}
}
ν¨ν€μ§.json
{
...
"@angular/core": "^8.2.11",
"@sentry/browser": "^5.7.1",
...
}
λλ μ΄κ²μνκΈ°λ‘ κ²°μ νλ€
Sentry.init({
dsn: environment.sentryUrl,
beforeSend(event, hint) {
/* tslint:disable:no-string-literal only-arrow-functions */
const isNonErrorException =
event.exception.values[0].value.startsWith('Non-Error exception captured') ||
hint.originalException['message'].startsWith('Non-Error exception captured');
/* tslint:enable:no-string-literal only-arrow-functions */
if (isNonErrorException) {
// We want to ignore those kind of errors
return null;
}
return event;
}
});
@gchronos ν΄κ²° λ°©λ²μ κ°μ¬λ립λλ€! μ‘°λ§κ° μμ κ°λ₯μ±μ΄ μκΈ°λ₯Ό λ°λλλ€.
λμκ²λ μ΄λ¬ν μ€λ₯κ° λ°μνλ€κ³ λ§νλ©΄μ μ리λ₯Ό μ§λ₯΄μμμ€. μ λ Angular 8μ μ¬μ©νκ³ μμΌλ©° μ΄μ λν λͺ κ°μ§ λ¬Έμ λ₯Ό μ½μ ν μ€λ₯ μ²λ¦¬ κ΅¬μ± μμμμ μ€λ₯λ₯Ό μ λλ‘ μ²λ¦¬νμ§ λͺ»νλ κ²½μ°μΌ μ μμμ κΉ¨λ¬μμ΅λλ€. captureExceptionμ μ λ¬λκΈ° μ μ μμΈλ₯Ό μ μνλ λ€λ₯Έ μ¬λλ€μ΄ μ μν ν΄κ²° λ°©λ²μ μλνμ§λ§ μ€λ₯κ° μ€μ΄λ€μ§ μμμ΅λλ€. λκ΅°κ° μ΄μ λν΄ μΆκ° μ 보λ₯Ό μ 곡νκ±°λ GChronosμ (κ°μ¬ν©λλ€!) μ루μ μ μ¬μ©ν΄μΌ νλ κ²½μ°μ μ’μ κ²μ λλ€.
+1
+1
λκ΅°κ°κ° μ΄κ²μ λλ²κΉ νλ λ° μ¬μ©ν μμλ μ¬νμ μ 곡 ν μ μμ΅λκΉ? κΈ°λ³Έ angular-cli μ±μ μ¬μ©νλ €κ³ νμ§λ§ μ΄ λμμ μ¬νν μ μμ΅λλ€. κ°μ¬ ν΄μ!
@kamilogorek λλ λΉμ μ΄ μλ‘μ΄ Angular 8 νλ‘μ νΈλ₯Ό μμνκ³ 500μ λ°ννλ λμ μ ν₯ν΄ http μμ²μ ν μ μλ€κ³ λ―Ώμ΅λλ€. κ·Έλ¦¬κ³ Sentryλ‘ μ νλλλ‘ http μλΉμ€μμ μ€λ₯λ₯Ό ν¬μ°©νμ§ λͺ»ν©λλ€.
μ’ λ λ§μ μ 보λ₯Ό μλ €λ릴 μ μμ΅λλ€. μ΄κ²μ μ°λ¦¬μ ErrorHandlerμ λλ€.
@Injectable()
export class SentryErrorHandler implements ErrorHandler {
constructor() { }
handleError(error) {
Sentry.captureException(error.originalError || error.error || error);
}
}
Sentry μΆμ μμλ νμ λ€μ μ΄λ²€νΈμ λν΄ μ€λ³΅ μ΄λ²€νΈλ₯Ό λ°μ΅λλ€.
(λ€λ₯Έ μ΄λ²€νΈλ λͺ©λ‘μ ν νλͺ©μΌλ‘ μ μμ μΌλ‘ λ³΄κ³ λ¨)
μ°λ¦¬λ μλ°± κ°μ "Non.Error" μ΄λ²€νΈλ₯Ό μμ§νμΌλ©° ν₯λ―Έλ‘κ²λ μ΄λ€ λͺ¨λμλ λ€μκ³Ό κ°μ 곡ν΅μ μ΄ μμ΅λλ€.
κ·Έλ¦¬κ³ μ€λ₯λ λλΆλΆ λ€μκ³Ό κ°μ΅λλ€.
{
error: [Object],
headers: [Object],
message: Http failure during parsing for https://foo.bar/baz,
name: HttpErrorResponse,
ok: False,
status: 200,
statusText: OK,
url: https://foo.bar/baz
}
μ’μ, SentryErrorHandlerλ₯Ό μ£Όμ
κ°λ₯νκ² λ λλ§νκ³ νμ₯ λμ ErrorHandlerλ₯Ό ꡬννμΌλ©° λ μ΄μ κ·Έλ° λ¬Έμ κ° μμ΅λλ€.
κ·Έλμ λλ
export class SentryErrorHandler extends ErrorHandler {
constructor() {
super();
}
handleError(err: any): void {
if (environment.production === true || environment.preprod === true) {
Sentry.captureMessage(err.originalError || err);
}
throw err;
}
}
μκ²
@Injectable()
export class SentryErrorHandler implements ErrorHandler {
constructor() { }
handleError(err: any): void {
if (environment.production === true || environment.preprod === true) {
Sentry.captureException(err.originalError || err);
}
throw err;
}
}
λλ λ¬Έμ μμ΄ 2λ λμ 첫 λ²μ§Έ ꡬμ±μ κ°μ§κ³ μμμ§λ§ Angular 8λ‘ μ κ·Έλ μ΄λν μ΄νλ‘ λͺ κ°μ§ μΌνΈλ¦¬ μμΈκ° μμ΅λλ€.
@jonathan-payiq μ΄ λ¬Έμ μ μμΈμ μ°Ύμ μ μμ΅λκΉ? μλλ©΄ μ§κΈ μ€λ₯κ° μλ μμΈλ₯Ό λͺ¨λ 무μν©λκΉ?
μ°λ¦¬λ νμ¬ κ·Έκ²λ€μ 무μνκ³ μμ΅λλ€.
μ°λ¦¬λ μΉλ·°/λΈλΌμ°μ κ° λ°±κ·ΈλΌμ΄λ(보μ΄μ§ μμ)μ μμ λ μ΄λ¬ν μΌμ΄ λ°μνλ€λ κ²μ λΈλ λν¬λΌμμ μμλμΌλ―λ‘ νμ΄μ§κ° νμλμ§ μλ λμ κ°μ Έμ€κΈ°κ° λ°μνμ§ μλλ‘ μμ νμ΅λλ€. λΆλͺ
ν μΌμ± λΈλΌμ°μ λ λ°±κ·ΈλΌμ΄λμμ λ€νΈμν¬ μλ‘ κ³ μΉ¨μ μλͺ» μ²λ¦¬ν©λλ€.
@jonathan-payiq μ νν μ΄λ»κ² 무μν©λκΉ? 미리 κ°μ¬λ립λλ€.
μ°λ¦¬λ νμ¬ κ·Έκ²μ 무μνκΈ° μν΄ λ€μμ μ¬μ©νκ³ μμ΅λλ€.
Sentry.init({
ignoreErrors: [
'Non-Error exception captured'
]
});
@kamilogorek λ¬Έμ λ₯Ό μ¬νν μ μμμ΅λκΉ?
μλ λ¬Έμ κ° λΆλΆμ μΌλ‘ ν΄κ²°λμκ±°λ μλνλ μ루μ
μ΄ μλ κ²μ²λΌ 보μ΄λ―λ‘ λ¬Έμ λ₯Ό μ’
λ£ν©λλ€. μ¬μ ν λ¬Έμ μΈ κ²½μ° λκ΅°κ°κ° μλ‘μ΄ μ€λͺ
μΌλ‘ μ λ¬Έμ λ₯Ό λ§λλ κ²μ μ νΈν©λλ€.
μ¬μ ν κ΄λ ¨μ±μ΄ μλ κ²½μ° μ£Όμ νμ§ λ§κ³ μ μκ² νμ 보λ΄μ£Όμμμ€. κ·Έλ¬λ©΄ κΈ°κΊΌμ΄ λ€μ μ΄μ΄ μμ
νκ² μ΅λλ€.
건배!
ν΄κ²°λμ§ μμμ΅λλ€. λ°©κΈ Sentryλ₯Ό Angular 8κ³Ό ν΅ν©νλ €κ³ μλνλλ° μ΄ λ¬Έμ λ₯Ό λ°κ²¬νμ΅λλ€.
λλ Sentryκ° κΈ°λ³Έ μ€μ μ μ΄λ»κ² μ£Όμ₯ν μ μλμ§ μ΄ν΄κ° λμ§ μμ΅λλ€. κ·Έκ²μ μμ ν κ±°μ§μ λλ€.
λλ Sentryκ° κΈ°λ³Έ μ€μ μ μ΄λ»κ² μ£Όμ₯ν μ μλμ§ μ΄ν΄κ° λμ§ μμ΅λλ€. κ·Έκ²μ μμ ν κ±°μ§μ λλ€.
@Rush λ 무μμ΄ μλͺ»λμλμ§ μ€λͺ νκ³ λ³΄μ¬μ£Όλ μ¬ν κ°λ₯ν μ¬λ‘λ₯Ό μ 곡νλ©΄ κ·νμ μ£Όμ₯μ νμΈν μ μμ΅λλ€.
@kamilogorek μ¬μ€μ 6κ°μ μ΄μ Angularμ ν¨κ» μλνμ§ μκ³ μμΌλ©° μ΄λ₯Ό νμΈν μ μλ λ³΄κ³ μκ° μΆ©λΆνλ―λ‘ IMOμμ λ μ΄μμ μ¬ν μ¬λ‘κ° νμνμ§ μμ΅λλ€. μ€μ€λ‘ κ½€ μ½κ² μ°Ύμ μ μμ΅λλ€. Angular v8μ μ¬μ©νλ νλ‘μ νΈμμ λμΌν λ¬Έμ κ° μκ³ μ΄μ v9(μμ€λ§΅ μμ)κ° μκΈ° λλ¬Έμ κ·Έλ μ§ μλ€λ κ²μ μ€μ€λ‘ μκ³ μμ΅λλ€.
μ νν, κ·Έλ¦¬κ³ Sentryκ° μ λ₯Ό μν΄ μΌν μ μλλ‘ λΉμ©μ μ§λΆνκ³ μμ΅λλ€. λ΄ μμ΄ λλ¬μμ§ κ²μΌλ‘ μμλλ μ€ν μμ€ νλ‘μ νΈκ° μλλλ€.
λλ Sentryλ₯Ό μ’μνμ§λ§ λμμ μ°Ύμ μ μμ΅λλ€ ...
https://github.com/gothinkster/angular-realworld-example-app μ±μ μλ‘ λ€μ΄ λͺ¨λκ° λμΌν μ¬μμ°μ ν μ μλλ‘ νμ΅λλ€.
Bareboneμ μ±μ 볡μ νκ³ Sentryμ Angular λ¬Έμλ₯Ό λ°λ₯΄κ³ μμ€ λ§΅μ μ λ‘λνμ΅λλ€. κ²°κ³Όλ λ€μκ³Ό κ°μ΅λλ€.
Angularκ° μ€λ₯ μ²λ¦¬κΈ°μμ μ 곡νλ κ² + μΊ‘μ²ν μ΄λ²€νΈ:
UIμμ μ΄λ»κ² 보μ΄λμ§:
μ°Έκ³ : λͺ¨λ κ²μ΄ μ μ리μ μμ΅λλ€. Angularκ° μμ
ν μ 체 Error
κ°μ²΄λ₯Ό μ 곡νκΈ° λλ¬Έμ μ€λ₯ λ©μμ§ λ° μ€λ₯ μ νμ΄ μ¬λ°λ₯Έ μ¬λ°λ₯Έ μ½λ μ€μ μ½κ² κ°λ¦¬ν¬ μ μμ΅λλ€.
Angularκ° μ€λ₯ μ²λ¦¬κΈ°μμ μ 곡νλ κ² + μΊ‘μ²ν μ΄λ²€νΈ:
UIμμ μ΄λ»κ² 보μ΄λμ§:
μ°Έκ³ : Angularκ° μ΄ μ 보λ₯Ό μ 곡νμ§ μκΈ° λλ¬Έμ μ΄λ€ μ νμ μ€λ₯κ° λ°μνλμ§ μ μ μλ λ°©λ²μ΄ μμ΅λλ€. κ·Έλ¬λ μ§λ ¬νλ λ°μ΄ν°λ₯Ό μ΄ν΄λ³΄λ©΄ "404 Not Found" μ€λ₯κ° λ°μνμμ μ μ μμ΅λλ€. μ΄ μ€λ₯λ _λλΆλΆμ_ μλͺ»λ XHR νΈμΆμμ λ°μνμ΅λλ€. κ·Έλ° λ€μ νμκ²½λ‘ νλ¦μ μ‘°μ¬νμ¬ _μ¬μ€_ μ£Όμ΄μ§ URL(μ΄ κ²½μ° μ€νκ° ν¬ν¨λ¨)μ λν XHR νΈμΆμ΄ μμκ³ μ νν DOM μμλ₯Ό ν΄λ¦ν ν μ΄λ₯Ό νΈλ¦¬κ±°νλμ§ νμΈν μ μμ΅λλ€. μ΄ μ 보λ₯Ό μ¬μ©νλ©΄ 99%μ κ²½μ° λ¬Έμ λ₯Ό ν΄κ²°νκΈ°μ μΆ©λΆν©λλ€.
μ°λ¦¬λ νλ μμν¬μμ μ£Όμ΄μ§ κ²λ§μΌλ‘ μμ ν μ μμ΅λλ€. κ·Έλ μ§ μμΌλ©΄ νλ μμν¬ μ체λ₯Ό μμμ΄ ν¨μΉν΄μΌ ν©λλ€.
μ°λ¦¬λ νλ μμν¬μμ μ£Όμ΄μ§ κ²λ§μΌλ‘ μμ ν μ μμ΅λλ€. κ·Έλ μ§ μμΌλ©΄ νλ μμν¬ μ체λ₯Ό μμμ΄ ν¨μΉν΄μΌ ν©λλ€.
μ΄κ²μ΄ "μ°λ¦¬μ λ¬Έμ κ° μλλ€"λΌκ³ λ§νλ λΉμ μ λ°©μμ λκΉ? (μΌλΆ κ²½μμ 체μ) μΌνΈλ¦¬λ‘ μ ννκΈ° μ μ μ΄λ¬ν XHR μ€λ₯λ μ μΊ‘μ²λμμΌλ©° κ°λ μ€λ₯ μ²λ¦¬κΈ°μ λμΌν μ€μΉ λ°©λ²μ μ¬μ©νμ΅λλ€.
@kamilogorek λ²€λλ‘μ νλ μμν¬λ‘ ν°μΌμ μ΄ μλ μμ΅λλ€. λλ κ·Έκ²μ΄ μ½κ°μ κ΄μ¬μ λ κ²μ΄λΌκ³ νμ ν©λλ€.
(μΌλΆ κ²½μμ 체μ) μΌνΈλ¦¬λ‘ μ ννκΈ° μ μ μ΄λ¬ν XHR μ€λ₯λ μ μΊ‘μ²λμμΌλ©° κ°λ μ€λ₯ μ²λ¦¬κΈ°μ λμΌν μ€μΉ λ°©λ²μ μ¬μ©νμ΅λλ€.
@szechyjs κ·Έλ λ€λ©΄ μ€ν μμ€ SDKμ΄κ³ μ°λ¦¬κ° λͺ©νλ‘ νλ κ²μ μλ€λ©΄ κ°μ μ¬νμ λ°λ³΅ν μ μκΈ° λλ¬Έμ λμ μ루μ μ 곡μ ν μ μλ€λ©΄ μ’μ κ²μ λλ€.
... νλ μμν¬λ‘ ν°μΌμ μ΄ μλ μμ΅λλ€. λλ κ·Έκ²μ΄ μ½κ°μ κ΄μ¬μ λ κ²μ΄λΌκ³ νμ ν©λλ€.
λ°©κΈ μΌνΈλ¦¬ μ§μμ ν΅ν΄ ν°μΌμ μ΄κ³ μ΄ λ¬Έμ λ₯Ό μΈκΈνμ΅λλ€.
μ¬κΈ° μ§λκ°λ μ¬λ. μ κ²½μ°μλ λ°μ λ€μ΄ν°λΈμμ μ²λ¦¬λ κ±°λΆλ₯Ό λ³΄κ³ νκ³ OPμ λμΌν μ€λ₯κ° νμλμμ΅λλ€. the object you provide is not an instance of Error
μ΄νλ‘ μλλ₯Ό μ¬μ©νμ΅λλ€.
export interface IError extends Error {
code?: ErrorCode
msg?: string
}
export const appError = (code: ErrorCode, msg: string = ''): IError => {
const errmsg = `code: ${code}, msg: ${msg}`
const err: IError = new Error(errmsg)
err.code = code
err.msg = msg
err.name = 'appError'
return err
}
κ·ΈλΌ λ μ ν
export const logError = (err: Error) => {
sentry.captureException(err)
}
κ·Έλ¦¬κ³ λλ λ³Έλ€
λμμ΄ λμκΈ°λ₯Ό λ°λλλ€!
μ κ²½μ°μλ Sentryμ Breadcrumbs μΉμ μ΄ μμΈμ μ°Ύλ λ° λ§μ λμμ΄ λμμ΅λλ€. μΌλΆ μΈλΆ APIμ 404κ°κ° μμ λ μ£Όλ‘ λ°μνμ΅λλ€.
λ¬Έμ μ λ°μ΄νΈ λ° νμν JS SDK λ³κ²½μ΄ μμ λμ΄ μμ΅λλ€.
https://github.com/getsentry/sentry-docs/pull/1695/
https://github.com/getsentry/sentry-javascript/pull/2601
μ΄λ² μ£Όμ μΆμλμ΄μΌ ν©λλ€! :)
μ΄μ λν μμ¬μ΄ μμ (HTTP κ°λ‘μ±λ μ€λ₯μμλ§ λ°μ):
handleError(error: Error | HttpErrorResponse | any) {
// ...
if (error.constructor.name === "HttpErrorResponse") {
error.error.Message + " (" + error.message + ")";
error = error.error;
}
// ...
Sentry.captureMessage(err.originalError || err.error || error);
throw err;
}
μλ‘μ΄ λ¬Έμμ 5.16.0
λ°©κΈ μΆμλμμ΅λλ€ - https://docs.sentry.io/platforms/javascript/angular/
μ΅λν λͺ
μμ μ΄κ³ μμΈνκ² λ§λ€λ €κ³ λ
Έλ ₯νκ³ , κ·Έλ κΈ° λλ¬Έμ λ§μ μ½λμ²λΌ λ³΄μΌ μ μμ΅λλ€.
@kamilogorek Vue μ±
μ¬κΈ°λ λ§μ°¬κ°μ§μ
λλ€. vuejs μΌνΈλ¦¬ ν΅ν© μ€λ₯ νΈλ€λ¬μμ μμΈκ° λ°μν©λλ€.
https://sentry.io/share/issue/eaf13a2455e04150aaaab595d0d7bafe/
@sblawrie μ νν μ΄λ€ λ¬Έμ κ° μμ΅λκΉ? μ’ λ μμΈν λ΄μ©μ΄ λμμ΄ λ κ²μ
λλ€.
@cincauhangus μ½λ μ΄λκ°μ promise μΈμ€ν΄μ€ μ체μ μ€λ₯κ° λ°μνλ κ² κ°μ΅λλ€( abort, always, catch, done
ν€ μ°Έκ³ ).
λ€μκ³Ό κ°μ κ²:
const promise = new Promise((resolve, reject) => (...));
// somehow somewhere in the code
function foo () {
// ...
throw promise
}
λ°λΌμ Vueμ errorHandler
λ Error
μΈμ€ν΄μ€κ° λ κ²μΌλ‘ μμλλ μ 체 μ½μ κ°μ²΄λ₯Ό κ°μ Έμ΅λλ€.
@kamilogorek μ€λͺ κ°μ¬ν©λλ€. λͺ κ°μ§λ₯Ό λ³κ²½νμΌλ©° μ¬μ ν λ¬Έμ κ° μλμ§ λͺ¨λν°λ§ν κ²μ λλ€.
Angular 8μ μ¬μ©νκ³ λμΌν λ¬Έμ κ° λ°μνμ΅λλ€. Non-Error μμΈ. μμ 'extractError' μ½λλ₯Ό λ€μκ³Ό κ°μ΄ μμ νμ΅λλ€.
private static extractError(error: any) {
// Try to unwrap zone.js error.
// https://github.com/angular/angular/blob/master/packages/core/src/util/errors.ts
if (error && error.ngOriginalError) {
error = error.ngOriginalError;
}
// We can handle messages and Error objects directly.
if (typeof error === 'string' || error instanceof Error) {
return error;
}
// If it's http module error, extract as much information from it as we can.
if (error instanceof HttpErrorResponse) {
// The `error` property of http exception can be either an `Error` object, which we can use directly...
if (error.error instanceof Error) {
return error.error;
}
// ... or an`ErrorEvent`, which can provide us with the message but no stack...
if (error.error instanceof ErrorEvent) {
return error.error.message;
}
// ...or the request body itself, which we can use as a message instead.
if (typeof error.error === 'string') {
return `Server returned code ${error.status} with body "${error.error}"`;
}
// If we don't have any detailed information, fallback to the request message itself.
return error.message;
}
// ***** CUSTOM *****
// The above code doesn't always work since 'instanceof' relies on the object being created with the 'new' keyword
if (error.error && error.error.message) {
return error.error.message;
}
if (error.message) {
return error.message;
}
// ***** END CUSTOM *****
// Skip if there's no error, and let user decide what to do with it.
return null;
}
μμ @untilinvite μ beforeSend μμ λ₯Ό κΈ°λ°μΌλ‘ λ΄ Sentry.init beforeSendλ₯Ό μμ νμ΅λλ€. μ΄ λ³κ²½ μ¬νμ https://github.com/getsentry/sentry-javascript/issues/2169 μ λ λ²μ§Έ λ‘κ·Έ λ©μμ§λ λΉ μ€λ₯λ‘ ν΄μλλ κ²μ μ²λ¦¬νκΈ° μν κ²μ λλ€.
Sentry.init({
dsn: AppConfig.envSettings.sentryDSN,
maxBreadcrumbs: 50,
environment: this.getEnvName(),
integrations: [new Sentry.Integrations.Breadcrumbs({ console: false })],
beforeSend(event, hint) {
// Note: issue with double entries during http exceptions: https://github.com/getsentry/sentry-javascript/issues/2169
// Note: issue with a second entry not being set correctly (as a non-error): https://github.com/getsentry/sentry-javascript/issues/2292#issuecomment-554932519
const isNonErrorException = event.exception.values[0].value.startsWith('Non-Error exception captured');
if (isNonErrorException) {
if (!event.extra.__serialized__) {
return null;
}
let realErrMsg = event.extra.__serialized__.error ? event.extra.__serialized__.error.message : null;
realErrMsg = realErrMsg || event.extra.__serialized__.message;
// this is a useless error message that masks the actual error. Lets try to set it properly
event.exception.values[0].value = realErrMsg;
event.message = realErrMsg;
}
return event;
}
});
5.16.0
릴리μ€λ‘ λ¬Έμμ μΆκ°λ λ³κ²½ μ¬νμ μ μ©νμ§λ§ μ¬μ ν Non-Error exception captured with keys: error, headers, message, name, ok
μ€λ₯κ° λ°μν©λλ€. @sentry/angular ν¨ν€μ§κ° μ΄λ¬ν λ¬Έμ λ₯Ό ν΄κ²°νκΈ°λ₯Ό λ°λλλ€.
κ°λ: v9.1
μΌνΈλ¦¬: v5.20
@szechyjs http μΈν°μ ν°μ λν λ λ²μ§Έ λΆλΆλ μ½μμ΅λκΉ? μ΄κ²μ μΌλ°μ μΌλ‘ μ¬λ°λ₯΄κ² κ°μ§λμ§ μλ μ€λ₯λ₯Ό λνλ΄λ μ£Όμ λ¬Έμ μ λλ€ - https://docs.sentry.io/platforms/javascript/angular/
@szechyjs http μΈν°μ ν°μ λν λ λ²μ§Έ λΆλΆλ μ½μμ΅λκΉ? μ΄κ²μ μΌλ°μ μΌλ‘ μ¬λ°λ₯΄κ² κ°μ§λμ§ μλ μ€λ₯λ₯Ό λνλ΄λ μ£Όμ λ¬Έμ μ λλ€ - https://docs.sentry.io/platforms/javascript/angular/
μ°λ¦¬λ μΈν°μ ν°λ₯Ό μ¬μ©νμ§ μμ΅λλ€.
μλ
νμΈμ, μ λ μ΄ λ¬Έμ μ λν΄ μκ°μ 보λκ³ HttpErrorResponse
μ νμ μ€λ₯μ λν error.error.message
μ μ λ³΄κ° λ°λμ ν¬ν¨λμ΄ μμ§λ μλ€λ κ²μ λ°κ²¬νμ΅λλ€. μμ±μλ₯Ό 보면 Angularκ° ErrorEvent
μλλΌ λ£¨νΈ κ°μ²΄μ message propμ μ€μ νλ€λ κ²μ μ μ μμ΅λλ€.
μ΄ μ€μ λ³κ²½νμ¬ https://github.com/getsentry/sentry-javascript/blob/8eb72865dcd62ff719441105c7eda28007a07e9d/packages/angular/src/errorhandler.ts#L112
μκ²
if (error.error instanceof ErrorEvent && error.error.message)
μ€λ₯ μ²λ¦¬κΈ°κ° return error.message;
μ§ννμ¬ μμ μ€λ₯λ₯Ό λ°μμμΌ°μ΅λλ€.
μ’μ μΊμΉ @jakkn , κ°μ¬ν©λλ€! PR https://github.com/getsentry/sentry-javascript/pull/2903μ μ λ°μ΄νΈλ μ²λ¦¬κΈ°
λ°©κΈ μμν Express μ±μμ μ΄ λ¬Έμ κ° λ°μν©λλ€. μ΄λ»κ² μ΄λ° μΌμ΄ μΌμ΄λ μ μλμ§ λͺ¨λ₯΄μ§λ§ μ±μμ λ°μνλ λλΆλΆμ μ€λ₯μ λν΄ λ°μνλ κ²μΌλ‘ 보μ΄λ©° λ¬Έμμμ νμ€ Express μ€μ μ μ¬μ©νκ³ μμ΅λλ€.
μ: https://sentry.io/share/issue/bfd4f674c10b4b4a8b6a291dde8e2a66/
λΉλ‘ κ·Έκ²μ΄ κ°λκ° μλλΌ μ΅μ€νλ μ€ μμ² νΈλ€λ¬λ₯Ό μν κ²μ΄μ§λ§, λλ μ΄μ κ°μ μ€λ₯λ₯Ό μ³€λ€. κΈ°λ³Έμ μΌλ‘ Error κ°μ²΄ λμ pojoλ‘ next
λ₯Ό νΈμΆνμ΅λλ€. λλ κ·Έκ²μ ν₯λ―Έλ‘μ΄ κ²μΌλ‘ λ°κΎΈκΈ° μν΄ λ΄ κ³ μ μ μ΅μ€νλ μ€ μ€λ₯ μ²λ¦¬κΈ°μμ λͺ κ°μ§ μ¬λ―Έμλ μμ
μ μννμ§λ§ sentryio μμ² λ―Έλ€μ¨μ΄κ° λ¨Όμ μ€νλκΈ° λλ¬Έμ μ΄ μ λ ¬λ μ€λ₯κ° λ°μνμ§ μμ΅λλ€.
κ²°κ΅, μ 곡λ λͺ¨λ κ²μ λ ν©λ¦¬μ μΈ κ²μΌλ‘ λ°κΎΈλ μ νΈλ¦¬ν° ν¨μλ₯Ό λ§λ€μμ΅λλ€.
export const handleMaybeError = err => {
if (err instanceof Error) return err
const newErr = new Error(err.message || 'unexpected')
for (const [key, value] of Object.entries(err)) {
newErr[key] = value
}
return newErr
}
export const someController = (req, res, next) => {
try {
await handleResponse(req, res)
} catch (err) {
next(handleMaybeError(err))
}
}
μ΄κ²μ μ€ν μΆμ μ λ€μ€ννλ€κ³ μκ°νμ§λ§ μ€μ λ‘ μ΄κ²μ΄ μ λ¬ λ pojoλΌλ©΄ μ΄μ¨λ μ€ν μΆμ μ΄ μμμ΅λλ€.
μ΄ λ¬Έμ κ° μμ λκΈ° μ μ λ³΄κ³ λ μ΄λ²€νΈμ λλΆλΆμ μ΄ νΉμ λ¬Έμ μ λν κ²μ΄λ©° μ₯κΈ° μ€ν λ Έλ μΉ μλ²μ΄κΈ° λλ¬Έμ μ΄λ κ²½λ‘λ κ±°μ μΈλͺ¨κ° μμΌλ©° λͺ¨λ μ€λ₯λ μ΄ νλμ μ΄λ²€νΈ μ νμ μ§μ€λ©λλ€.
const μμΈ = error.error || μ€λ₯ λ©μμ§ || error.originalμ€λ₯ || μ€λ₯;
μ΄κ²μ μ°Έ/κ±°μ§μΌλ‘ νκ°λ κ²μ λλ€
const μμΈ = error.error || μ€λ₯ λ©μμ§ || error.originalμ€λ₯ || μ€λ₯;
μ΄κ²μ μ°Έ/κ±°μ§μΌλ‘ νκ°λ κ²μ λλ€
κ°λ₯μ±μ μμ§λ§ κ°λ₯ν©λλ€. κ·Έκ²μ λͺ¨λ λΉμ μ΄ μ€νΈλ¦ΌμΌλ‘ 보λ΄λ "μ€λ₯"μ λ¬λ € μμ΅λλ€. κ·Έλ¬λ κ²°κ΅ μ¬κΈ°μλ μΌμ’ μ μ μ©ν μ λ³΄κ° ν¬ν¨λμ΄μΌ ν©λλ€.
κ°μ₯ μ μ©ν λκΈ
μ°λ¦¬λ νμ¬ κ·Έκ²μ 무μνκΈ° μν΄ λ€μμ μ¬μ©νκ³ μμ΅λλ€.