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