Sentry-javascript: ์˜คํ”„๋ผ์ธ ๋ณด๊ณ  ๋ฐฉํ–ฅ์€?

์— ๋งŒ๋“  2014๋…„ 10์›” 31์ผ  ยท  27์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: getsentry/sentry-javascript

์•ˆ๋…•ํ•˜์„ธ์š”. ์˜คํ”„๋ผ์ธ ๊ธฐ๋Šฅ์ด ๋ฐฐํฌ๋œ ์›น ์•ฑ์ด ์žˆ์œผ๋ฉฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ชจ๋‹ˆํ„ฐ๋ง์— Sentry๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ด๋ฏธ ๊ทธ๊ฒƒ์„ ๋ฐฑ์—”๋“œ์— ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ํ›Œ๋ฅญํ•˜๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค!

๋ถˆํ–‰ํžˆ๋„ raven js์—์„œ ์ด์— ๋Œ€ํ•œ ์ง€์›์ด ํ‘œ์‹œ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ž์ฒด ์†”๋ฃจ์…˜์„ ์ถœ์‹œํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์ง„ํ–‰ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์–ด๋–ค ์ œ์•ˆ์„ ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? raven js์˜ ์ผ๋ถ€ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๊นŒ?

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์šฐ๋ฆฌ์˜ ์†”๋ฃจ์…˜:

Raven ์ดˆ๊ธฐํ™”์— shouldSendCallback ์ „๋‹ฌ

์—ฐ๊ฒฐ์ด ์—†์œผ๋ฉด logStorageService์—์„œ ์ด๋ฒคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

var options = {
    ...
    shouldSendCallback: function(data) {
        if (connectionStatus.check() && Raven.isSetup()) {
            return true;
        } else {
            // store log data somewhere
            logStorageService.set(data);
            return false;
        }
    }
    ...
};

Raven.config(SENTRY_KEY, options).install();

๋กœ๊ทธ ์ „์†ก์„ ์‹œ๋„ํ•˜๋Š” ๋Œ€๊ธฐ์—ด

Queue๋Š” 25์ดˆ๋งˆ๋‹ค ์ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๊ฒฐ๊ตญ ๋ชจ๋“  ์ด๋ฒคํŠธ๋ฅผ Sentry์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

queue.enqueue(function () {
                    logStorageService
                        .getKeys()
                        .then(function (keys) {
                            if (keys && keys[0]) {
                                logStorageService
                                    .get(keys[0])
                                    .then(function (log) {
                                        Raven.captureMessage('', log);
                                        logStorageService.remove(keys[0]);
                                    });
                            }
                            ...
                        });
                });

๋ชจ๋“  27 ๋Œ“๊ธ€

์‚ฌ์šฉ์ž๊ฐ€ ์˜คํ”„๋ผ์ธ์ธ์ง€ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๊ทธ๋ ‡๋‹ค๋ฉด ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ณ  ํ์— ๋„ฃ๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค์‹œ ์˜จ๋ผ์ธ ์ƒํƒœ๊ฐ€ ๋˜๋ฉด Raven.captureException ํ†ตํ•ด ๋‹ค์‹œ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

์ž‘๋™ ๋ฐฉ์‹์— ๋Œ€ํ•ด ๋„์›€์„ ์ฃผ๊ฑฐ๋‚˜ ์ด๋ฅผ ๋•๊ธฐ ์œ„ํ•ด ํ›„ํฌ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ข‹์Šต๋‹ˆ๋‹ค. ํ˜‘๋ ฅํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. Sentry ์—ฐ๊ฒฐ ๊ฐ€๋Šฅ์„ฑ์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ์‚ฌ์šฉ์ž๊ฐ€ ์˜จ๋ผ์ธ ์ƒํƒœ์ž„์„ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ์ „์†ก ์‹คํŒจ ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋‹ค์‹œ ์‹œ๋„ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

