diff options
author | lambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-09 20:48:58 +0000 |
---|---|---|
committer | lambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-09 20:48:58 +0000 |
commit | 33030585c878d09ec9812bfae08a0f7153056ff4 (patch) | |
tree | 582e0143017ffb5defaec9abf12aef61dffb919d | |
parent | 22c1d05e1d769df249ccf83d91174bff333cf87b (diff) | |
download | chromium_src-33030585c878d09ec9812bfae08a0f7153056ff4.zip chromium_src-33030585c878d09ec9812bfae08a0f7153056ff4.tar.gz chromium_src-33030585c878d09ec9812bfae08a0f7153056ff4.tar.bz2 |
Implement stats reporting in Android client
This reports the same connection statistics and session change events
that are currently reported by the web-app.
Caveats:
This does not provide Chrome or Webapp versions - instead it
reports the Android OS version, and the app version, under
differently-named keys.
Session termination events don't seem to be reported. This is a
limitation of the Android client that might not be easy to work around.
BUG=368015
R=rmsousa@chromium.org
Review URL: https://codereview.chromium.org/270613005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269404 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | remoting/client/jni/chromoting_jni_instance.cc | 13 | ||||
-rw-r--r-- | remoting/client/jni/chromoting_jni_instance.h | 5 | ||||
-rw-r--r-- | remoting/client/log_to_server.cc | 194 | ||||
-rw-r--r-- | remoting/client/log_to_server.h | 90 | ||||
-rw-r--r-- | remoting/client/server_log_entry.cc | 238 | ||||
-rw-r--r-- | remoting/client/server_log_entry.h | 93 | ||||
-rw-r--r-- | remoting/remoting_client.gypi | 3 | ||||
-rw-r--r-- | remoting/remoting_srcs.gypi | 4 |
8 files changed, 639 insertions, 1 deletions
diff --git a/remoting/client/jni/chromoting_jni_instance.cc b/remoting/client/jni/chromoting_jni_instance.cc index 19e78971..3f9bd22 100644 --- a/remoting/client/jni/chromoting_jni_instance.cc +++ b/remoting/client/jni/chromoting_jni_instance.cc @@ -12,6 +12,8 @@ #include "remoting/client/audio_player.h" #include "remoting/client/jni/android_keymap.h" #include "remoting/client/jni/chromoting_jni_runtime.h" +#include "remoting/client/log_to_server.h" +#include "remoting/client/server_log_entry.h" #include "remoting/client/software_video_renderer.h" #include "remoting/jingle_glue/chromium_port_allocator.h" #include "remoting/jingle_glue/chromium_socket_factory.h" @@ -29,7 +31,7 @@ const int kXmppPort = 5222; const bool kXmppUseTls = true; // Interval at which to log performance statistics, if enabled. -const int kPerfStatsIntervalMs = 10000; +const int kPerfStatsIntervalMs = 60000; } @@ -215,6 +217,8 @@ void ChromotingJniInstance::OnConnectionState( EnableStatsLogging(state == protocol::ConnectionToHost::CONNECTED); + log_to_server_->LogSessionStateChange(state, error); + if (create_pairing_ && state == protocol::ConnectionToHost::CONNECTED) { protocol::PairingRequest request; DCHECK(!device_name_.empty()); @@ -332,6 +336,10 @@ void ChromotingJniInstance::ConnectToHostOnNetworkThread() { net::ClientSocketFactory::GetDefaultFactory(), jni_runtime_->url_requester(), xmpp_config_)); + log_to_server_.reset(new client::LogToServer(client::ServerLogEntry::ME2ME, + signaling_.get(), + "remoting@bot.talk.google.com")); + NetworkSettings network_settings(NetworkSettings::NAT_TRAVERSAL_FULL); // Use Chrome's network stack to allocate ports for peer-to-peer channels. @@ -358,6 +366,7 @@ void ChromotingJniInstance::DisconnectFromHostOnNetworkThread() { // |client_| must be torn down before |signaling_|. connection_.reset(); client_.reset(); + log_to_server_.reset(); } void ChromotingJniInstance::FetchSecret( @@ -420,6 +429,8 @@ void ChromotingJniInstance::LogPerfStats() { stats->video_paint_ms()->Average(), stats->round_trip_ms()->Average()); + log_to_server_->LogStatistics(stats); + jni_runtime_->network_task_runner()->PostDelayedTask( FROM_HERE, base::Bind(&ChromotingJniInstance::LogPerfStats, this), base::TimeDelta::FromMilliseconds(kPerfStatsIntervalMs)); diff --git a/remoting/client/jni/chromoting_jni_instance.h b/remoting/client/jni/chromoting_jni_instance.h index edb8b4a..0840497 100644 --- a/remoting/client/jni/chromoting_jni_instance.h +++ b/remoting/client/jni/chromoting_jni_instance.h @@ -29,6 +29,10 @@ class ClipboardEvent; class CursorShapeInfo; } // namespace protocol +namespace client { +class LogToServer; +} + class VideoRenderer; // ClientUserInterface that indirectly makes and receives JNI calls. @@ -148,6 +152,7 @@ class ChromotingJniInstance scoped_ptr<ChromotingClient> client_; XmppSignalStrategy::XmppServerConfig xmpp_config_; scoped_ptr<XmppSignalStrategy> signaling_; // Must outlive client_ + scoped_ptr<client::LogToServer> log_to_server_; // Pass this the user's PIN once we have it. To be assigned and accessed on // the UI thread, but must be posted to the network thread to call it. diff --git a/remoting/client/log_to_server.cc b/remoting/client/log_to_server.cc new file mode 100644 index 0000000..c45ad38 --- /dev/null +++ b/remoting/client/log_to_server.cc @@ -0,0 +1,194 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/client/log_to_server.h" + +#include "base/macros.h" +#include "base/rand_util.h" +#include "remoting/base/constants.h" +#include "remoting/client/chromoting_stats.h" +#include "remoting/jingle_glue/iq_sender.h" +#include "remoting/jingle_glue/signal_strategy.h" +#include "third_party/libjingle/source/talk/xmllite/xmlelement.h" +#include "third_party/libjingle/source/talk/xmpp/constants.h" + +using buzz::QName; +using buzz::XmlElement; +using remoting::protocol::ConnectionToHost; + +namespace { + +const char kSessionIdAlphabet[] = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; +const int kSessionIdLength = 20; + +const int kMaxSessionIdAgeDays = 1; + +bool IsStartOfSession(ConnectionToHost::State state) { + return state == ConnectionToHost::INITIALIZING || + state == ConnectionToHost::CONNECTING || + state == ConnectionToHost::AUTHENTICATED || + state == ConnectionToHost::CONNECTED; +} + +bool IsEndOfSession(ConnectionToHost::State state) { + return state == ConnectionToHost::FAILED || + state == ConnectionToHost::CLOSED; +} + +bool ShouldAddDuration(ConnectionToHost::State state) { + // Duration is added to log entries at the end of the session, as well as at + // some intermediate states where it is relevant (e.g. to determine how long + // it took for a session to become CONNECTED). + return IsEndOfSession(state) || state == ConnectionToHost::CONNECTED; +} + +} // namespace + +namespace remoting { + +namespace client { + +LogToServer::LogToServer(ServerLogEntry::Mode mode, + SignalStrategy* signal_strategy, + const std::string& directory_bot_jid) + : mode_(mode), + signal_strategy_(signal_strategy), + directory_bot_jid_(directory_bot_jid) { + signal_strategy_->AddListener(this); +} + +LogToServer::~LogToServer() { + signal_strategy_->RemoveListener(this); +} + +void LogToServer::LogSessionStateChange( + protocol::ConnectionToHost::State state, + protocol::ErrorCode error) { + DCHECK(CalledOnValidThread()); + + scoped_ptr<ServerLogEntry> entry( + ServerLogEntry::MakeForSessionStateChange(state, error)); + entry->AddClientFields(); + entry->AddModeField(mode_); + + MaybeExpireSessionId(); + if (IsStartOfSession(state)) { + // Maybe set the session ID and start time. + if (session_id_.empty()) { + GenerateSessionId(); + } + if (session_start_time_.is_null()) { + session_start_time_ = base::TimeTicks::Now(); + } + } + + if (!session_id_.empty()) { + entry->AddSessionId(session_id_); + } + + // Maybe clear the session start time and log the session duration. + if (ShouldAddDuration(state) && !session_start_time_.is_null()) { + entry->AddSessionDuration(base::TimeTicks::Now() - session_start_time_); + } + + if (IsEndOfSession(state)) { + session_start_time_ = base::TimeTicks(); + session_id_.clear(); + } + + Log(*entry.get()); +} + +void LogToServer::LogStatistics(ChromotingStats* statistics) { + DCHECK(CalledOnValidThread()); + + MaybeExpireSessionId(); + + scoped_ptr<ServerLogEntry> entry( + ServerLogEntry::MakeForStatistics(statistics)); + entry->AddClientFields(); + entry->AddModeField(mode_); + entry->AddSessionId(session_id_); + Log(*entry.get()); +} + +void LogToServer::OnSignalStrategyStateChange(SignalStrategy::State state) { + DCHECK(CalledOnValidThread()); + + if (state == SignalStrategy::CONNECTED) { + iq_sender_.reset(new IqSender(signal_strategy_)); + SendPendingEntries(); + } else if (state == SignalStrategy::DISCONNECTED) { + iq_sender_.reset(); + } +} + +bool LogToServer::OnSignalStrategyIncomingStanza( + const buzz::XmlElement* stanza) { + return false; +} + +void LogToServer::Log(const ServerLogEntry& entry) { + pending_entries_.push_back(entry); + SendPendingEntries(); +} + +void LogToServer::SendPendingEntries() { + if (iq_sender_ == NULL) { + return; + } + if (pending_entries_.empty()) { + return; + } + // Make one stanza containing all the pending entries. + scoped_ptr<XmlElement> stanza(ServerLogEntry::MakeStanza()); + while (!pending_entries_.empty()) { + ServerLogEntry& entry = pending_entries_.front(); + stanza->AddElement(entry.ToStanza().release()); + pending_entries_.pop_front(); + } + // Send the stanza to the server. + scoped_ptr<IqRequest> req = iq_sender_->SendIq( + buzz::STR_SET, directory_bot_jid_, stanza.Pass(), + IqSender::ReplyCallback()); + // We ignore any response, so let the IqRequest be destroyed. + return; +} + +void LogToServer::GenerateSessionId() { + session_id_.resize(kSessionIdLength); + for (int i = 0; i < kSessionIdLength; i++) { + const int alphabet_size = arraysize(kSessionIdAlphabet) - 1; + session_id_[i] = kSessionIdAlphabet[base::RandGenerator(alphabet_size)]; + } + session_id_generation_time_ = base::TimeTicks::Now(); +} + +void LogToServer::MaybeExpireSessionId() { + if (session_id_.empty()) { + return; + } + + base::TimeDelta max_age = base::TimeDelta::FromDays(kMaxSessionIdAgeDays); + if (base::TimeTicks::Now() - session_id_generation_time_ > max_age) { + // Log the old session ID. + scoped_ptr<ServerLogEntry> entry( + ServerLogEntry::MakeForSessionIdOld(session_id_)); + entry->AddModeField(mode_); + Log(*entry.get()); + + // Generate a new session ID. + GenerateSessionId(); + + // Log the new session ID. + entry = ServerLogEntry::MakeForSessionIdNew(session_id_); + entry->AddModeField(mode_); + Log(*entry.get()); + } +} + +} // namespace client + +} // namespace remoting diff --git a/remoting/client/log_to_server.h b/remoting/client/log_to_server.h new file mode 100644 index 0000000..35f3c96 --- /dev/null +++ b/remoting/client/log_to_server.h @@ -0,0 +1,90 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_CLIENT_LOG_TO_SERVER_H_ +#define REMOTING_CLIENT_LOG_TO_SERVER_H_ + +#include <deque> +#include <map> +#include <string> + +#include "base/threading/non_thread_safe.h" +#include "base/time/time.h" +#include "remoting/client/server_log_entry.h" +#include "remoting/jingle_glue/signal_strategy.h" +#include "remoting/protocol/connection_to_host.h" +#include "remoting/protocol/errors.h" + +namespace buzz { +class XmlElement; +} // namespace buzz + +namespace remoting { + +class ChromotingStats; +class IqSender; + +// Temporary namespace to prevent conflict with the same-named class in +// remoting/host when linking unittests. +// +// TODO(lambroslambrou): Remove this and factor out any shared code. +namespace client { + +// LogToServer sends log entries to a server. +// The contents of the log entries are described in server_log_entry.cc. +// They do not contain any personally identifiable information. +class LogToServer : public base::NonThreadSafe, + public SignalStrategy::Listener { + public: + LogToServer(ServerLogEntry::Mode mode, + SignalStrategy* signal_strategy, + const std::string& directory_bot_jid); + virtual ~LogToServer(); + + // Logs a session state change. + void LogSessionStateChange(protocol::ConnectionToHost::State state, + protocol::ErrorCode error); + void LogStatistics(remoting::ChromotingStats* statistics); + + // SignalStrategy::Listener interface. + virtual void OnSignalStrategyStateChange( + SignalStrategy::State state) OVERRIDE; + virtual bool OnSignalStrategyIncomingStanza( + const buzz::XmlElement* stanza) OVERRIDE; + + private: + void Log(const ServerLogEntry& entry); + void SendPendingEntries(); + + // Generates a new random session ID. + void GenerateSessionId(); + + // Expire the session ID if the maximum duration has been exceeded. + void MaybeExpireSessionId(); + + ServerLogEntry::Mode mode_; + SignalStrategy* signal_strategy_; + scoped_ptr<IqSender> iq_sender_; + std::string directory_bot_jid_; + + std::deque<ServerLogEntry> pending_entries_; + + // A randomly generated session ID to be attached to log messages. This + // is regenerated at the start of a new session. + std::string session_id_; + + // Start time of the session. + base::TimeTicks session_start_time_; + + // Time when the session ID was generated. + base::TimeTicks session_id_generation_time_; + + DISALLOW_COPY_AND_ASSIGN(LogToServer); +}; + +} // namespace client + +} // namespace remoting + +#endif // REMOTING_CLIENT_LOG_TO_SERVER_H_ diff --git a/remoting/client/server_log_entry.cc b/remoting/client/server_log_entry.cc new file mode 100644 index 0000000..cd580d8 --- /dev/null +++ b/remoting/client/server_log_entry.cc @@ -0,0 +1,238 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/client/server_log_entry.h" + +#include "base/logging.h" +#include "base/macros.h" +#include "base/rand_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/stringize_macros.h" +#include "base/strings/stringprintf.h" +#include "base/sys_info.h" +#include "remoting/base/constants.h" +#include "remoting/client/chromoting_stats.h" +#include "remoting/protocol/connection_to_host.h" +#include "remoting/protocol/errors.h" +#include "third_party/libjingle/source/talk/xmllite/xmlelement.h" + +using base::StringPrintf; +using base::SysInfo; +using buzz::QName; +using buzz::XmlElement; +using remoting::protocol::ConnectionToHost; + +namespace remoting { + +namespace client { + +namespace { +const char kLogCommand[] = "log"; + +const char kLogEntry[] = "entry"; + +const char kKeyEventName[] = "event-name"; +const char kValueEventNameSessionState[] = "session-state"; +const char kValueEventNameStatistics[] = "connection-statistics"; +const char kValueEventNameSessionIdOld[] = "session-id-old"; +const char kValueEventNameSessionIdNew[] = "session-id-new"; + +const char kKeyRole[] = "role"; +const char kValueRoleClient[] = "client"; + +const char kKeyMode[] = "mode"; +const char kValueModeIt2Me[] = "it2me"; +const char kValueModeMe2Me[] = "me2me"; + +const char kKeySessionState[] = "session-state"; +const char kValueSessionStateConnected[] = "connected"; +const char kValueSessionStateClosed[] = "closed"; + +const char kKeyOsName[] = "os-name"; +const char kKeyOsVersion[] = "os-version"; +const char kKeyAppVersion[] = "app-version"; + +const char kKeyCpu[] = "cpu"; + +} // namespace + +ServerLogEntry::ServerLogEntry() { +} + +ServerLogEntry::~ServerLogEntry() { +} + +// static +scoped_ptr<buzz::XmlElement> ServerLogEntry::MakeStanza() { + return scoped_ptr<buzz::XmlElement>( + new XmlElement(QName(kChromotingXmlNamespace, kLogCommand))); +} + +// static +scoped_ptr<ServerLogEntry> ServerLogEntry::MakeForSessionStateChange( + protocol::ConnectionToHost::State state, + protocol::ErrorCode error) { + scoped_ptr<ServerLogEntry> entry(new ServerLogEntry()); + entry->Set(kKeyRole, kValueRoleClient); + entry->Set(kKeyEventName, kValueEventNameSessionState); + + entry->Set(kKeySessionState, GetValueSessionState(state)); + if (error != protocol::OK) { + entry->Set("connection-error", GetValueError(error)); + } + + return entry.Pass(); +} + +// static +scoped_ptr<ServerLogEntry> ServerLogEntry::MakeForStatistics( + ChromotingStats* statistics) { + scoped_ptr<ServerLogEntry> entry(new ServerLogEntry()); + entry->Set(kKeyRole, kValueRoleClient); + entry->Set(kKeyEventName, kValueEventNameStatistics); + + entry->Set("video-bandwidth", + StringPrintf("%.2f", statistics->video_bandwidth()->Rate())); + entry->Set("capture-latency", + StringPrintf("%.2f", statistics->video_capture_ms()->Average())); + entry->Set("encode-latency", + StringPrintf("%.2f", statistics->video_encode_ms()->Average())); + entry->Set("decode-latency", + StringPrintf("%.2f", statistics->video_decode_ms()->Average())); + entry->Set("render-latency", + StringPrintf("%.2f", statistics->video_frame_rate()->Rate())); + entry->Set("roundtrip-latency", + StringPrintf("%.2f", statistics->round_trip_ms()->Average())); + + return entry.Pass(); +} + +// static +scoped_ptr<ServerLogEntry> ServerLogEntry::MakeForSessionIdOld( + const std::string& session_id) { + scoped_ptr<ServerLogEntry> entry(new ServerLogEntry()); + entry->Set(kKeyRole, kValueRoleClient); + entry->Set(kKeyEventName, kValueEventNameSessionIdOld); + entry->AddSessionId(session_id); + return entry.Pass(); +} + +// static +scoped_ptr<ServerLogEntry> ServerLogEntry::MakeForSessionIdNew( + const std::string& session_id) { + scoped_ptr<ServerLogEntry> entry(new ServerLogEntry()); + entry->Set(kKeyRole, kValueRoleClient); + entry->Set(kKeyEventName, kValueEventNameSessionIdNew); + entry->AddSessionId(session_id); + return entry.Pass(); +} + +void ServerLogEntry::AddClientFields() { + Set(kKeyOsName, SysInfo::OperatingSystemName()); + Set(kKeyOsVersion, SysInfo::OperatingSystemVersion()); + Set(kKeyAppVersion, STRINGIZE(VERSION)); + Set(kKeyCpu, SysInfo::OperatingSystemArchitecture()); +}; + +void ServerLogEntry::AddModeField(ServerLogEntry::Mode mode) { + Set(kKeyMode, GetValueMode(mode)); +} + +void ServerLogEntry::AddSessionId(const std::string& session_id) { + Set("session-id", session_id); +} + +void ServerLogEntry::AddSessionDuration(base::TimeDelta duration) { + Set("session-duration", base::Int64ToString(duration.InSeconds())); +} + +// static +const char* ServerLogEntry::GetValueMode(ServerLogEntry::Mode mode) { + switch (mode) { + case IT2ME: + return kValueModeIt2Me; + case ME2ME: + return kValueModeMe2Me; + default: + NOTREACHED(); + return NULL; + } +} + +scoped_ptr<XmlElement> ServerLogEntry::ToStanza() const { + scoped_ptr<XmlElement> stanza(new XmlElement(QName( + kChromotingXmlNamespace, kLogEntry))); + ValuesMap::const_iterator iter; + for (iter = values_map_.begin(); iter != values_map_.end(); ++iter) { + stanza->AddAttr(QName(std::string(), iter->first), iter->second); + } + return stanza.Pass(); +} + +// static +const char* ServerLogEntry::GetValueSessionState( + ConnectionToHost::State state) { + switch (state) { + // Where possible, these are the same strings that the webapp sends for the + // corresponding state - see remoting/webapp/server_log_entry.js. + case ConnectionToHost::INITIALIZING: + return "initializing"; + case ConnectionToHost::CONNECTING: + return "connecting"; + case ConnectionToHost::AUTHENTICATED: + return "authenticated"; + case ConnectionToHost::CONNECTED: + return kValueSessionStateConnected; + case ConnectionToHost::FAILED: + return "connection-failed"; + case ConnectionToHost::CLOSED: + return kValueSessionStateClosed; + default: + NOTREACHED(); + return NULL; + } +} + +// static +const char* ServerLogEntry::GetValueError(protocol::ErrorCode error) { + switch (error) { + // Where possible, these are the same strings that the webapp sends for the + // corresponding error - see remoting/webapp/server_log_entry.js. + case protocol::OK: + return "none"; + case protocol::PEER_IS_OFFLINE: + return "host-is-offline"; + case protocol::SESSION_REJECTED: + return "session-rejected"; + case protocol::INCOMPATIBLE_PROTOCOL: + return "incompatible-protocol"; + case protocol::AUTHENTICATION_FAILED: + return "authentication-failed"; + case protocol::CHANNEL_CONNECTION_ERROR: + return "channel-connection-error"; + case protocol::SIGNALING_ERROR: + return "signaling-error"; + case protocol::SIGNALING_TIMEOUT: + return "signaling-timeout"; + case protocol::HOST_OVERLOAD: + return "host-overload"; + case protocol::UNKNOWN_ERROR: + return "unknown-error"; + default: + NOTREACHED(); + return NULL; + } +} + +void ServerLogEntry::AddEventName(const std::string& event_name) { + Set("event-name", event_name); +} + +void ServerLogEntry::Set(const std::string& key, const std::string& value) { + values_map_[key] = value; +} + +} // namespace client + +} // namespace remoting diff --git a/remoting/client/server_log_entry.h b/remoting/client/server_log_entry.h new file mode 100644 index 0000000..9f861d2 --- /dev/null +++ b/remoting/client/server_log_entry.h @@ -0,0 +1,93 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_CLIENT_SERVER_LOG_ENTRY_H_ +#define REMOTING_CLIENT_SERVER_LOG_ENTRY_H_ + +#include <map> +#include <string> + +#include "base/memory/scoped_ptr.h" +#include "base/time/time.h" +#include "remoting/protocol/connection_to_host.h" +#include "remoting/protocol/errors.h" + +namespace buzz { +class XmlElement; +} // namespace buzz + +namespace remoting { + +class ChromotingStats; + +// Temporary namespace to prevent conflict with the same-named class in +// remoting/host when linking unittests. +// +// TODO(lambroslambrou): Remove this and factor out any shared code. +namespace client { + +class ServerLogEntry { + public: + // The mode of a connection. + enum Mode { + IT2ME, + ME2ME + }; + + // Constructs a log stanza. The caller should add one or more log entry + // stanzas as children of this stanza, before sending the log stanza to + // the remoting bot. + static scoped_ptr<buzz::XmlElement> MakeStanza(); + + // Constructs a log entry for a session state change. + static scoped_ptr<ServerLogEntry> MakeForSessionStateChange( + remoting::protocol::ConnectionToHost::State state, + remoting::protocol::ErrorCode error); + + // Constructs a log entry for reporting statistics. + static scoped_ptr<ServerLogEntry> MakeForStatistics( + remoting::ChromotingStats* statistics); + + // Constructs a log entry for reporting session ID is old. + static scoped_ptr<ServerLogEntry> MakeForSessionIdOld( + const std::string& session_id); + + // Constructs a log entry for reporting session ID is old. + static scoped_ptr<ServerLogEntry> MakeForSessionIdNew( + const std::string& session_id); + + ~ServerLogEntry(); + + // Adds fields describing the client to this log entry. + void AddClientFields(); + + // Adds a field describing the mode of a connection to this log entry. + void AddModeField(Mode mode); + + void AddEventName(const std::string& event_name); + void AddSessionId(const std::string& session_id); + void AddSessionDuration(base::TimeDelta duration); + + // Converts this object to an XML stanza. + scoped_ptr<buzz::XmlElement> ToStanza() const; + + private: + typedef std::map<std::string, std::string> ValuesMap; + + ServerLogEntry(); + void Set(const std::string& key, const std::string& value); + + static const char* GetValueSessionState( + remoting::protocol::ConnectionToHost::State state); + static const char* GetValueError(remoting::protocol::ErrorCode error); + static const char* GetValueMode(Mode mode); + + ValuesMap values_map_; +}; + +} // namespace client + +} // namespace remoting + +#endif // REMOTING_CLIENT_SERVER_LOG_ENTRY_H_ diff --git a/remoting/remoting_client.gypi b/remoting/remoting_client.gypi index d05130e..e9d5b32d 100644 --- a/remoting/remoting_client.gypi +++ b/remoting/remoting_client.gypi @@ -38,6 +38,9 @@ 'target_name': 'remoting_client', 'type': 'static_library', 'variables': { 'enable_wexit_time_destructors': 1, }, + 'defines': [ + 'VERSION=<(version_full)', + ], 'dependencies': [ 'remoting_base', 'remoting_protocol', diff --git a/remoting/remoting_srcs.gypi b/remoting/remoting_srcs.gypi index f694c8d..d9d663e 100644 --- a/remoting/remoting_srcs.gypi +++ b/remoting/remoting_srcs.gypi @@ -210,6 +210,10 @@ 'client/frame_producer.h', 'client/key_event_mapper.cc', 'client/key_event_mapper.h', + 'client/log_to_server.cc', + 'client/log_to_server.h', + 'client/server_log_entry.cc', + 'client/server_log_entry.h', 'client/software_video_renderer.cc', 'client/software_video_renderer.h', 'client/video_renderer.h', |