Roll usrcstplib -> r9048.
[chromium-blink-merge.git] / remoting / webapp / log_to_server.js
blob53cf161cbbb83e14bdc5f370b8b90e1207542267
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.
5 /**
6  * @fileoverview
7  * Module for sending log entries to the server.
8  */
10 'use strict';
12 /** @suppress {duplicate} */
13 var remoting = remoting || {};
15 /**
16  * @param {remoting.SignalStrategy} signalStrategy Signal strategy.
17  * @constructor
18  */
19 remoting.LogToServer = function(signalStrategy) {
20   /** @private */
21   this.statsAccumulator_ = new remoting.StatsAccumulator();
22   /** @private */
23   this.sessionId_ = '';
24   /** @private */
25   this.sessionIdGenerationTime_ = 0;
26   /** @private */
27   this.sessionStartTime_ = 0;
28   /** @private */
29   this.signalStrategy_ = signalStrategy;
32 // Constants used for generating a session ID.
33 /** @private */
34 remoting.LogToServer.SESSION_ID_ALPHABET_ =
35     'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
36 /** @private */
37 remoting.LogToServer.SESSION_ID_LEN_ = 20;
39 // The maximum age of a session ID, in milliseconds.
40 remoting.LogToServer.MAX_SESSION_ID_AGE = 24 * 60 * 60 * 1000;
42 // The time over which to accumulate connection statistics before logging them
43 // to the server, in milliseconds.
44 remoting.LogToServer.CONNECTION_STATS_ACCUMULATE_TIME = 60 * 1000;
46 /**
47  * Logs a client session state change.
48  *
49  * @param {remoting.ClientSession.State} state
50  * @param {remoting.Error} connectionError
51  * @param {remoting.ClientSession.Mode} mode
52  */
53 remoting.LogToServer.prototype.logClientSessionStateChange =
54     function(state, connectionError, mode) {
55   this.maybeExpireSessionId(mode);
56   // Maybe set the session ID and start time.
57   if (remoting.LogToServer.isStartOfSession(state)) {
58     if (this.sessionId_ == '') {
59       this.setSessionId();
60     }
61     if (this.sessionStartTime_ == 0) {
62       this.sessionStartTime_ = new Date().getTime();
63     }
64   }
65   // Log the session state change.
66   var entry = remoting.ServerLogEntry.makeClientSessionStateChange(
67       state, connectionError, mode);
68   entry.addHostFields();
69   entry.addChromeVersionField();
70   entry.addWebappVersionField();
71   entry.addSessionIdField(this.sessionId_);
72   // Maybe clear the session start time, and log the session duration.
73   if (remoting.LogToServer.shouldAddDuration(state) &&
74       (this.sessionStartTime_ != 0)) {
75     entry.addSessionDurationField(
76         (new Date().getTime() - this.sessionStartTime_) / 1000.0);
77     if (remoting.LogToServer.isEndOfSession(state)) {
78       this.sessionStartTime_ = 0;
79     }
80   }
81   this.log(entry);
82   // Don't accumulate connection statistics across state changes.
83   this.logAccumulatedStatistics(mode);
84   this.statsAccumulator_.empty();
85   // Maybe clear the session ID.
86   if (remoting.LogToServer.isEndOfSession(state)) {
87     this.clearSessionId();
88   }
91 /**
92  * Whether a session state is one of the states that occurs at the start of
93  * a session.
94  *
95  * @private
96  * @param {remoting.ClientSession.State} state
97  * @return {boolean}
98  */
99 remoting.LogToServer.isStartOfSession = function(state) {
100   return ((state == remoting.ClientSession.State.CONNECTING) ||
101       (state == remoting.ClientSession.State.INITIALIZING) ||
102       (state == remoting.ClientSession.State.CONNECTED));
106  * Whether a session state is one of the states that occurs at the end of
107  * a session.
109  * @private
110  * @param {remoting.ClientSession.State} state
111  * @return {boolean}
112  */
113 remoting.LogToServer.isEndOfSession = function(state) {
114   return ((state == remoting.ClientSession.State.CLOSED) ||
115       (state == remoting.ClientSession.State.FAILED) ||
116       (state == remoting.ClientSession.State.CONNECTION_DROPPED) ||
117       (state == remoting.ClientSession.State.CONNECTION_CANCELED));
121  * Whether the duration should be added to the log entry for this state.
123  * @private
124  * @param {remoting.ClientSession.State} state
125  * @return {boolean}
126  */
127 remoting.LogToServer.shouldAddDuration = function(state) {
128   // Duration is added to log entries at the end of the session, as well as at
129   // some intermediate states where it is relevant (e.g. to determine how long
130   // it took for a session to become CONNECTED).
131   return (remoting.LogToServer.isEndOfSession(state) ||
132       (state == remoting.ClientSession.State.CONNECTED));
136  * Logs connection statistics.
137  * @param {Object.<string, number>} stats the connection statistics
138  * @param {remoting.ClientSession.Mode} mode
139  */
140 remoting.LogToServer.prototype.logStatistics = function(stats, mode) {
141   this.maybeExpireSessionId(mode);
142   // Store the statistics.
143   this.statsAccumulator_.add(stats);
144   // Send statistics to the server if they've been accumulating for at least
145   // 60 seconds.
146   if (this.statsAccumulator_.getTimeSinceFirstValue() >=
147       remoting.LogToServer.CONNECTION_STATS_ACCUMULATE_TIME) {
148     this.logAccumulatedStatistics(mode);
149   }
153  * Moves connection statistics from the accumulator to the log server.
155  * If all the statistics are zero, then the accumulator is still emptied,
156  * but the statistics are not sent to the log server.
158  * @private
159  * @param {remoting.ClientSession.Mode} mode
160  */
161 remoting.LogToServer.prototype.logAccumulatedStatistics = function(mode) {
162   var entry = remoting.ServerLogEntry.makeStats(this.statsAccumulator_, mode);
163   if (entry) {
164     entry.addHostFields();
165     entry.addChromeVersionField();
166     entry.addWebappVersionField();
167     entry.addSessionIdField(this.sessionId_);
168     this.log(entry);
169   }
170   this.statsAccumulator_.empty();
174  * Sends a log entry to the server.
176  * @private
177  * @param {remoting.ServerLogEntry} entry
178  */
179 remoting.LogToServer.prototype.log = function(entry) {
180   // Send the stanza to the debug log.
181   console.log('Enqueueing log entry:');
182   entry.toDebugLog(1);
184   var stanza = '<cli:iq to="' + remoting.settings.DIRECTORY_BOT_JID + '" ' +
185                        'type="set" xmlns:cli="jabber:client">' +
186                  '<gr:log xmlns:gr="google:remoting">' +
187                    entry.toStanza() +
188                  '</gr:log>' +
189                '</cli:iq>';
190   this.signalStrategy_.sendMessage(stanza);
194  * Sets the session ID to a random string.
196  * @private
197  */
198 remoting.LogToServer.prototype.setSessionId = function() {
199   this.sessionId_ = remoting.LogToServer.generateSessionId();
200   this.sessionIdGenerationTime_ = new Date().getTime();
204  * Clears the session ID.
206  * @private
207  */
208 remoting.LogToServer.prototype.clearSessionId = function() {
209   this.sessionId_ = '';
210   this.sessionIdGenerationTime_ = 0;
214  * Sets a new session ID, if the current session ID has reached its maximum age.
216  * This method also logs the old and new session IDs to the server, in separate
217  * log entries.
219  * @private
220  * @param {remoting.ClientSession.Mode} mode
221  */
222 remoting.LogToServer.prototype.maybeExpireSessionId = function(mode) {
223   if ((this.sessionId_ != '') &&
224       (new Date().getTime() - this.sessionIdGenerationTime_ >=
225       remoting.LogToServer.MAX_SESSION_ID_AGE)) {
226     // Log the old session ID.
227     var entry = remoting.ServerLogEntry.makeSessionIdOld(this.sessionId_, mode);
228     this.log(entry);
229     // Generate a new session ID.
230     this.setSessionId();
231     // Log the new session ID.
232     entry = remoting.ServerLogEntry.makeSessionIdNew(this.sessionId_, mode);
233     this.log(entry);
234   }
238  * Generates a string that can be used as a session ID.
240  * @private
241  * @return {string} a session ID
242  */
243 remoting.LogToServer.generateSessionId = function() {
244   var idArray = [];
245   for (var i = 0; i < remoting.LogToServer.SESSION_ID_LEN_; i++) {
246     var index =
247         Math.random() * remoting.LogToServer.SESSION_ID_ALPHABET_.length;
248     idArray.push(
249         remoting.LogToServer.SESSION_ID_ALPHABET_.slice(index, index + 1));
250   }
251   return idArray.join('');