Sentry-javascript: μ½˜μ†”μ—λ„ μ˜ˆμ™Έ(`captureException`)λ₯Ό κΈ°λ‘ν•˜λŠ” 방법

에 λ§Œλ“  2018λ…„ 09μ›” 30일  Β·  17μ½”λ©˜νŠΈ  Β·  좜처: getsentry/sentry-javascript

λ‘œμ»¬μ—μ„œ κ°œλ°œν•  λ•Œ Sentry둜 였λ₯˜ 보내기λ₯Ό λΉ„ν™œμ„±ν™”ν•˜μ§€λ§Œ μ—¬μ „νžˆ μ΄λŸ¬ν•œ 였λ₯˜λ₯Ό μ½˜μ†”μ— ν‘œμ‹œν•˜μ—¬ μˆ˜μ •ν•  수 있기λ₯Ό μ›ν•©λ‹ˆλ‹€.

Sentry에 μ˜ˆμ™Έ/이벀트λ₯Ό λ³΄λ‚΄λŠ” 것을 λΉ„ν™œμ„±ν™”ν•˜μ§€λ§Œ μ—¬μ „νžˆ μ½˜μ†”μ— κΈ°λ‘ν•˜λŠ” 방법이 μžˆμŠ΅λ‹ˆκΉŒ?

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

@gaastonsr 당신은 두 번째 인수둜 μˆ˜ν–‰ :) https://docs.sentry.io/learn/filtering/?platform=browser#before -send

Sentry.init({
  dsn: "DSN",
  beforeSend: (event, hint) => {
   if (IS_DEBUG) {
     console.error(hint.originalException || hint.syntheticException);
     return null; // this drops the event and nothing will be sent to sentry
   }
   return event;
  }
});

λͺ¨λ“  17 λŒ“κΈ€

μ΄λŸ¬ν•œ 이유둜 captureException λ₯Ό λž˜ν•‘ν–ˆμŠ΅λ‹ˆλ‹€.

function captureException(...args) {
    if (typeof Sentry !== 'undefined') {
        Sentry.captureException(...args);
    }
    else {
        console.error(...args);
    }
}

