Unify metrics_collection and metrics_daemon into metrics.
Tested new binaries on the target.
Tested incremental build.
Tested arm-generic build.
Review URL: http://codereview.chromium.org/1650006
diff --git a/metrics/metrics_daemon.cc b/metrics/metrics_daemon.cc
new file mode 100644
index 0000000..a924b8a
--- /dev/null
+++ b/metrics/metrics_daemon.cc
@@ -0,0 +1,144 @@
+// Copyright (c) 2010 The Chromium OS 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 "metrics_daemon.h"
+#include "metrics_library.h"
+
+#include <glib-object.h>
+
+extern "C" {
+#include "marshal_void__string_boxed.h"
+}
+
+#include <base/logging.h>
+
+#define SAFE_MESSAGE(e) ((e && e->message) ? e->message : "unknown error")
+
+MetricsDaemon::NetworkState
+MetricsDaemon::network_states_[MetricsDaemon::kNumberNetworkStates] = {
+#define STATE(name, capname) { #name, "Connman" # capname },
+#include "network_states.h"
+};
+
+void MetricsDaemon::Run(bool run_as_daemon, bool testing) {
+ Init(testing);
+ if (!run_as_daemon || daemon(0, 0) == 0) {
+ Loop();
+ }
+}
+
+void MetricsDaemon::Init(bool testing) {
+ testing_ = testing;
+ network_state_id_ = kUnknownNetworkStateId;
+
+ ::g_thread_init(NULL);
+ ::g_type_init();
+ ::dbus_g_thread_init();
+
+ ::GError* error = NULL;
+ ::DBusGConnection* dbc = ::dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
+ // Note that LOG(FATAL) terminates the process; otherwise we'd have to worry
+ // about leaking |error|.
+ LOG_IF(FATAL, dbc == NULL) <<
+ "cannot connect to dbus: " << SAFE_MESSAGE(error);
+
+ ::DBusGProxy* net_proxy = ::dbus_g_proxy_new_for_name(
+ dbc, "org.moblin.connman", "/", "org.moblin.connman.Metrics");
+ LOG_IF(FATAL, net_proxy == NULL) << "no dbus proxy for network";
+
+#if 0
+ // Unclear how soon one can call dbus_g_type_get_map(). Doing it before the
+ // call to dbus_g_bus_get() results in a (non-fatal) assertion failure.
+ // GetProperties returns a hash table.
+ hashtable_gtype = ::dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
+ G_TYPE_VALUE);
+#endif
+
+ dbus_g_object_register_marshaller(marshal_VOID__STRING_BOXED,
+ G_TYPE_NONE,
+ G_TYPE_STRING,
+ G_TYPE_VALUE,
+ G_TYPE_INVALID);
+ ::dbus_g_proxy_add_signal(net_proxy, "ConnectionStateChanged",
+ G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID);
+ ::dbus_g_proxy_connect_signal(net_proxy, "ConnectionStateChanged",
+ G_CALLBACK(&StaticNetSignalHandler),
+ this, NULL);
+}
+
+void MetricsDaemon::Loop() {
+ ::GMainLoop* loop = ::g_main_loop_new(NULL, false);
+ ::g_main_loop_run(loop);
+}
+
+void MetricsDaemon::StaticNetSignalHandler(::DBusGProxy* proxy,
+ const char* property,
+ const ::GValue* value,
+ void *data) {
+ (static_cast<MetricsDaemon*>(data))->NetSignalHandler(proxy, property, value);
+}
+
+void MetricsDaemon::NetSignalHandler(::DBusGProxy* proxy,
+ const char* property,
+ const ::GValue* value) {
+ if (strcmp("ConnectionState", property) != 0) {
+ return;
+ }
+
+ const char* newstate = static_cast<const char*>(g_value_get_string(value));
+ LogNetworkStateChange(newstate);
+}
+
+void MetricsDaemon::LogNetworkStateChange(const char* newstate) {
+ NetworkStateId new_id = GetNetworkStateId(newstate);
+ if (new_id == kUnknownNetworkStateId) {
+ LOG(WARNING) << "unknown network connection state " << newstate;
+ return;
+ }
+ NetworkStateId old_id = network_state_id_;
+ if (new_id == old_id) { // valid new state and no change
+ return;
+ }
+ struct timeval now;
+ if (gettimeofday(&now, NULL) != 0) {
+ PLOG(WARNING) << "gettimeofday";
+ }
+ if (old_id != kUnknownNetworkStateId) {
+ struct timeval diff;
+ timersub(&now, &network_state_start_, &diff);
+ int diff_ms = diff.tv_usec / 1000 + diff.tv_sec * 1000;
+ // Saturates rather than overflowing. We expect this to be statistically
+ // insignificant, since INT_MAX milliseconds is 24.8 days.
+ if (diff.tv_sec >= INT_MAX / 1000) {
+ diff_ms = INT_MAX;
+ }
+ char buffer[100];
+ snprintf(buffer, sizeof(buffer), "%d", diff_ms);
+ if (testing_) {
+ TestPublishMetric(network_states_[old_id].stat_name, buffer);
+ } else {
+ ChromePublishMetric(network_states_[old_id].stat_name, buffer);
+ }
+ }
+ network_state_id_ = new_id;
+ network_state_start_ = now;
+}
+
+MetricsDaemon::NetworkStateId
+MetricsDaemon::GetNetworkStateId(const char* state_name) {
+ for (int i = 0; i < kNumberNetworkStates; i++) {
+ if (strcmp(state_name, network_states_[i].name) == 0) {
+ return static_cast<NetworkStateId>(i);
+ }
+ }
+ return static_cast<NetworkStateId>(-1);
+}
+
+void MetricsDaemon::ChromePublishMetric(const char* name, const char* value) {
+ MetricsLibrary::SendToChrome(name, value);
+}
+
+void MetricsDaemon::TestPublishMetric(const char* name, const char* value) {
+ LOG(INFO) << "received metric: " << name << " " << value;
+}