1// Copyright 2014 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#include "remoting/client/server_log_entry_client.h"
6
7#include "base/strings/string_number_conversions.h"
8#include "base/strings/stringize_macros.h"
9#include "base/strings/stringprintf.h"
10#include "base/sys_info.h"
11#include "remoting/client/chromoting_stats.h"
12#include "remoting/signaling/server_log_entry.h"
13
14using base::StringPrintf;
15using base::SysInfo;
16using remoting::protocol::ConnectionToHost;
17using remoting::protocol::ErrorCode;
18
19namespace remoting {
20
21namespace {
22const char kValueRoleClient[] = "client";
23
24const char kValueEventNameSessionState[] = "session-state";
25const char kValueEventNameStatistics[] = "connection-statistics";
26const char kValueEventNameSessionIdOld[] = "session-id-old";
27const char kValueEventNameSessionIdNew[] = "session-id-new";
28
29const char kKeySessionId[] = "session-id";
30const char kKeySessionDuration[] = "session-duration";
31
32const char kKeySessionState[] = "session-state";
33const char kKeyConnectionError[] = "connection-error";
34const char kValueSessionStateConnected[] = "connected";
35const char kValueSessionStateClosed[] = "closed";
36
37const char kKeyOsName[] = "os-name";
38const char kKeyOsVersion[] = "os-version";
39const char kKeyAppVersion[] = "app-version";
40
41const char* GetValueSessionState(ConnectionToHost::State state) {
42  switch (state) {
43    // Where possible, these are the same strings that the webapp sends for the
44    // corresponding state - see remoting/webapp/server_log_entry.js.
45    case ConnectionToHost::INITIALIZING:
46      return "initializing";
47    case ConnectionToHost::CONNECTING:
48      return "connecting";
49    case ConnectionToHost::AUTHENTICATED:
50      return "authenticated";
51    case ConnectionToHost::CONNECTED:
52      return kValueSessionStateConnected;
53    case ConnectionToHost::FAILED:
54      return "connection-failed";
55    case ConnectionToHost::CLOSED:
56      return kValueSessionStateClosed;
57    default:
58      NOTREACHED();
59      return NULL;
60  }
61}
62
63const char* GetValueError(ErrorCode error) {
64  switch (error) {
65    // Where possible, these are the same strings that the webapp sends for the
66    // corresponding error - see remoting/webapp/server_log_entry.js.
67    case protocol::OK:
68      return "none";
69    case protocol::PEER_IS_OFFLINE:
70      return "host-is-offline";
71    case protocol::SESSION_REJECTED:
72      return "session-rejected";
73    case protocol::INCOMPATIBLE_PROTOCOL:
74      return "incompatible-protocol";
75    case protocol::AUTHENTICATION_FAILED:
76      return "authentication-failed";
77    case protocol::CHANNEL_CONNECTION_ERROR:
78      return "channel-connection-error";
79    case protocol::SIGNALING_ERROR:
80      return "signaling-error";
81    case protocol::SIGNALING_TIMEOUT:
82      return "signaling-timeout";
83    case protocol::HOST_OVERLOAD:
84      return "host-overload";
85    case protocol::UNKNOWN_ERROR:
86      return "unknown-error";
87    default:
88      NOTREACHED();
89      return NULL;
90  }
91}
92
93}  // namespace
94
95scoped_ptr<ServerLogEntry> MakeLogEntryForSessionStateChange(
96    ConnectionToHost::State state,
97    ErrorCode error) {
98  scoped_ptr<ServerLogEntry> entry(new ServerLogEntry());
99  entry->AddRoleField(kValueRoleClient);
100  entry->AddEventNameField(kValueEventNameSessionState);
101
102  entry->Set(kKeySessionState, GetValueSessionState(state));
103  if (error != protocol::OK) {
104    entry->Set(kKeyConnectionError, GetValueError(error));
105  }
106
107  return entry.Pass();
108}
109
110scoped_ptr<ServerLogEntry> MakeLogEntryForStatistics(
111    ChromotingStats* statistics) {
112  scoped_ptr<ServerLogEntry> entry(new ServerLogEntry());
113  entry->AddRoleField(kValueRoleClient);
114  entry->AddEventNameField(kValueEventNameStatistics);
115
116  entry->Set("video-bandwidth",
117             StringPrintf("%.2f", statistics->video_bandwidth()->Rate()));
118  entry->Set("capture-latency",
119             StringPrintf("%.2f", statistics->video_capture_ms()->Average()));
120  entry->Set("encode-latency",
121             StringPrintf("%.2f", statistics->video_encode_ms()->Average()));
122  entry->Set("decode-latency",
123             StringPrintf("%.2f", statistics->video_decode_ms()->Average()));
124  entry->Set("render-latency",
125             StringPrintf("%.2f", statistics->video_frame_rate()->Rate()));
126  entry->Set("roundtrip-latency",
127             StringPrintf("%.2f", statistics->round_trip_ms()->Average()));
128
129  return entry.Pass();
130}
131
132scoped_ptr<ServerLogEntry> MakeLogEntryForSessionIdOld(
133    const std::string& session_id) {
134  scoped_ptr<ServerLogEntry> entry(new ServerLogEntry());
135  entry->AddRoleField(kValueRoleClient);
136  entry->AddEventNameField(kValueEventNameSessionIdOld);
137  AddSessionIdToLogEntry(entry.get(), session_id);
138  return entry.Pass();
139}
140
141scoped_ptr<ServerLogEntry> MakeLogEntryForSessionIdNew(
142    const std::string& session_id) {
143  scoped_ptr<ServerLogEntry> entry(new ServerLogEntry());
144  entry->AddRoleField(kValueRoleClient);
145  entry->AddEventNameField(kValueEventNameSessionIdNew);
146  AddSessionIdToLogEntry(entry.get(), session_id);
147  return entry.Pass();
148}
149
150void AddClientFieldsToLogEntry(ServerLogEntry* entry) {
151  entry->Set(kKeyOsName, SysInfo::OperatingSystemName());
152  entry->Set(kKeyOsVersion, SysInfo::OperatingSystemVersion());
153  entry->Set(kKeyAppVersion, STRINGIZE(VERSION));
154  entry->AddCpuField();
155}
156
157void AddSessionIdToLogEntry(ServerLogEntry* entry, const std::string& id) {
158  entry->Set(kKeySessionId, id);
159}
160
161void AddSessionDurationToLogEntry(ServerLogEntry* entry,
162                                  base::TimeDelta duration) {
163  entry->Set(kKeySessionDuration, base::Int64ToString(duration.InSeconds()));
164}
165
166}  // namespace remoting
167