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 |