| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview | 6 * @fileoverview |
| 7 * Module for sending log entries to the server. | 7 * Module for sending log entries to the server. |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 'use strict'; | 10 'use strict'; |
| 11 | 11 |
| 12 /** @suppress {duplicate} */ | 12 /** @suppress {duplicate} */ |
| 13 var remoting = remoting || {}; | 13 var remoting = remoting || {}; |
| 14 | 14 |
| 15 /** | 15 /** |
| 16 * @constructor | 16 * @constructor |
| 17 */ | 17 */ |
| 18 remoting.LogToServer = function() { | 18 remoting.LogToServer = function() { |
| 19 /** @type Array.<string> */ | 19 /** @type Array.<string> */ |
| 20 this.pendingEntries = []; | 20 this.pendingEntries = []; |
| 21 /** @type {remoting.StatsAccumulator} */ | 21 /** @type {remoting.StatsAccumulator} */ |
| 22 this.statsAccumulator = new remoting.StatsAccumulator(); | 22 this.statsAccumulator = new remoting.StatsAccumulator(); |
| 23 /** @type string */ |
| 24 this.sessionId = ''; |
| 25 /** @type number */ |
| 26 this.sessionIdGenerationTime = 0; |
| 23 }; | 27 }; |
| 24 | 28 |
| 25 // Local storage keys. | 29 // Local storage key. |
| 26 /** @private */ | 30 /** @private */ |
| 27 remoting.LogToServer.prototype.KEY_ENABLED_ = 'remoting.LogToServer.enabled'; | 31 remoting.LogToServer.KEY_ENABLED_ = 'remoting.LogToServer.enabled'; |
| 32 |
| 33 // Constants used for generating a session ID. |
| 28 /** @private */ | 34 /** @private */ |
| 29 remoting.LogToServer.prototype.KEY_ID_ = 'remoting.LogToServer.id'; | 35 remoting.LogToServer.SESSION_ID_ALPHABET_ = |
| 30 | |
| 31 // Constants used for generating an ID. | |
| 32 /** @private */ | |
| 33 remoting.LogToServer.prototype.ID_ALPHABET_ = | |
| 34 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'; | 36 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'; |
| 35 /** @private */ | 37 /** @private */ |
| 36 remoting.LogToServer.prototype.ID_LEN_ = 20; | 38 remoting.LogToServer.SESSION_ID_LEN_ = 20; |
| 39 |
| 40 // The maximum age of a session ID, in milliseconds. |
| 41 remoting.LogToServer.MAX_SESSION_ID_AGE = 24 * 60 * 60 * 1000; |
| 42 |
| 43 // The time over which to accumulate connection statistics before logging them |
| 44 // to the server, in milliseconds. |
| 45 remoting.LogToServer.CONNECTION_STATS_ACCUMULATE_TIME = 60 * 1000; |
| 37 | 46 |
| 38 /** | 47 /** |
| 39 * Enables or disables logging. | 48 * Enables or disables logging. |
| 40 * | 49 * |
| 41 * @param {boolean} enabled whether logging is enabled | 50 * @param {boolean} enabled whether logging is enabled |
| 42 */ | 51 */ |
| 43 remoting.LogToServer.prototype.setEnabled = function(enabled) { | 52 remoting.LogToServer.prototype.setEnabled = function(enabled) { |
| 44 window.localStorage.setItem(this.KEY_ENABLED_, enabled ? 'true' : 'false'); | 53 window.localStorage.setItem(remoting.LogToServer.KEY_ENABLED_, |
| 54 enabled ? 'true' : 'false'); |
| 45 } | 55 } |
| 46 | 56 |
| 47 /** | 57 /** |
| 48 * Logs a client session state change. | 58 * Logs a client session state change. |
| 49 * | 59 * |
| 50 * @param {remoting.ClientSession.State} state | 60 * @param {remoting.ClientSession.State} state |
| 51 * @param {remoting.ClientSession.ConnectionError} connectionError | 61 * @param {remoting.ClientSession.ConnectionError} connectionError |
| 52 */ | 62 */ |
| 53 remoting.LogToServer.prototype.logClientSessionStateChange = | 63 remoting.LogToServer.prototype.logClientSessionStateChange = |
| 54 function(state, connectionError) { | 64 function(state, connectionError) { |
| 65 this.maybeExpireSessionId(); |
| 66 // Maybe set the session ID. |
| 67 if ((state == remoting.ClientSession.State.CONNECTING) || |
| 68 (state == remoting.ClientSession.State.INITIALIZING) || |
| 69 (state == remoting.ClientSession.State.CONNECTED)) { |
| 70 if (this.sessionId == '') { |
| 71 this.setSessionId(); |
| 72 } |
| 73 } |
| 74 // Log the session state change. |
| 55 var entry = remoting.ServerLogEntry.makeClientSessionStateChange( | 75 var entry = remoting.ServerLogEntry.makeClientSessionStateChange( |
| 56 state, connectionError); | 76 state, connectionError); |
| 57 entry.addHostFields(); | 77 entry.addHostFields(); |
| 58 entry.addChromeVersionField(); | 78 entry.addChromeVersionField(); |
| 59 entry.addWebappVersionField(); | 79 entry.addWebappVersionField(); |
| 60 entry.addIdField(this.getId()); | 80 entry.addSessionIdField(this.sessionId); |
| 61 this.log(entry); | 81 this.log(entry); |
| 62 // Don't accumulate connection statistics across state changes. | 82 // Don't accumulate connection statistics across state changes. |
| 63 this.logAccumulatedStatistics(); | 83 this.logAccumulatedStatistics(); |
| 64 this.statsAccumulator.empty(); | 84 this.statsAccumulator.empty(); |
| 85 // Maybe clear the session ID. |
| 86 if ((state == remoting.ClientSession.State.CLOSED) || |
| 87 (state == remoting.ClientSession.State.CONNECTION_FAILED)) { |
| 88 this.clearSessionId(); |
| 89 } |
| 65 }; | 90 }; |
| 66 | 91 |
| 67 /** | 92 /** |
| 68 * Logs connection statistics. | 93 * Logs connection statistics. |
| 69 * @param {Object.<string, number>} stats the connection statistics | 94 * @param {Object.<string, number>} stats the connection statistics |
| 70 */ | 95 */ |
| 71 remoting.LogToServer.prototype.logStatistics = function(stats) { | 96 remoting.LogToServer.prototype.logStatistics = function(stats) { |
| 97 this.maybeExpireSessionId(); |
| 72 // Store the statistics. | 98 // Store the statistics. |
| 73 this.statsAccumulator.add(stats); | 99 this.statsAccumulator.add(stats); |
| 74 // Send statistics to the server if they've been accumulating for at least | 100 // Send statistics to the server if they've been accumulating for at least |
| 75 // 60 seconds. | 101 // 60 seconds. |
| 76 if (this.statsAccumulator.getTimeSinceFirstValue() >= 60 * 1000) { | 102 if (this.statsAccumulator.getTimeSinceFirstValue() >= |
| 103 remoting.LogToServer.CONNECTION_STATS_ACCUMULATE_TIME) { |
| 77 this.logAccumulatedStatistics(); | 104 this.logAccumulatedStatistics(); |
| 78 } | 105 } |
| 79 }; | 106 }; |
| 80 | 107 |
| 81 /** | 108 /** |
| 82 * Moves connection statistics from the accumulator to the log server. | 109 * Moves connection statistics from the accumulator to the log server. |
| 83 * | 110 * |
| 84 * If all the statistics are zero, then the accumulator is still emptied, | 111 * If all the statistics are zero, then the accumulator is still emptied, |
| 85 * but the statistics are not sent to the log server. | 112 * but the statistics are not sent to the log server. |
| 86 * | 113 * |
| 87 * @private | 114 * @private |
| 88 */ | 115 */ |
| 89 remoting.LogToServer.prototype.logAccumulatedStatistics = function() { | 116 remoting.LogToServer.prototype.logAccumulatedStatistics = function() { |
| 90 var entry = remoting.ServerLogEntry.makeStats(this.statsAccumulator); | 117 var entry = remoting.ServerLogEntry.makeStats(this.statsAccumulator); |
| 91 if (entry) { | 118 if (entry) { |
| 92 entry.addHostFields(); | 119 entry.addHostFields(); |
| 93 entry.addChromeVersionField(); | 120 entry.addChromeVersionField(); |
| 94 entry.addWebappVersionField(); | 121 entry.addWebappVersionField(); |
| 95 entry.addIdField(this.getId()); | 122 entry.addSessionIdField(this.sessionId); |
| 96 this.log(entry); | 123 this.log(entry); |
| 97 } | 124 } |
| 98 this.statsAccumulator.empty(); | 125 this.statsAccumulator.empty(); |
| 99 }; | 126 }; |
| 100 | 127 |
| 101 /** | 128 /** |
| 102 * Sends a log entry to the server. | 129 * Sends a log entry to the server. |
| 103 * | 130 * |
| 104 * @private | 131 * @private |
| 105 * @param {remoting.ServerLogEntry} entry | 132 * @param {remoting.ServerLogEntry} entry |
| (...skipping 24 matching lines...) Expand all Loading... |
| 130 remoting.wcs.sendIq(stanza); | 157 remoting.wcs.sendIq(stanza); |
| 131 }; | 158 }; |
| 132 | 159 |
| 133 /** | 160 /** |
| 134 * Whether logging is enabled. | 161 * Whether logging is enabled. |
| 135 * | 162 * |
| 136 * @private | 163 * @private |
| 137 * @return {boolean} whether logging is enabled | 164 * @return {boolean} whether logging is enabled |
| 138 */ | 165 */ |
| 139 remoting.LogToServer.prototype.isEnabled = function() { | 166 remoting.LogToServer.prototype.isEnabled = function() { |
| 140 var value = window.localStorage.getItem(this.KEY_ENABLED_); | 167 var value = window.localStorage.getItem(remoting.LogToServer.KEY_ENABLED_); |
| 141 return (value == 'true'); | 168 return (value == 'true'); |
| 142 }; | 169 }; |
| 143 | 170 |
| 144 /** | 171 /** |
| 145 * Gets an ID from local storage. | 172 * Sets the session ID to a random string. |
| 146 * | |
| 147 * This function returns the empty string if logging is disabled. | |
| 148 * If logging is enabled, and there is no ID in local storage, then this | |
| 149 * function will create and store an ID. | |
| 150 * | 173 * |
| 151 * @private | 174 * @private |
| 152 * @return {string} an ID, or the empty string | |
| 153 */ | 175 */ |
| 154 remoting.LogToServer.prototype.getId = function() { | 176 remoting.LogToServer.prototype.setSessionId = function() { |
| 155 if (!this.isEnabled()) { | 177 this.sessionId = remoting.LogToServer.generateSessionId(); |
| 156 return ''; | 178 this.sessionIdGenerationTime = new Date().getTime(); |
| 157 } | |
| 158 var id = window.localStorage.getItem(this.KEY_ID_); | |
| 159 if ((!id) || (typeof id != 'string')) { | |
| 160 id = this.generateId(); | |
| 161 window.localStorage.setItem(this.KEY_ID_, id); | |
| 162 } | |
| 163 return id.toString(); | |
| 164 }; | 179 }; |
| 165 | 180 |
| 166 /** | 181 /** |
| 167 * Generates an ID. | 182 * Clears the session ID. |
| 168 * | 183 * |
| 169 * @private | 184 * @private |
| 170 * @return {string} an ID | |
| 171 */ | 185 */ |
| 172 remoting.LogToServer.prototype.generateId = function() { | 186 remoting.LogToServer.prototype.clearSessionId = function() { |
| 187 this.sessionId = ''; |
| 188 this.sessionIdGenerationTime = 0; |
| 189 }; |
| 190 |
| 191 /** |
| 192 * Sets a new session ID, if the current session ID has reached its maximum age. |
| 193 * |
| 194 * This method also logs the old and new session IDs to the server, in separate |
| 195 * log entries. |
| 196 * |
| 197 * @private |
| 198 */ |
| 199 remoting.LogToServer.prototype.maybeExpireSessionId = function() { |
| 200 if ((this.sessionId != '') && |
| 201 (new Date().getTime() - this.sessionIdGenerationTime >= |
| 202 remoting.LogToServer.MAX_SESSION_ID_AGE)) { |
| 203 // Log the old session ID. |
| 204 var entry = remoting.ServerLogEntry.makeSessionIdOld(this.sessionId); |
| 205 this.log(entry); |
| 206 // Generate a new session ID. |
| 207 this.setSessionId(); |
| 208 // Log the new session ID. |
| 209 entry = remoting.ServerLogEntry.makeSessionIdNew(this.sessionId); |
| 210 this.log(entry); |
| 211 } |
| 212 }; |
| 213 |
| 214 /** |
| 215 * Generates a string that can be used as a session ID. |
| 216 * |
| 217 * @private |
| 218 * @return {string} a session ID |
| 219 */ |
| 220 remoting.LogToServer.generateSessionId = function() { |
| 173 var idArray = []; | 221 var idArray = []; |
| 174 for (var i = 0; i < this.ID_LEN_; i++) { | 222 for (var i = 0; i < remoting.LogToServer.SESSION_ID_LEN_; i++) { |
| 175 var index = Math.random() * this.ID_ALPHABET_.length; | 223 var index = |
| 176 idArray.push(this.ID_ALPHABET_.slice(index, index + 1)); | 224 Math.random() * remoting.LogToServer.SESSION_ID_ALPHABET_.length; |
| 225 idArray.push( |
| 226 remoting.LogToServer.SESSION_ID_ALPHABET_.slice(index, index + 1)); |
| 177 } | 227 } |
| 178 return idArray.join(''); | 228 return idArray.join(''); |
| 179 }; | 229 }; |
| OLD | NEW |