captureException ์‚ฌ์šฉ์— ๊ด€ํ•ด์„œ๋Š” ๊ดœ์ฐฎ๊ฒ ์ง€๋งŒ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ์˜ˆ์™ธ์— ๋Œ€ํ•ด ์šฐ์ˆ˜ํ•œ ์ฒ˜๋ฆฌ๊ธฐ raven์ด ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์„ ์œ ์ง€ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๊นŒ๋งˆ๊ท€ ์˜ค๋ฅ˜ ๊ฐ์ง€์™€ ์˜ค๋ฅ˜ ์ „์†ก ์‚ฌ์ด์— ์ค‘๊ฐ„ ๋…ผ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ, ์ž ์‹œ ์ƒ๊ฐํ•ด ๋ณด์‹ญ์‹œ์˜ค. raven-js์—์„œ ์ด๊ฒƒ์„ ์ž๋™์œผ๋กœ ์ง€์›ํ•˜๊ฑฐ๋‚˜ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ํ›„ํฌ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ณต์ •ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ €๋„ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์ฐพ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์„œ๋ฅผ ๊ฒ€ํ† ํ•œ ํ›„ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด shouldSendCallback ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

shouldSendCallback: function(data) {
  localStorage['queued-errors'] = (localStorage['queued-errors'] || []).push(data);
  return false;
}

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์„ ์ˆ˜์‹ ํ•˜๊ณ  Raven.captureException ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€๊ธฐ์—ด์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

window.addEventListener('online', checkAndProcessQueue);

์ด๊ฒƒ์€ ์•ฝ๊ฐ„ ํŽธ์Šนํ•˜์ง€๋งŒ ๋น„์Šทํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ˜ธ์ŠคํŠธ์— ๋Œ€ํ•œ ์—ฐ๊ฒฐ์ด ๋Š์–ด์ง€๋ฉด ์˜ค๋ฅ˜๋ฅผ ๋ณด๊ณ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค(๋ฐ˜๋“œ์‹œ ์˜คํ”„๋ผ์ธ์ผ ํ•„์š”๋Š” ์—†์Œ). ์ฃผ๋ณ€์„ ๋‘˜๋Ÿฌ๋ณด๋‹ˆ ravenFailure ์ด๋ฒคํŠธ๊ฐ€ ์ฐฝ์—์„œ ํŠธ๋ฆฌ๊ฑฐ๋˜๊ณ  ์žˆ์ง€๋งŒ ์ด ์ด๋ฒคํŠธ์—์„œ ์ถฉ๋ถ„ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์„ ์ˆ˜ ์—†์–ด ๋‚ด๊ฐ€ ํ•˜๋ ค๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์‹คํŒจ ์‹œ ์˜ค๋ฅ˜ ๋ณด๋‚ด๊ธฐ๋ฅผ ๋‹ค์‹œ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.

