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.
7 * Module for sending log entries to the server.
12 /** @suppress {duplicate} */
13 var remoting = remoting || {};
16 * @param {remoting.SignalStrategy} signalStrategy Signal strategy.
17 * @param {remoting.DesktopConnectedView.Mode} mode The mode of this connection.
20 remoting.LogToServer = function(signalStrategy, mode) {
22 this.statsAccumulator_ = new remoting.StatsAccumulator();
26 this.sessionIdGenerationTime_ = 0;
28 this.sessionStartTime_ = 0;
30 this.signalStrategy_ = signalStrategy;
33 /** @type {string} @private */
34 this.connectionType_ = '';
37 signalStrategy.sendConnectionSetupResults(this);
40 // Constants used for generating a session ID.
42 remoting.LogToServer.SESSION_ID_ALPHABET_ =
43 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
45 remoting.LogToServer.SESSION_ID_LEN_ = 20;
47 // The maximum age of a session ID, in milliseconds.
48 remoting.LogToServer.MAX_SESSION_ID_AGE = 24 * 60 * 60 * 1000;
50 // The time over which to accumulate connection statistics before logging them
51 // to the server, in milliseconds.
52 remoting.LogToServer.CONNECTION_STATS_ACCUMULATE_TIME = 60 * 1000;
55 * Logs a client session state change.
57 * @param {remoting.ClientSession.State} state
58 * @param {remoting.Error} connectionError
60 remoting.LogToServer.prototype.logClientSessionStateChange =
61 function(state, connectionError) {
62 this.maybeExpireSessionId_();
63 // Set the session start time if we haven't done so already.
64 if (remoting.LogToServer.isStartOfSession_(state)) {
65 if (this.sessionStartTime_ == 0) {
66 this.sessionStartTime_ = new Date().getTime();
69 // Log the session state change.
70 var entry = remoting.ServerLogEntry.makeClientSessionStateChange(
71 state, connectionError, this.mode_);
72 entry.addHostFields();
73 entry.addChromeVersionField();
74 entry.addWebappVersionField();
75 entry.addSessionIdField(this.sessionId_);
76 // Maybe clear the session start time, and log the session duration.
77 if (remoting.LogToServer.shouldAddDuration_(state) &&
78 (this.sessionStartTime_ != 0)) {
79 entry.addSessionDurationField(
80 (new Date().getTime() - this.sessionStartTime_) / 1000.0);
81 if (remoting.LogToServer.isEndOfSession_(state)) {
82 this.sessionStartTime_ = 0;
86 // Don't accumulate connection statistics across state changes.
87 this.logAccumulatedStatistics_();
88 this.statsAccumulator_.empty();
89 // Maybe clear the session ID.
90 if (remoting.LogToServer.isEndOfSession_(state)) {
91 this.clearSessionId_();
96 * Set the connection type (direct, stun relay).
98 * @param {string} connectionType
100 remoting.LogToServer.prototype.setConnectionType = function(connectionType) {
101 this.connectionType_ = connectionType;
105 * @param {remoting.SignalStrategy.Type} strategyType
106 * @param {remoting.FallbackSignalStrategy.Progress} progress
107 * @param {number} elapsedTimeInMs
109 remoting.LogToServer.prototype.logSignalStrategyProgress =
110 function(strategyType, progress, elapsedTimeInMs) {
111 this.maybeExpireSessionId_();
112 var entry = remoting.ServerLogEntry.makeSignalStrategyProgress(
113 this.sessionId_, strategyType, progress, elapsedTimeInMs);
118 * Whether a session state is one of the states that occurs at the start of
122 * @param {remoting.ClientSession.State} state
125 remoting.LogToServer.isStartOfSession_ = function(state) {
126 return ((state == remoting.ClientSession.State.CONNECTING) ||
127 (state == remoting.ClientSession.State.INITIALIZING) ||
128 (state == remoting.ClientSession.State.CONNECTED));
132 * Whether a session state is one of the states that occurs at the end of
136 * @param {remoting.ClientSession.State} state
139 remoting.LogToServer.isEndOfSession_ = function(state) {
140 return ((state == remoting.ClientSession.State.CLOSED) ||
141 (state == remoting.ClientSession.State.FAILED) ||
142 (state == remoting.ClientSession.State.CONNECTION_DROPPED) ||
143 (state == remoting.ClientSession.State.CONNECTION_CANCELED));
147 * Whether the duration should be added to the log entry for this state.
150 * @param {remoting.ClientSession.State} state
153 remoting.LogToServer.shouldAddDuration_ = function(state) {
154 // Duration is added to log entries at the end of the session, as well as at
155 // some intermediate states where it is relevant (e.g. to determine how long
156 // it took for a session to become CONNECTED).
157 return (remoting.LogToServer.isEndOfSession_(state) ||
158 (state == remoting.ClientSession.State.CONNECTED));
162 * Logs connection statistics.
163 * @param {Object<string, number>} stats The connection statistics
165 remoting.LogToServer.prototype.logStatistics = function(stats) {
166 this.maybeExpireSessionId_();
167 // Store the statistics.
168 this.statsAccumulator_.add(stats);
169 // Send statistics to the server if they've been accumulating for at least
171 if (this.statsAccumulator_.getTimeSinceFirstValue() >=
172 remoting.LogToServer.CONNECTION_STATS_ACCUMULATE_TIME) {
173 this.logAccumulatedStatistics_();
178 * Moves connection statistics from the accumulator to the log server.
180 * If all the statistics are zero, then the accumulator is still emptied,
181 * but the statistics are not sent to the log server.
185 remoting.LogToServer.prototype.logAccumulatedStatistics_ = function() {
186 var entry = remoting.ServerLogEntry.makeStats(this.statsAccumulator_,
187 this.connectionType_,
190 entry.addHostFields();
191 entry.addChromeVersionField();
192 entry.addWebappVersionField();
193 entry.addSessionIdField(this.sessionId_);
196 this.statsAccumulator_.empty();
200 * Sends a log entry to the server.
203 * @param {remoting.ServerLogEntry} entry
205 remoting.LogToServer.prototype.log_ = function(entry) {
206 // Send the stanza to the debug log.
207 console.log('Enqueueing log entry:');
210 var stanza = '<cli:iq to="' + remoting.settings.DIRECTORY_BOT_JID + '" ' +
211 'type="set" xmlns:cli="jabber:client">' +
212 '<gr:log xmlns:gr="google:remoting">' +
216 this.signalStrategy_.sendMessage(stanza);
220 * Sets the session ID to a random string.
224 remoting.LogToServer.prototype.setSessionId_ = function() {
225 this.sessionId_ = remoting.LogToServer.generateSessionId_();
226 this.sessionIdGenerationTime_ = new Date().getTime();
230 * Clears the session ID.
234 remoting.LogToServer.prototype.clearSessionId_ = function() {
235 this.sessionId_ = '';
236 this.sessionIdGenerationTime_ = 0;
240 * Sets a new session ID, if the current session ID has reached its maximum age.
242 * This method also logs the old and new session IDs to the server, in separate
247 remoting.LogToServer.prototype.maybeExpireSessionId_ = function() {
248 if ((this.sessionId_ != '') &&
249 (new Date().getTime() - this.sessionIdGenerationTime_ >=
250 remoting.LogToServer.MAX_SESSION_ID_AGE)) {
251 // Log the old session ID.
252 var entry = remoting.ServerLogEntry.makeSessionIdOld(this.sessionId_,
255 // Generate a new session ID.
256 this.setSessionId_();
257 // Log the new session ID.
258 entry = remoting.ServerLogEntry.makeSessionIdNew(this.sessionId_,
265 * Generates a string that can be used as a session ID.
268 * @return {string} a session ID
270 remoting.LogToServer.generateSessionId_ = function() {
272 for (var i = 0; i < remoting.LogToServer.SESSION_ID_LEN_; i++) {
274 Math.random() * remoting.LogToServer.SESSION_ID_ALPHABET_.length;
276 remoting.LogToServer.SESSION_ID_ALPHABET_.slice(index, index + 1));
278 return idArray.join('');