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 * A class of server log entries.
12 /** @suppress {duplicate} */
13 var remoting
= remoting
|| {};
19 remoting
.ServerLogEntry = function() {
20 /** @type Object.<string, string> */ this.dict
= {};
24 remoting
.ServerLogEntry
.KEY_EVENT_NAME_
= 'event-name';
26 remoting
.ServerLogEntry
.VALUE_EVENT_NAME_SESSION_STATE_
=
30 remoting
.ServerLogEntry
.KEY_SESSION_ID_
= 'session-id';
33 remoting
.ServerLogEntry
.KEY_ROLE_
= 'role';
35 remoting
.ServerLogEntry
.VALUE_ROLE_CLIENT_
= 'client';
38 remoting
.ServerLogEntry
.KEY_SESSION_STATE_
= 'session-state';
42 * @param {remoting.ClientSession.State} state
45 remoting
.ServerLogEntry
.getValueForSessionState = function(state
) {
47 case remoting
.ClientSession
.State
.UNKNOWN
:
49 case remoting
.ClientSession
.State
.CREATED
:
51 case remoting
.ClientSession
.State
.CONNECTING
:
53 case remoting
.ClientSession
.State
.INITIALIZING
:
54 return 'initializing';
55 case remoting
.ClientSession
.State
.CONNECTED
:
57 case remoting
.ClientSession
.State
.CLOSED
:
59 case remoting
.ClientSession
.State
.FAILED
:
60 return 'connection-failed';
61 case remoting
.ClientSession
.State
.CONNECTION_DROPPED
:
62 return 'connection-dropped';
63 case remoting
.ClientSession
.State
.CONNECTION_CANCELED
:
64 return 'connection-canceled';
66 return 'undefined-' + state
;
71 remoting
.ServerLogEntry
.KEY_CONNECTION_ERROR_
= 'connection-error';
75 * @param {remoting.Error} connectionError
78 remoting
.ServerLogEntry
.getValueForError
=
79 function(connectionError
) {
80 switch(connectionError
) {
81 case remoting
.Error
.NONE
:
83 case remoting
.Error
.INVALID_ACCESS_CODE
:
84 return 'invalid-access-code';
85 case remoting
.Error
.MISSING_PLUGIN
:
86 return 'missing_plugin';
87 case remoting
.Error
.AUTHENTICATION_FAILED
:
88 return 'authentication-failed';
89 case remoting
.Error
.HOST_IS_OFFLINE
:
90 return 'host-is-offline';
91 case remoting
.Error
.INCOMPATIBLE_PROTOCOL
:
92 return 'incompatible-protocol';
93 case remoting
.Error
.BAD_PLUGIN_VERSION
:
94 return 'bad-plugin-version';
95 case remoting
.Error
.NETWORK_FAILURE
:
96 return 'network-failure';
97 case remoting
.Error
.HOST_OVERLOAD
:
98 return 'host-overload';
99 case remoting
.Error
.P2P_FAILURE
:
100 return 'p2p-failure';
101 case remoting
.Error
.UNEXPECTED
:
104 return 'unknown-' + connectionError
;
109 remoting
.ServerLogEntry
.KEY_SESSION_DURATION_
= 'session-duration';
112 remoting
.ServerLogEntry
.VALUE_EVENT_NAME_CONNECTION_STATISTICS_
=
113 "connection-statistics";
115 remoting
.ServerLogEntry
.KEY_VIDEO_BANDWIDTH_
= "video-bandwidth";
117 remoting
.ServerLogEntry
.KEY_CAPTURE_LATENCY_
= "capture-latency";
119 remoting
.ServerLogEntry
.KEY_ENCODE_LATENCY_
= "encode-latency";
121 remoting
.ServerLogEntry
.KEY_DECODE_LATENCY_
= "decode-latency";
123 remoting
.ServerLogEntry
.KEY_RENDER_LATENCY_
= "render-latency";
125 remoting
.ServerLogEntry
.KEY_ROUNDTRIP_LATENCY_
= "roundtrip-latency";
128 remoting
.ServerLogEntry
.KEY_OS_NAME_
= 'os-name';
130 remoting
.ServerLogEntry
.VALUE_OS_NAME_WINDOWS_
= 'Windows';
132 remoting
.ServerLogEntry
.VALUE_OS_NAME_LINUX_
= 'Linux';
134 remoting
.ServerLogEntry
.VALUE_OS_NAME_MAC_
= 'Mac';
136 remoting
.ServerLogEntry
.VALUE_OS_NAME_CHROMEOS_
= 'ChromeOS';
139 remoting
.ServerLogEntry
.KEY_OS_VERSION_
= 'os-version';
142 remoting
.ServerLogEntry
.KEY_CPU_
= 'cpu';
145 remoting
.ServerLogEntry
.KEY_BROWSER_VERSION_
= 'browser-version';
148 remoting
.ServerLogEntry
.KEY_WEBAPP_VERSION_
= 'webapp-version';
151 remoting
.ServerLogEntry
.VALUE_EVENT_NAME_SESSION_ID_OLD_
= 'session-id-old';
154 remoting
.ServerLogEntry
.VALUE_EVENT_NAME_SESSION_ID_NEW_
= 'session-id-new';
157 remoting
.ServerLogEntry
.KEY_MODE_
= 'mode';
159 remoting
.ServerLogEntry
.VALUE_MODE_IT2ME_
= 'it2me';
161 remoting
.ServerLogEntry
.VALUE_MODE_ME2ME_
= 'me2me';
163 remoting
.ServerLogEntry
.VALUE_MODE_UNKNOWN_
= 'unknown';
166 * Sets one field in this log entry.
169 * @param {string} key
170 * @param {string} value
172 remoting
.ServerLogEntry
.prototype.set = function(key
, value
) {
173 this.dict
[key
] = value
;
177 * Converts this object into an XML stanza.
181 remoting
.ServerLogEntry
.prototype.toStanza = function() {
182 var stanza
= '<gr:entry ';
183 for (var key
in this.dict
) {
184 stanza
+= escape(key
) + '="' + escape(this.dict
[key
]) + '" ';
191 * Prints this object on the debug log.
193 * @param {number} indentLevel the indentation level
195 remoting
.ServerLogEntry
.prototype.toDebugLog = function(indentLevel
) {
196 /** @type Array.<string> */ var fields
= [];
197 for (var key
in this.dict
) {
198 fields
.push(key
+ ': ' + this.dict
[key
]);
200 console
.log(Array(indentLevel
+1).join(" ") + fields
.join(', '));
204 * Makes a log entry for a change of client session state.
206 * @param {remoting.ClientSession.State} state
207 * @param {remoting.Error} connectionError
208 * @param {remoting.ClientSession.Mode} mode
209 * @return {remoting.ServerLogEntry}
211 remoting
.ServerLogEntry
.makeClientSessionStateChange = function(state
,
212 connectionError
, mode
) {
213 var entry
= new remoting
.ServerLogEntry();
214 entry
.set(remoting
.ServerLogEntry
.KEY_ROLE_
,
215 remoting
.ServerLogEntry
.VALUE_ROLE_CLIENT_
);
216 entry
.set(remoting
.ServerLogEntry
.KEY_EVENT_NAME_
,
217 remoting
.ServerLogEntry
.VALUE_EVENT_NAME_SESSION_STATE_
);
218 entry
.set(remoting
.ServerLogEntry
.KEY_SESSION_STATE_
,
219 remoting
.ServerLogEntry
.getValueForSessionState(state
));
220 if (connectionError
!= remoting
.Error
.NONE
) {
221 entry
.set(remoting
.ServerLogEntry
.KEY_CONNECTION_ERROR_
,
222 remoting
.ServerLogEntry
.getValueForError(connectionError
));
224 entry
.addModeField(mode
);
229 * Adds a session duration to a log entry.
231 * @param {number} sessionDuration
233 remoting
.ServerLogEntry
.prototype.addSessionDurationField = function(
235 this.set(remoting
.ServerLogEntry
.KEY_SESSION_DURATION_
,
236 sessionDuration
.toString());
240 * Makes a log entry for a set of connection statistics.
241 * Returns null if all the statistics were zero.
243 * @param {remoting.StatsAccumulator} statsAccumulator
244 * @param {remoting.ClientSession.Mode} mode
245 * @return {?remoting.ServerLogEntry}
247 remoting
.ServerLogEntry
.makeStats = function(statsAccumulator
, mode
) {
248 var entry
= new remoting
.ServerLogEntry();
249 entry
.set(remoting
.ServerLogEntry
.KEY_ROLE_
,
250 remoting
.ServerLogEntry
.VALUE_ROLE_CLIENT_
);
251 entry
.set(remoting
.ServerLogEntry
.KEY_EVENT_NAME_
,
252 remoting
.ServerLogEntry
.VALUE_EVENT_NAME_CONNECTION_STATISTICS_
);
253 entry
.addModeField(mode
);
255 nonZero
|= entry
.addStatsField(
256 remoting
.ServerLogEntry
.KEY_VIDEO_BANDWIDTH_
,
257 remoting
.ClientSession
.STATS_KEY_VIDEO_BANDWIDTH
, statsAccumulator
);
258 nonZero
|= entry
.addStatsField(
259 remoting
.ServerLogEntry
.KEY_CAPTURE_LATENCY_
,
260 remoting
.ClientSession
.STATS_KEY_CAPTURE_LATENCY
, statsAccumulator
);
261 nonZero
|= entry
.addStatsField(
262 remoting
.ServerLogEntry
.KEY_ENCODE_LATENCY_
,
263 remoting
.ClientSession
.STATS_KEY_ENCODE_LATENCY
, statsAccumulator
);
264 nonZero
|= entry
.addStatsField(
265 remoting
.ServerLogEntry
.KEY_DECODE_LATENCY_
,
266 remoting
.ClientSession
.STATS_KEY_DECODE_LATENCY
, statsAccumulator
);
267 nonZero
|= entry
.addStatsField(
268 remoting
.ServerLogEntry
.KEY_RENDER_LATENCY_
,
269 remoting
.ClientSession
.STATS_KEY_RENDER_LATENCY
, statsAccumulator
);
270 nonZero
|= entry
.addStatsField(
271 remoting
.ServerLogEntry
.KEY_ROUNDTRIP_LATENCY_
,
272 remoting
.ClientSession
.STATS_KEY_ROUNDTRIP_LATENCY
, statsAccumulator
);
280 * Adds one connection statistic to a log entry.
283 * @param {string} entryKey
284 * @param {string} statsKey
285 * @param {remoting.StatsAccumulator} statsAccumulator
286 * @return {boolean} whether the statistic is non-zero
288 remoting
.ServerLogEntry
.prototype.addStatsField = function(
289 entryKey
, statsKey
, statsAccumulator
) {
290 var val
= statsAccumulator
.calcMean(statsKey
);
291 this.set(entryKey
, val
.toFixed(2));
296 * Makes a log entry for a "this session ID is old" event.
298 * @param {string} sessionId
299 * @param {remoting.ClientSession.Mode} mode
300 * @return {remoting.ServerLogEntry}
302 remoting
.ServerLogEntry
.makeSessionIdOld = function(sessionId
, mode
) {
303 var entry
= new remoting
.ServerLogEntry();
304 entry
.set(remoting
.ServerLogEntry
.KEY_ROLE_
,
305 remoting
.ServerLogEntry
.VALUE_ROLE_CLIENT_
);
306 entry
.set(remoting
.ServerLogEntry
.KEY_EVENT_NAME_
,
307 remoting
.ServerLogEntry
.VALUE_EVENT_NAME_SESSION_ID_OLD_
);
308 entry
.addSessionIdField(sessionId
);
309 entry
.addModeField(mode
);
314 * Makes a log entry for a "this session ID is new" event.
316 * @param {string} sessionId
317 * @param {remoting.ClientSession.Mode} mode
318 * @return {remoting.ServerLogEntry}
320 remoting
.ServerLogEntry
.makeSessionIdNew = function(sessionId
, mode
) {
321 var entry
= new remoting
.ServerLogEntry();
322 entry
.set(remoting
.ServerLogEntry
.KEY_ROLE_
,
323 remoting
.ServerLogEntry
.VALUE_ROLE_CLIENT_
);
324 entry
.set(remoting
.ServerLogEntry
.KEY_EVENT_NAME_
,
325 remoting
.ServerLogEntry
.VALUE_EVENT_NAME_SESSION_ID_NEW_
);
326 entry
.addSessionIdField(sessionId
);
327 entry
.addModeField(mode
);
332 * Adds a session ID field to this log entry.
334 * @param {string} sessionId
336 remoting
.ServerLogEntry
.prototype.addSessionIdField = function(sessionId
) {
337 this.set(remoting
.ServerLogEntry
.KEY_SESSION_ID_
, sessionId
);
341 * Adds fields describing the host to this log entry.
343 remoting
.ServerLogEntry
.prototype.addHostFields = function() {
344 var host
= remoting
.ServerLogEntry
.getHostData();
346 if (host
.os_name
.length
> 0) {
347 this.set(remoting
.ServerLogEntry
.KEY_OS_NAME_
, host
.os_name
);
349 if (host
.os_version
.length
> 0) {
350 this.set(remoting
.ServerLogEntry
.KEY_OS_VERSION_
, host
.os_version
);
352 if (host
.cpu
.length
> 0) {
353 this.set(remoting
.ServerLogEntry
.KEY_CPU_
, host
.cpu
);
359 * Extracts host data from the userAgent string.
362 * @return {{os_name:string, os_version:string, cpu:string} | null}
364 remoting
.ServerLogEntry
.getHostData = function() {
365 return remoting
.ServerLogEntry
.extractHostDataFrom(navigator
.userAgent
);
369 * Extracts host data from the given userAgent string.
373 * @return {{os_name:string, os_version:string, cpu:string} | null}
375 remoting
.ServerLogEntry
.extractHostDataFrom = function(s
) {
376 // Sample userAgent strings:
377 // 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 ' +
378 // '(KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2'
379 // 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.8 ' +
380 // '(KHTML, like Gecko) Chrome/17.0.933.0 Safari/535.8'
381 // 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.1 ' +
382 // '(KHTML, like Gecko) Chrome/14.0.835.202 Safari/535.1'
383 // 'Mozilla/5.0 (X11; CrOS i686 14.811.154) AppleWebKit/535.1 ' +
384 // '(KHTML, like Gecko) Chrome/14.0.835.204 Safari/535.1'
385 var match
= new RegExp('Windows NT ([0-9\\.]*)').exec(s
);
386 if (match
&& (match
.length
>= 2)) {
388 'os_name': remoting
.ServerLogEntry
.VALUE_OS_NAME_WINDOWS_
,
389 'os_version': match
[1],
393 match
= new RegExp('Linux ([a-zA-Z0-9_]*)').exec(s
);
394 if (match
&& (match
.length
>= 2)) {
396 'os_name': remoting
.ServerLogEntry
.VALUE_OS_NAME_LINUX_
,
401 match
= new RegExp('([a-zA-Z]*) Mac OS X ([0-9_]*)').exec(s
);
402 if (match
&& (match
.length
>= 3)) {
404 'os_name': remoting
.ServerLogEntry
.VALUE_OS_NAME_MAC_
,
405 'os_version': match
[2].replace(/_
/g
, '.'),
409 match
= new RegExp('CrOS ([a-zA-Z0-9]*) ([0-9.]*)').exec(s
);
410 if (match
&& (match
.length
>= 3)) {
412 'os_name': remoting
.ServerLogEntry
.VALUE_OS_NAME_CHROMEOS_
,
413 'os_version': match
[2],
421 * Adds a field specifying the browser version to this log entry.
423 remoting
.ServerLogEntry
.prototype.addChromeVersionField = function() {
424 var version
= remoting
.getChromeVersion();
425 if (version
!= null) {
426 this.set(remoting
.ServerLogEntry
.KEY_BROWSER_VERSION_
, version
);
431 * Adds a field specifying the webapp version to this log entry.
433 remoting
.ServerLogEntry
.prototype.addWebappVersionField = function() {
434 var manifest
= chrome
.runtime
.getManifest();
435 if (manifest
&& manifest
.version
) {
436 this.set(remoting
.ServerLogEntry
.KEY_WEBAPP_VERSION_
, manifest
.version
);
441 * Adds a field specifying the mode to this log entry.
443 * @param {remoting.ClientSession.Mode} mode
445 remoting
.ServerLogEntry
.prototype.addModeField = function(mode
) {
446 this.set(remoting
.ServerLogEntry
.KEY_MODE_
,
447 remoting
.ServerLogEntry
.getModeField(mode
));
451 * Gets the value of the mode field to be put in a log entry.
454 * @param {remoting.ClientSession.Mode} mode
457 remoting
.ServerLogEntry
.getModeField = function(mode
) {
459 case remoting
.ClientSession
.Mode
.IT2ME
:
460 return remoting
.ServerLogEntry
.VALUE_MODE_IT2ME_
;
461 case remoting
.ClientSession
.Mode
.ME2ME
:
462 return remoting
.ServerLogEntry
.VALUE_MODE_ME2ME_
;
464 return remoting
.ServerLogEntry
.VALUE_MODE_UNKNOWN_
;