diff --git a/main/index.js b/main/index.js index 1d120f86..dc6f759b 100644 --- a/main/index.js +++ b/main/index.js @@ -68,6 +68,13 @@ function init () { // To keep app startup fast, some code is delayed. setTimeout(delayedInit, config.DELAYED_INIT) + + // Report uncaught exceptions + process.on('uncaughtException', (err) => { + console.error(err) + var errJSON = {message: err.message, stack: err.stack} + windows.main.dispatch('uncaughtError', 'main', errJSON) + }) }) app.once('ipcReady', function () { diff --git a/renderer/main.js b/renderer/main.js index 7b6085fb..f4fae7f6 100644 --- a/renderer/main.js +++ b/renderer/main.js @@ -95,9 +95,11 @@ function onState (err, _state) { // ...window visibility state. document.addEventListener('webkitvisibilitychange', onVisibilityChange) - sound.play('STARTUP') + // Log uncaught JS errors + window.addEventListener('error', (err) => telemetry.logUncaughtError('window', err.error), true) // Done! Ideally we want to get here < 500ms after the user clicks the app + sound.play('STARTUP') console.timeEnd('init') } @@ -327,6 +329,9 @@ function dispatch (action, ...args) { if (action === 'setTitle') { state.window.title = args[0] /* title */ } + if (action === 'uncaughtError') { + telemetry.logUncaughtError(args[0] /* process */, args[1] /* error */) + } // Update the virtual-dom, unless it's just a mouse move event if (action !== 'mediaMouseMoved' || showOrHidePlayerControls()) { @@ -481,6 +486,8 @@ function setupIpc () { ipcRenderer.on('wt-audio-metadata', (e, ...args) => torrentAudioMetadata(...args)) ipcRenderer.on('wt-server-running', (e, ...args) => torrentServerRunning(...args)) + ipcRenderer.on('wt-uncaught-error', (e, err) => telemetry.logUncaughtError('webtorrent', err)) + ipcRenderer.send('ipcReady') } diff --git a/renderer/webtorrent.js b/renderer/webtorrent.js index e2ccbd3c..8daac00f 100644 --- a/renderer/webtorrent.js +++ b/renderer/webtorrent.js @@ -63,6 +63,9 @@ function init () { ipc.send('ipcReadyWebTorrent') + window.addEventListener('error', (err) => + ipc.send('wt-uncaught-error', {message: err.error.message, stack: err.error.stack})) + setInterval(updateTorrentProgress, 1000) } diff --git a/telemetry.js b/telemetry.js index 946fd490..39680585 100644 --- a/telemetry.js +++ b/telemetry.js @@ -47,7 +47,6 @@ function reset () { function postToServer () { // Serialize the telemetry summary - return console.log(JSON.stringify(telemetry, null, 2)) var payload = new Buffer(JSON.stringify(telemetry), 'utf8') // POST to our server @@ -111,14 +110,16 @@ function getApproxNumTorrents (state) { } // An uncaught error happened in the main process or one in one of the windows -function logUncaughtError (err) { - var errString +function logUncaughtError (process, err) { + var message, stack if (typeof err === 'string') { - errString = err + message = err + stack = '' } else { - errString = err.message + '\n' + err.stack + message = err.message + stack = err.stack } - telemetry.uncaughtErrors.push(errString) + telemetry.uncaughtErrors.push({process, message, stack}) } // The user pressed play. It either worked, timed out, or showed the