Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 65b01468 authored by Darin Petkov's avatar Darin Petkov
Browse files

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
parents
Loading
Loading
Loading
Loading

metrics/Makefile

0 → 100644
+91 −0
Original line number Diff line number Diff line
# 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.
#
# Makefile for metrics utilities -- library, client and daemon
#

CCONFIG = $(shell $(PKG_CONFIG) --cflags dbus-1 glib-2.0 dbus-glib-1)
LDCONFIG = $(shell $(PKG_CONFIG) --libs dbus-1 glib-2.0 gthread-2.0 dbus-glib-1)

CFLAGS = -Wall -Werror -I/usr/include -fpic -O2 $(CCONFIG)
CXXFLAGS = $(CFLAGS) -fno-exceptions

CLIENT = metrics_client
DAEMON = metrics_daemon
TESTDAEMON = test_daemon
LIB = libmetrics.a
SHAREDLIB = libmetrics.so

CLIENT_OBJS = \
	metrics_client.o
LIB_OBJS = \
	metrics_library.o
DAEMON_OBJS = \
	marshal_void__string_boxed.o \
	metrics_daemon.o \
	metrics_daemon_main.o
TESTDAEMON_OBJS = \
	marshal_void__string_boxed.o \
	metrics_daemon.o \
	metrics_daemon_unittest.o

DAEMON_LDFLAGS = $(LDCONFIG) -lrt -lbase -lpthread -lgflags
TESTDAEMON_LIBS = -lgtest

all: $(LIB) $(SHAREDLIB) $(CLIENT) $(DAEMON) $(TESTDAEMON)

$(CLIENT): $(CLIENT_OBJS) $(SHAREDLIB)
	$(CXX) $(LDFLAGS) $^ -o $@

$(DAEMON): $(DAEMON_OBJS) $(SHAREDLIB)
	$(CXX) -o $@ $^ $(DAEMON_LDFLAGS)

$(TESTDAEMON): $(TESTDAEMON_OBJS) $(SHAREDLIB)
	$(CXX) -o $@ $^ $(DAEMON_LDFLAGS) $(TESTDAEMON_LIBS)

$(LIB): $(LIB_OBJS)
	ar rcs $@ $^

$(SHAREDLIB): $(LIB_OBJS)
	$(CXX) $(LDFLAGS) -shared $^ -o $@

%.o: %.cc
	$(CXX) $(CXXFLAGS) -c $< -o $@

%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

%.c: %.list
	glib-genmarshal --body --prefix=marshal $< > $@

%.h: %.list
	glib-genmarshal --header --prefix=marshal $< > $@

# dependencies in addition to those defined by the rules

metrics_daemon.o: \
	marshal_void__string_boxed.h \
	metrics_daemon.h \
	network_states.h
metrics_daemon_unittest.o: \
	marshal_void__string_boxed.h \
	metrics_daemon.h \
	network_states.h
marshal_void__string_boxed.o: \
	marshal_void__string_boxed.h

.PRECIOUS: marshal_void__string_boxed.c  # keep around for debugging

install:
	install $(CLIENT) $(DESTDIR)/usr/bin
	install $(DAEMON) $(DESTDIR)/usr/bin
	install $(LIB) $(DESTDIR)/usr/lib
	install $(SHAREDLIB) $(DESTDIR)/usr/lib
	install metrics_library.h $(DESTDIR)/usr/include
	install syslog_parser.sh $(DESTDIR)/usr/bin
	install omaha_tracker.sh $(DESTDIR)/usr/sbin

clean:
	rm -f $(CLIENT) $(DAEMON) $(LIB) $(SHAREDLIB) $(TESTDAEMON)
	rm -f *.o marshal_void__string_boxed.[ch]

metrics/README

0 → 100644
+8 −0
Original line number Diff line number Diff line
This packages contains all scripts and programs assoicated with metrics
collection for both Chrome's User Metrics Server and automated performance
metrics collection via Autotest. 

The package includes the metrics daemon for Chrome OS.  This program
runs as a daemon and collects events by polling and listening for
d-bus signals. It then adds timing (if needed) and sends the events
to Chrome for transport to the UMA server at Google.
+1 −0
Original line number Diff line number Diff line
VOID:STRING,BOXED
+73 −0
Original line number Diff line number Diff line
// 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 <errno.h>
#include <sys/file.h>
#include <string.h>
#include <stdio.h>

#include <cstdlib>
#include <iostream>

#include "metrics_library.h"

using namespace std;

// Usage:  metrics_client [-ab] metric_name metric_value
int main(int argc, char** argv) {
  bool send_to_autotest = false;
  bool send_to_chrome = true;
  int metric_name_index = 1;
  int metric_value_index = 2;
  bool print_usage = false;

  if (argc >= 3) {
    // Parse arguments
    int flag;
    while ((flag = getopt(argc, argv, "ab")) != -1) {
      switch (flag) {
        case 'a':
          send_to_autotest = true;
          send_to_chrome = false;
          break;
        case 'b':
          send_to_chrome = true;
          send_to_autotest = true;
          break;
        default:
          print_usage = true;
          break;
      }
    }
    metric_name_index = optind;
    metric_value_index = optind + 1;
  } else {
    print_usage = true;
  }

  // Metrics value should be the last argument passed
  if ((metric_value_index + 1) != argc) {
    print_usage = true;
  }

  if (print_usage) {
    cerr << "Usage:  metrics_client [-ab] name value" << endl;
    cerr << endl;
    cerr << "  default: send metric to chrome only" << endl;
    cerr << "  -a: send metric to autotest only" << endl;
    cerr << "  -b: send metric to both chrome and autotest" << endl;
    return 1;
  }

  // Send metrics
  if (send_to_autotest) {
    MetricsLibrary::SendToAutotest(argv[metric_name_index],
                                   argv[metric_value_index]);
  }
  if (send_to_chrome) {
    MetricsLibrary::SendToChrome(argv[metric_name_index],
                                 argv[metric_value_index]);
  }
  return 0;
}
+144 −0
Original line number Diff line number Diff line
// 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;
}