κ°€μž₯ 쒋은 방법은 beforeSend
```js
Sentry.init({
dsn: "DSN",
beforeSend: 이벀트 => {
if (IS_DEBUG) {
console.error(이벀트);
null을 λ°˜ν™˜ν•©λ‹ˆλ‹€. // 이것은 이벀트λ₯Ό μ‚­μ œν•˜κ³  아무 것도 μ„ΌνŠΈλ¦¬λ‘œ 보내지 μ•Šμ„ κ²ƒμž…λ‹ˆλ‹€.
}
λ°˜ν™˜ 이벀트;
}
});

beforeSend 에 λŒ€ν•΄ λ§ˆμŒμ— 듀지 μ•ŠλŠ” 점은 μ›λž˜ 였λ₯˜ 개체λ₯Ό 얻지 λͺ»ν•œλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ λ‹΅μž₯을 λ³΄λ‚΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€.

@gaastonsr 당신은 두 번째 인수둜 μˆ˜ν–‰ :) https://docs.sentry.io/learn/filtering/?platform=browser#before -send

Sentry.init({
  dsn: "DSN",
  beforeSend: (event, hint) => {
   if (IS_DEBUG) {
     console.error(hint.originalException || hint.syntheticException);
     return null; // this drops the event and nothing will be sent to sentry
   }
   return event;
  }
});

옴, 이것은 λͺ¨λ“  것을 λ°”κΏ‰λ‹ˆλ‹€! κ°μ‚¬ν•©λ‹ˆλ‹€, @kamilogorek.

λ‚΄ μ½˜μ†”μ΄ 였λ₯˜λ₯Ό κΈ°λ‘ν•˜μ§€ μ•ŠλŠ” 이유λ₯Ό μ°ΎλŠ” 데 30뢄이 κ±Έλ ΈμŠ΅λ‹ˆλ‹€. 이 μž‘μ—…μ€ 더 μ‰¬μ›Œμ•Ό ν•©λ‹ˆλ‹€.

μ—¬κΈ°μ„œ λ¬Έμ œλŠ” 기본적으둜 κΈ°λ‘ν•˜λŠ” 경우 기본적으둜 이동 경둜둜 μΊ‘μ²˜ν•œλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. 그리고 μš°λ¦¬λŠ” 이미 캑처 였λ₯˜μ— λŒ€ν•΄ 이 μž‘μ—…μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€. λ”°λΌμ„œ 쀑볡 ν•­λͺ©μ΄ μƒμ„±λ©λ‹ˆλ‹€.
ν”Όλ“œλ°±μ„ μœ„ν•΄ κ·€κ°€ μ™„μ „νžˆ μ—΄λ € 있고 λˆ„κ΅°κ°€κ°€ 이 λ¬Έμ„œ 뢀뢄을 κ°œμ„ ν•˜λŠ” 방법을 μ•Œκ³  μžˆλ‹€λ©΄ ν¬ν•¨ν•˜κ²Œ λ˜μ–΄ κΈ°μ©λ‹ˆλ‹€. :)

μ—¬κΈ°μ„œ λ¬Έμ œλŠ” 기본적으둜 κΈ°λ‘ν•˜λŠ” 경우 기본적으둜 이동 경둜둜 μΊ‘μ²˜ν•œλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. 그리고 μš°λ¦¬λŠ” 이미 캑처 였λ₯˜μ— λŒ€ν•΄ 이 μž‘μ—…μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€. λ”°λΌμ„œ 쀑볡 ν•­λͺ©μ΄ μƒμ„±λ©λ‹ˆλ‹€.
ν”Όλ“œλ°±μ„ μœ„ν•΄ κ·€κ°€ μ™„μ „νžˆ μ—΄λ € 있고 λˆ„κ΅°κ°€κ°€ 이 λ¬Έμ„œ 뢀뢄을 κ°œμ„ ν•˜λŠ” 방법을 μ•Œκ³  μžˆλ‹€λ©΄ ν¬ν•¨ν•˜κ²Œ λ˜μ–΄ κΈ°μ©λ‹ˆλ‹€. :)

Sentryκ°€ 였λ₯˜λ₯Ό ν¬μ°©ν•˜κ³  μ½˜μ†”μ— ν‘œμ‹œν•˜μ§€ μ•ŠλŠ” 것은 정말 μ˜ˆμƒμΉ˜ λͺ»ν•œ ν–‰λ™μž…λ‹ˆλ‹€!
λ‚˜λŠ” λ˜ν•œ μ½˜μ†”μ΄ κΉ¨λ—ν•˜μ§€λ§Œ λ‚΄ 앱이 μž‘λ™ν•˜μ§€ μ•ŠλŠ” 이유λ₯Ό λ°œκ²¬ν•˜λŠ” 데 ν•œ μ‹œκ°„μ„ λ³΄λƒˆμŠ΅λ‹ˆλ‹€.
이것은 λ°˜λ“œμ‹œ λ³€κ²½λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

μ„œλ²„ 츑의 이동 κ²½λ‘œμ—μ„œ 였λ₯˜λ₯Ό 필터링할 수 μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.
λ˜λŠ” setTimeout μ½œλ°±μ—μ„œ μ½˜μ†”μ— 기둝할 수 μžˆμœΌλ―€λ‘œ 이동 κ²½λ‘œκ°€ 이미 μΊ‘μ²˜λ©λ‹ˆλ‹€. λ‚΄κ°€ ν˜„μž¬ ν•˜λŠ” κ²ƒμ²˜λŸΌ:

Sentry.init({
  dsn: 'DSN',
  beforeSend: (event, hint) => {
    setTimeout(() => console.error(hint.originalException || hint.syntheticException), 0);
    return event;
  }
});

@vitalets 5.9.0 μ—μ„œ λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이제 μ½˜μ†”μ—λ„ 였λ₯˜κ°€ ν‘œμ‹œλ©λ‹ˆλ‹€.

@vitalets 5.9.0 μ—μ„œ λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이제 μ½˜μ†”μ—λ„ 였λ₯˜κ°€ ν‘œμ‹œλ©λ‹ˆλ‹€.

@kamilogorek
sentry/browser 5.9.1 (chrome 78, osx)μ—μ„œλŠ” μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
μ½”λ“œλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

Sentry.init({  dsn: 'dsn' });
setTimeout(() => {throw new Error('abc')}, 3000);

μ½˜μ†”μ΄ λΉ„μ–΄ μžˆμŠ΅λ‹ˆλ‹€. λ„€νŠΈμ›Œν¬ 탭은 였λ₯˜κ°€ μ„ΌνŠΈλ¦¬λ‘œ μ „μ†‘λ˜μ—ˆμŒμ„ λ³΄μ—¬μ€λ‹ˆλ‹€.

μ„ΌνŠΈλ¦¬ 없이 였λ₯˜κ°€ ν‘œμ‹œλ©λ‹ˆλ‹€.

// Sentry.init({  dsn: 'dsn' });
setTimeout(() => {throw new Error('abc')}, 3000);

image

캑처 μ΄λ²€νŠΈκ°€ μ•„λ‹Œ captureException에 λŒ€ν•΄ κΈ°λ‘ν•©λ‹ˆλ‹€.
captureEvent 및 captureException을 κΈ°λ‘ν•˜κΈ° μœ„ν•΄ @kamilogorek 의 μ†”λ£¨μ…˜μ„ μ•½κ°„ μˆ˜μ •ν–ˆμŠ΅λ‹ˆλ‹€.

Sentry.init({
  dsn: "DSN",
  beforeSend: (event, hint) => {
   if (IS_DEBUG) {
     console.error(hint.originalException || hint.syntheticException || event);
     return null; // this drops the event and nothing will be sent to sentry
   }
   return event;
  }
});

@kamilogorek 도 @sentry/node νŒ¨ν‚€μ§€μ˜ κΈ°λ³Έκ°’μΈκ°€μš”? 5.9.0 버전이 있고 beforeSend ν•¨μˆ˜κ°€ ν˜ΈμΆœλ˜λŠ” 것을 λ³Ό 수 μžˆμ§€λ§Œ μ½˜μ†”μ— 아무것도 κΈ°λ‘λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

λ˜ν•œ 5.10.1을 μ‚¬μš©ν•˜λŠ” μ½˜μ†”μ— 였λ₯˜κ°€ ν‘œμ‹œλ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 디버그가 true둜 μ„€μ •λ˜μ–΄ 있으면 λ‘œκΉ…μœΌλ‘œ μΆ©λΆ„ν•©λ‹ˆλ‹€.

μŠ€νŽ™μ„ λκΉŒμ§€ μ•ˆμ½μœΌλ©΄ μ΄λ ‡κ²Œ λ˜λŠ”κ΅¬λ‚˜...

https://html.spec.whatwg.org/multipage/webappapis.html#the -event-handler-processing-algorithm

특수 였λ₯˜ 이벀트 μ²˜λ¦¬κ°€ true인 경우
λ°˜ν™˜ 값이 true이면 이벀트의 μ·¨μ†Œ ν”Œλž˜κ·Έλ₯Ό μ„€μ •ν•©λ‹ˆλ‹€.
그렇지 μ•ŠμœΌλ©΄
λ°˜ν™˜ 값이 false이면 이벀트의 μ·¨μ†Œ ν”Œλž˜κ·Έλ₯Ό μ„€μ •ν•©λ‹ˆλ‹€.

그리고 μŠ€ν¬λ‘€μ„ 내리면...

역사적 이유둜 ν”Œλž«νΌμ—λŠ” 두 가지 μ˜ˆμ™Έκ°€ μžˆμŠ΅λ‹ˆλ‹€.
trueλ₯Ό λ°˜ν™˜ν•˜λ©΄ μ΄λ²€νŠΈκ°€ μ·¨μ†Œλ˜λŠ” μ „μ—­ 객체의 onerror ν•Έλ“€λŸ¬

그에 따라 μ½”λ“œλ₯Ό μ—…λ°μ΄νŠΈν•˜κ² μŠ΅λ‹ˆλ‹€

μŠ€νŽ™ μ•ˆμ½μœΌλ©΄ μƒκΈ°λŠ” 일

아무도 사양을 λκΉŒμ§€ 읽지 μ•ŠμŠ΅λ‹ˆλ‹€. :)

μˆ˜μ •ν•΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€!

이 μŠ€λ ˆλ“œλ₯Ό μ˜¬λ°”λ₯΄κ²Œ 읽고 μžˆλ‹€λ©΄ ν˜„μž¬ μ„ΌνŠΈλ¦¬ λ¦΄λ¦¬μŠ€λŠ” μ½˜μ†”μ— 였λ₯˜λ₯Ό ν‘œμ‹œν•˜λŠ” λ™μ‹œμ— μ„ΌνŠΈλ¦¬ λŒ€μ‹œλ³΄λ“œμ—λ„ 였λ₯˜λ₯Ό 전솑해야 ν•©λ‹ˆλ‹€. 이 λ™μž‘μ΄ λ°œμƒν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

λ‚΄ νŽ˜μ΄μ§€μ— μ„ΌνŠΈλ¦¬λ₯Ό λ‘œλ“œν•˜λŠ” 방법은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

<script src="https://browser.sentry-cdn.com/5.20.1/bundle.min.js" integrity="sha384-O8HdAJg1h8RARFowXd2J/r5fIWuinSBtjhwQoPesfVILeXzGpJxvyY/77OaPPXUo" crossorigin="anonymous"></script>
<script src="https://browser.sentry-cdn.com/5.20.1/vue.min.js" crossorigin="anonymous"></script>

λ‹€μŒμ€ μ΄ˆκΈ°ν™” ν˜ΈμΆœμž…λ‹ˆλ‹€.

  Sentry.init({
    dsn: 'https://_________.ingest.sentry.io/___________',
    integrations: [new Sentry.Integrations.Vue({Vue, attachProps: true})],
  });

λ‹€μŒ 였λ₯˜ 생성 라인을 μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€.

 window.undef.undef += 1;

νŽ˜μ΄μ§€λ₯Ό λ‘œλ“œν•˜κ³  였λ₯˜ 쀄을 νŠΈλ¦¬κ±°ν•˜λ©΄ μ½˜μ†”μ— 아무 것도 ν‘œμ‹œλ˜μ§€ μ•Šμ§€λ§Œ μ„ΌνŠΈλ¦¬ λŒ€μ‹œλ³΄λ“œμ—λŠ” 였λ₯˜κ°€ ν‘œμ‹œλ©λ‹ˆλ‹€. Sentry.init ν˜ΈμΆœμ„ 주석 μ²˜λ¦¬ν•˜λ©΄ js μ½˜μ†”μ— TypeError κ°€ ν‘œμ‹œλ©λ‹ˆλ‹€.

이 μŠ€λ ˆλ“œλ₯Ό 읽은 κ²°κ³Ό js μ½˜μ†”μ—μ„œ 였λ₯˜κ°€ ν‘œμ‹œλ˜λŠ” λ™μ‹œμ— μ„ΌνŠΈλ¦¬ λŒ€μ‹œλ³΄λ“œμ— λ‘œκΉ…ν•  κ²ƒμœΌλ‘œ μ˜ˆμƒν–ˆμŠ΅λ‹ˆλ‹€. μ˜³μ§€ μ•ŠμŠ΅λ‹ˆκΉŒ? μ—¬μ „νžˆ beforeSend 후크λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆκΉŒ?

이제 logErrors: true λ₯Ό Integrations.Vue ν˜ΈμΆœμ— 전달해야 ν•œλ‹€λŠ” 것을 κΉ¨λ‹¬μ•˜μŠ΅λ‹ˆλ‹€.

new Sentry.Integrations.Vue({Vue, attachProps: true, logErrors: true}

μ£„μ†‘ν•©λ‹ˆλ‹€. λ¬Έμ„œλ₯Ό 더 μžμ„Ένžˆ μ½μ—ˆμ–΄μ•Ό ν–ˆμŠ΅λ‹ˆλ‹€!

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