From 3b69a3fc1d6293ffbde93a8a8643a103ee3a7d6d Mon Sep 17 00:00:00 2001 From: Eric Mc Sween Date: Tue, 30 Jun 2020 08:04:31 -0400 Subject: [PATCH] Merge pull request #2938 from overleaf/jpa-simple-sampled-socket-io-error [misc] emit 'socket-io-error' event on connection setup errors GitOrigin-RevId: 3054da8ec692574f8383fd6cff8788165cbad89b --- services/web/frontend/js/ide.js | 2 +- .../js/ide/connection/ConnectionManager.js | 46 ++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/services/web/frontend/js/ide.js b/services/web/frontend/js/ide.js index 565d6509ba..e97fc70faf 100644 --- a/services/web/frontend/js/ide.js +++ b/services/web/frontend/js/ide.js @@ -179,7 +179,7 @@ App.controller('IdeController', function( ide.$scope = $scope ide.referencesSearchManager = new ReferencesManager(ide, $scope) - ide.connectionManager = new ConnectionManager(ide, $scope) + ide.connectionManager = new ConnectionManager(ide, $scope, eventTracking) ide.fileTreeManager = new FileTreeManager(ide, $scope) ide.editorManager = new EditorManager(ide, $scope, localStorage) ide.onlineUsersManager = new OnlineUsersManager(ide, $scope) diff --git a/services/web/frontend/js/ide/connection/ConnectionManager.js b/services/web/frontend/js/ide/connection/ConnectionManager.js index ffe7a138fc..76a76e836f 100644 --- a/services/web/frontend/js/ide/connection/ConnectionManager.js +++ b/services/web/frontend/js/ide/connection/ConnectionManager.js @@ -14,6 +14,7 @@ import SocketIoShim from './SocketIoShim' let ConnectionManager const ONEHOUR = 1000 * 60 * 60 +let transport = 'handshake' export default (ConnectionManager = (function() { ConnectionManager = class ConnectionManager { @@ -31,7 +32,7 @@ export default (ConnectionManager = (function() { this.prototype.MAX_RECONNECT_GRACEFULLY_INTERVAL = 45 * 1000 } - constructor(ide, $scope) { + constructor(ide, $scope, eventTracking) { this.ide = ide this.$scope = $scope this.wsUrl = ide.wsUrl || null // websocket url (if defined) @@ -134,6 +135,45 @@ export default (ConnectionManager = (function() { 'force new connection': true } ) + const socket = this.ide.socket + socket.on('error', reportTransportError) + socket.on('connect_failed', reportTransportError) + socket.on('connecting', name => { + transport = name + socket.removeListener('error', reportTransportError) + socket.on('error', reportTransportError) + }) + socket.on('connectionAccepted', () => { + // we have reached the real-time layer. ignore errors from now on. + socket.removeListener('error', reportTransportError) + socket.removeListener('connect_failed', reportTransportError) + }) + function reportTransportError(error) { + socket.removeListener('error', reportTransportError) + socket.removeListener('connect_failed', reportTransportError) + if (typeof error === 'undefined') { + error = 'undefined' + } else if (typeof error !== 'string') { + try { + error = JSON.stringify(error) + } catch (e) { + error = `JSON_serialize_failed: ${e.message}` + } + } + if (transport === 'websocket' && error === '{"isTrusted":true}') { + error = 'hidden' + } else if (error.indexOf('500') !== -1) { + error = '500' + } else if (error.indexOf('<title>502') !== -1) { + error = '502' + } else if (error.indexOf('<title>503') !== -1) { + error = '503' + } else if (error.length > 97) { + error = error.slice(0, 97) + '...' + } + eventTracking.sendMBSampled('socket-io-error', { transport, error }) + } + this.ide.socket.reportTransportError = reportTransportError // handle network-level websocket errors (e.g. failed dns lookups) @@ -559,6 +599,10 @@ Something went wrong connecting to your project. Please refresh if this continue } this.ide.socket.on('error', handleFailure) this.ide.socket.on('connect', handleSuccess) + const reportTransportError = this.ide.socket.reportTransportError + this.ide.socket.on('error', reportTransportError) + this.ide.socket.on('connect_failed', reportTransportError) + transport = 'handshake' // use socket.io connect() here to make a single attempt, the // reconnect() method makes multiple attempts