์ด์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ๊ฐ€๋Šฅํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์ด๋ฒคํŠธ ์ „์†ก์„ ์žฌ์‹œ๋„ํ•  ๋นˆ๋„, ํฌ๊ธฐํ•˜๊ธฐ ์ „์— ์‹œ๋„ํ•  ํšŸ์ˆ˜ ๋“ฑ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ธ์Šคํ„ด์Šค๋ณ„ ๋˜๋Š” ๋ฉ”์‹œ์ง€๋ณ„ retry ์˜ต์…˜
  2. captureException(), sendMessage()` ๋“ฑ์˜ ์ฝœ๋ฐฑ/์ฝœ๋ฐฑ์€ ์„ฑ๊ณต/์‹คํŒจ ์‹œ ํŠธ๋ฆฌ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.
  3. ๊ทธ ๋ฐฉ๋ฒ•์„ ์•ฝ์† (meh)
  4. ์‹คํŒจ ์‹œ ์ด๋ฒคํŠธ(์–ด๋””์„œ?)๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๊ณ  ํ•ด๋‹น ์ด๋ฒคํŠธ์˜ ์žฌ์ „์†ก์„ ์‹œ๋„ํ•˜๊ธฐ ์œ„ํ•ด ์ด๋ฒคํŠธ ๋ฐ์ดํ„ฐ์— ์ถฉ๋ถ„ํ•œ ์ปจํ…์ŠคํŠธ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋‚˜์ค‘์— ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋„๋ก ์˜คํ”„๋ผ์ธ ์ €์žฅ ๊ธฐ๋Šฅ์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์•ฑ์„ ๋‹ซ์•˜๋‹ค๊ฐ€ ๋‚˜์ค‘์— ์˜จ๋ผ์ธ ์ƒํƒœ์—์„œ ๋‹ค์‹œ ์—ฐ ํ›„์—๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. "์˜คํ”„๋ผ์ธ ์šฐ์„ " ์ ‘๊ทผ ๋ฐฉ์‹๊ณผ ์œ ์‚ฌ:
http://offlinefirst.org/

๋‚˜๋Š” ๊ฐ™์€ ๋ฌธ์ œ์— ์ง๋ฉดํ–ˆ๋‹ค. ์ฒ˜์Œ์—๋Š” ์„œ๋น„์Šค ์›Œ์ปค๋กœ ์˜คํ”„๋ผ์ธ ๊ตฌ๊ธ€ ์• ๋„๋ฆฌํ‹ฑ์Šค ๋ฌธ์ œ๋ฅผ ํ‘ธ๋Š” ๋ฐฉ์‹๊ณผ ๋น„์Šทํ•˜๊ฒŒ ํ’€๊ณ  ์‹ถ์—ˆ๋‹ค. ์ ‘๊ทผ ๋ฐฉ์‹์€ ์—ฌ๊ธฐ ์—์„œ Google์— ์˜ํ•ด ์ž˜ ์„ค๋ช…๋˜์–ด

๊ทธ๋Ÿฌ๋‚˜ Cordova๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•˜๋Š” ๊ฒฝ์šฐ Service Worker๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  _hacky_ ์†”๋ฃจ์…˜ ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์„ ์ƒ๊ฐํ•ด ๋ƒˆ์Šต๋‹ˆ๋‹ค.

https://gist.github.com/oliviertassinari/73389727fe58373eef7b63d2d2c5ce5d

import raven from 'raven-js';
import config from 'config';

const SENTRY_DSN = 'https://[email protected]/YYYY';

function sendQueue() {
  const sentryOffline = JSON.parse(window.localStorage.sentryOffline);

  if (sentryOffline.length > 0) {
    raven._send(sentryOffline[0]);
  }
}

// ... 

@webberig์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋งŽ์€ ๋ฉ‹์ง„ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ฝค ์ธ์ƒ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์ด ์ด๋ฏธ ๊นŒ๋งˆ๊ท€์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ์‚ฌ์‹ค์— ์‚ฌ์‹ค ์กฐ๊ธˆ ๋†€๋ž์Šต๋‹ˆ๋‹ค. ์•ฑ์˜ ์•„ํ‚คํ…์ฒ˜์— ๋”ฐ๋ผ ์˜คํ”„๋ผ์ธ ์ƒํƒœ์˜ ๊ฒฐ๊ณผ์ธ ์˜ค๋ฅ˜์˜ ์‚ฌ์†Œํ•œ ๋น„์œจ์ด ์ž ์žฌ์ ์œผ๋กœ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์— ๋Œ€ํ•ด ๋ณด๊ณ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ๋งŽ์€ ๊ตฌํ˜„์—์„œ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋‚ด ํˆฌํ‘œ๋Š” ์ด๊ฒƒ์ด ์ž๋™์œผ๋กœ ๊ตฌ์›Œ์ ธ์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Sentry๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋Š” ์ค‘์— ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•˜๊ณ  ๋‚˜์ค‘์— ๋‹ค์‹œ ์‹œ๋„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(ํƒ€์ด๋จธ, ์ด๋ฒคํŠธ ๋˜๋Š” ๋‹จ์ˆœํ•˜๊ฒŒ ์œ ์ง€ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ ๋ฉ”์‹œ์ง€ ์ „์†ก ์‹œ).

๋˜ํ•œ "DDN"๋ ˆ์ด๋ธ”์€ ๋ฌด์—‡์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ?

๋‹ค๋ฅธ ๋งŽ์€ ๋ฉ‹์ง„ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ฝค ์ธ์ƒ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์ด ์ด๋ฏธ ๊นŒ๋งˆ๊ท€์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ์‚ฌ์‹ค์— ์‚ฌ์‹ค ์กฐ๊ธˆ ๋†€๋ž์Šต๋‹ˆ๋‹ค. ์•ฑ์˜ ์•„ํ‚คํ…์ฒ˜์— ๋”ฐ๋ผ ์˜คํ”„๋ผ์ธ ์ƒํƒœ์˜ ๊ฒฐ๊ณผ์ธ ์˜ค๋ฅ˜์˜ ์‚ฌ์†Œํ•œ ๋น„์œจ์ด ์ž ์žฌ์ ์œผ๋กœ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์™„์ „ํžˆ ๊ณต์ •ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ˆ˜ํ–‰๋˜์–ด์•ผ ํ•˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋กœ๋“œ๋˜์ง€ ์•Š์œผ๋ฉด ๋ฌด์Šจ ์ผ์ด ์žˆ์–ด๋„ ์•ฑ์ด ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ๋งŽ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋Œ€๋ถ€๋ถ„์˜ ์•ฑ์€ ์˜คํ”„๋ผ์ธ์—์„œ ์ž‘๋™ํ•˜์ง€ ์•Š์œผ๋ฉฐ ๊ธฐ๋Œ€ํ•˜์ง€๋„ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ์ข‹์€ ์Šต๊ด€์ธ์ง€ ์•„๋‹Œ์ง€๋Š” ๋‹ค๋ฅธ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

๋งŽ์€ Raven ์‚ฌ์šฉ์ž๊ฐ€ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๊ธฐ๋ณธ์ ์œผ๋กœ AJAX ์˜ค๋ฅ˜๋ฅผ ๊ธฐ๋กํ•˜์ง€ ์•Š๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ _์›ํ•˜์‹ ๋‹ค๋ฉด_ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋…ธ๋ ฅํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์—ฌ๊ธฐ์„œ๋„ ๊ฐ™์€ ์ผ์„ ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ "DDN"๋ ˆ์ด๋ธ”์€ ๋ฌด์—‡์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ?

ํ™•์‹คํ•˜์ง€ ์•Š๋‹ค. @๋งคํŠธ๋กœ๋ฒ ๋†€ํŠธ?

๋””์ž์ธ ๊ฒฐ์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. :)

๊ธฐ๋ณธ์ ์œผ๋กœ ์ˆ˜ํ–‰๋˜์–ด์•ผ ํ•˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋„ค ๋ง์ด ๋˜๋„ค์š”.

ํ•˜์ง€๋งŒ ์›ํ•˜์‹ ๋‹ค๋ฉด ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋…ธ๋ ฅํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์—ฌ๊ธฐ์„œ๋„ ๊ฐ™์€ ์ผ์„ ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋””์ž์ธ ๊ฒฐ์ •์„ ๋‚ด๋ฆฌ๋Š” ๋ฐ ๋„์›€์ด ๋˜๋„๋ก ๋ช‡ ๊ฐ€์ง€ ์ƒ๊ฐ์„ ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฌธ์„œ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ดํ•ด transport ๊ตฌ์„ฑ ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ Sentry๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋Š” ํŒŒ์ดํ”„๋ผ์ธ์˜ ๋งˆ์ง€๋ง‰ ๋ถ€๋ถ„์„ ์ œ์–ดํ•˜๊ณ  ํ•ด๋‹น ์ „์†ก์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ฑ…์ž„์„ ๋งก์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์˜คํ”„๋ผ์ธ ๋Œ€๊ธฐ์—ด์„ ํ”Œ๋Ÿฌ๊ทธ์ธํ•˜๊ธฐ์— ๊ฐ€์žฅ ์ข‹์€ ์žฅ์†Œ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋Š” ๋Œ€์‹  ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์„œ๋ฒ„์— ์—…๋กœ๋“œํ•˜๋Š” ๋Œ€๊ธฐ์—ด๋กœ ๋ณด๋‚ด์‹ญ์‹œ์˜ค. ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๊ทธ๊ฒƒ์„ ์‹คํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์ž์‹ ์˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒฝ์šฐ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋น„์Šทํ•œ ๋งฅ๋ฝ์—์„œ ๊ธฐ๋ณธ HTTP ์ „์†ก์„ ๊ณต์‹ Raven ๋กค๋ง ์˜คํ”„๋ผ์ธ ๊ฐ€๋Šฅ ๋Œ€๊ธฐ์—ด๋กœ ๋Œ€์ฒดํ•˜๋Š” ๊ตฌ์„ฑ ์˜ต์…˜( includeOffline ?)์„ ๋…ธ์ถœํ•˜๋Š” ๊ฒƒ์ด ์ถฉ๋ถ„ํžˆ ๊ฐ„๋‹จํ• ๊นŒ์š”?

  • ๋ธŒ๋ผ์šฐ์ € ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด ๋Œ€๊ธฐ์—ด์„ localStorage์— ์ €์žฅํ•˜๊ณ  ์‹œ๊ฐ„ ์ดˆ๊ณผ ์‹œ ์—ฐ๊ฒฐ์„ ํ™•์ธํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋” ๋‚˜์€ ์„ฑ๋Šฅ๊ณผ ์•ˆ์ •์„ฑ์„ ์œ„ํ•ด ์„œ๋น„์Šค ์ž‘์—…์ž๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋Œ€๊ธฐ์—ด์„ ๊ด€๋ฆฌํ•˜์—ฌ ํŽ˜์ด์ง€๊ฐ€ ๋‹ซํžŒ ํ›„์—๋„ ์˜ค๋ฅ˜๊ฐ€ ์—…๋กœ๋“œ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ์‹œ์ ์—์„œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ž์ฒด ์„œ๋น„์Šค ์›Œ์ปค๋ฅผ ๊ฐ€๋™ํ•˜๋Š” ๊ฒƒ์€ ์•ฝ๊ฐ„ ์ฃผ์ œ๋„˜์€ ์ผ์ž…๋‹ˆ๊นŒ?

์ด ๊ธฐ๋Šฅ์ด ์ด์ œ ์–ด๋–ป๊ฒŒ๋“  ๊นŒ๋งˆ๊ท€์— ๋‚ด์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๊นŒ?

@Freundschaft ์•„๋‹ˆ์š”, ์•„์ง ์•„๋‹™๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์ดํ•ดํ•˜๋Š” ํ•œ, ์ง€๊ธˆ์€ transport ์˜ต์…˜์„ ๋ฌด์‹œํ•˜๊ฑฐ๋‚˜ shouldSendCallback ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‚˜์ค‘์— ๋ณด๋‚ผ ๋Œ€๊ธฐ์—ด์„ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@cudaste ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!
๋ˆ„๊ตฐ๊ฐ€ ์ž‘์—… ์ƒ˜ํ”Œ ๊ตฌํ˜„์„ ์–ป์—ˆ์Šต๋‹ˆ๊นŒ? ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์ž‘์„ฑํ•˜๊ณ  ์—ฌ๊ธฐ์— ๊ฒŒ์‹œํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค

@Freundschaft ์ด๊ฒƒ์€ ๋งค์šฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ฐ™์€ ๋ฌธ์ œ์— ์ง๋ฉดํ•ด ์žˆ๋‹ค

++1 ์ œ๋ฐœ

+1

+1

์šฐ๋ฆฌ์˜ ์†”๋ฃจ์…˜:

Raven ์ดˆ๊ธฐํ™”์— shouldSendCallback ์ „๋‹ฌ

์—ฐ๊ฒฐ์ด ์—†์œผ๋ฉด logStorageService์—์„œ ์ด๋ฒคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

var options = {
    ...
    shouldSendCallback: function(data) {
        if (connectionStatus.check() && Raven.isSetup()) {
            return true;
        } else {
            // store log data somewhere
            logStorageService.set(data);
            return false;
        }
    }
    ...
};

Raven.config(SENTRY_KEY, options).install();

๋กœ๊ทธ ์ „์†ก์„ ์‹œ๋„ํ•˜๋Š” ๋Œ€๊ธฐ์—ด

Queue๋Š” 25์ดˆ๋งˆ๋‹ค ์ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๊ฒฐ๊ตญ ๋ชจ๋“  ์ด๋ฒคํŠธ๋ฅผ Sentry์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

queue.enqueue(function () {
                    logStorageService
                        .getKeys()
                        .then(function (keys) {
                            if (keys && keys[0]) {
                                logStorageService
                                    .get(keys[0])
                                    .then(function (log) {
                                        Raven.captureMessage('', log);
                                        logStorageService.remove(keys[0]);
                                    });
                            }
                            ...
                        });
                });

์œ„์˜ ๋ช‡ ๊ฐ€์ง€ ์˜ˆ๋Š” "๋น„๊ณต๊ฐœ" ํ•จ์ˆ˜์— ๋Œ€ํ•œ ํ˜ธ์ถœ์„ ๋ณด์—ฌ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Raven._sendProcessedPayload ๋˜๋Š” Raven._send ์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด Raven()์ด ์–ด๋–ป๊ฒŒ ๊ฐ์ฒด๋กœ ๊ตฌ์„ฑ๋˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์–ด๋””์—๋„ "new Raven()"์ด ๋ณด์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์„ ์–ด๋–ป๊ฒŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์‹ ๊ฒฝ์“ฐ์ง€ ๋งˆ์„ธ์š”. ๋ฌธ์ œ๋Š” raven.min.js ์ผ ๋•Œ๋งŒ ๋ฐœ์ƒํ–ˆ์œผ๋ฉฐ raven.js ์•„๋‹ˆ๋ผ ํ•ด๋‹น ์งˆ๋ฌธ์— ๋Œ€ํ•œ ๋‹ต๋ณ€์ด์—ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ _sendProcessedPayload ํ•จ์ˆ˜์˜ ์ถ•์†Œ๋œ ์ด๋ฆ„์„ ์ฐพ์•˜๊ณ  ๋‹ค์Œ์€ ๋‚ด ์ฝ”๋“œ์—์„œ ๋๋‚ธ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค(ํ˜„์žฌ๋กœ์„œ๋Š”).

  /**
   * HACK: Using a private function that gets minified!
   * Pinned Raven-js to version 3.8.1.
   */
  Raven._sendProcessedPayload = Raven._sendProcessedPayload || Raven.Y;

  ...

  function processQueue(items) {
    // Stop if we're not online.
    if (!canSend())
      return;
    // Process the given items or get them from the queue.
    items = items || queue.getItems();
    if (!items || items.length < 1)
      return;
    // First in, first out.
    var next = items.shift();
    // Send the next item.
    Raven._sendProcessedPayload(next, function processed(error) {
      // If no errors, save the queue and process more items.
      if (!error) {
        queue.save(items);
        processQueue(items);
      }
    });
  }

  function shouldSend(data) {
    if (canSend())
      return true;
    if (data.extra.retry)
      return false;
    data.extra.retry = true;
    queue.add(data);
    return false;
  }

  ...

  setInterval(processQueue, OFFLINE_QUEUE_TIMEOUT);

์ด๊ฒƒ์€ ๋”์ฐํ•œ HACK ์œผ๋กœ ์ธํ•ด ์ด์ƒ์ ์ด์ง€ ์•Š์œผ๋ฉฐ ๋˜ํ•œ ์ด ๋Œ€๊ธฐ์—ด์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋™์•ˆ ๋” ๋งŽ์€ ์˜ค๋ฅ˜๊ฐ€ ์บก์ฒ˜๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ˆœ์„œ๊ฐ€ ๋งž์ง€ ์•Š๊ฒŒ ์ „์†ก๋ฉ๋‹ˆ๋‹ค...

์˜ค๋Š˜์˜ ๋งˆ์ง€๋ง‰ ๋ฉ”๋ชจ: _sendProcessedPayload ๊ณต๊ฐœํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. shouldSendCallback ๊ฐ€ false๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ _send ์ข…๋ฃŒ๋˜๋Š” ์œ„์น˜์—์„œ ๋ฐ”๋กœ ์„ ํƒํ•˜๋ฏ€๋กœ ๋ณด๋‚ด๊ธฐ๋ฅผ ๋‹ค์‹œ ์‹œ๋„ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด ํ™•์‹คํ•œ ์„ ํƒ์ž…๋‹ˆ๋‹ค...

๊ทธ๋Ÿฌ๋‚˜ ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์€ ๋งˆ์Œ์— ๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด์ƒ์ ์ธ ๋ฐฉ๋ฒ•์€ ์•„๋‹™๋‹ˆ๋‹ค.

์ด ๊ธฐ๋Šฅ์ด ์•„์ง ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ถ”๊ฐ€๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๊นŒ?

๋‚˜๋Š” ์˜คํ”„๋ผ์ธ ๊ธฐ๋Šฅ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์˜ค๋Š˜ ์ด๊ฒƒ์ด ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” indexdb๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‚ด ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜์ง€๋งŒ Sentry์— ๋Œ€ํ•œ ์ฆ‰์‹œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์˜คํ”„๋ผ์ธ ๊ธฐ๋Šฅ์„ ๊ฐ–๋Š” ๊ฒƒ์ด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž์ฒด ๋กœ์ปฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฒคํŠธ๋ฅผ ์ €์žฅํ•˜๊ณ  ์ฃผ๊ธฐ์ ์œผ๋กœ/๋„คํŠธ์›Œํฌ ๋ณ€๊ฒฝ์„ ํ†ตํ•ด ๋งค์šฐ ์œ ์šฉํ•œ db๋ฅผ ๋ณด๋‚ด๊ณ  ์ง€์šฐ๋ ค๊ณ  ์‹œ๋„ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด.

์—ฌ๊ธฐ์—์„œ ์ฃผ์†Œ https://github.com/getsentry/raven-js/pull/1165

๋‚˜์ค‘์— ์˜จ๋ผ์ธ ์ƒํƒœ๊ฐ€ ๋˜์—ˆ์„ ๋•Œ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด ์˜ˆ์™ธ๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฒฝ์šฐ ์˜ˆ์™ธ์— ํƒ€์ž„์Šคํƒฌํ”„๋ฅผ ์„ค์ •ํ•˜์—ฌ ๋‚ด๊ฐ€ ์„ผํŠธ๋ฆฌ๋กœ ๋ณด๋‚ผ ๋•Œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜์Œ์„ ๋‚˜ํƒ€๋‚ด๋„๋ก ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์ง€๋งŒ ์–ด๋Š ์‹œ์ ์—์„œ ๊ณผ๊ฑฐ? ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์ถ”๊ฐ€๋กœ ์ถ”๊ฐ€ ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ์‹ค์ œ ํƒ€์ž„ ์Šคํƒฌํ”„๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

captureException ๊ทธ๋Ÿฐ ์˜ต์…˜์ด ์—†์Šต๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