Update the libmetrics API to match the new Chrome interface.

Review URL: http://codereview.chromium.org/1642018
diff --git a/metrics/metrics_client.cc b/metrics/metrics_client.cc
index 17f933c..bb67698 100644
--- a/metrics/metrics_client.cc
+++ b/metrics/metrics_client.cc
@@ -7,13 +7,11 @@
 
 #include "metrics_library.h"
 
-// Usage:  metrics_client [-ab] metric_name metric_value
 int main(int argc, char** argv) {
   bool send_to_autotest = false;
   bool send_to_chrome = true;
   bool secs_to_msecs = false;
-  int metric_name_index = 1;
-  int metric_value_index = 2;
+  int name_index = 1;
   bool print_usage = false;
 
   if (argc >= 3) {
@@ -37,43 +35,43 @@
           break;
       }
     }
-    metric_name_index = optind;
-    metric_value_index = optind + 1;
+    name_index = optind;
   } else {
     print_usage = true;
   }
 
-  // Metrics value should be the last argument passed
-  if ((metric_value_index + 1) != argc) {
+  if ((name_index + 5) != argc) {
     print_usage = true;
   }
 
   if (print_usage) {
     fprintf(stderr,
-            "Usage:  metrics_client [-abt] name value\n"
+            "Usage:  metrics_client [-abt] name sample min max nbuckets\n"
             "\n"
-            "  default: send metric with integer value to chrome only\n"
-            "  -a: send metric to autotest only\n"
+            "  default: send metric with integer values to Chrome only\n"
+            "  -a: send metric to autotest only (min/max/nbuckets ignored)\n"
             "  -b: send metric to both chrome and autotest\n"
-            "  -t: convert value from float seconds to int milliseconds\n");
+            "  -t: convert sample from double seconds to int milliseconds\n");
     return 1;
   }
 
-  const char* name = argv[metric_name_index];
-  int value;
+  const char* name = argv[name_index];
+  int sample;
   if (secs_to_msecs) {
-    float secs = strtof(argv[metric_value_index], NULL);
-    value = static_cast<int>(secs * 1000.0f);
+    sample = static_cast<int>(atof(argv[name_index + 1]) * 1000.0);
   } else {
-    value = atoi(argv[metric_value_index]);
+    sample = atoi(argv[name_index + 1]);
   }
+  int min = atoi(argv[name_index + 2]);
+  int max = atoi(argv[name_index + 3]);
+  int nbuckets = atoi(argv[name_index + 4]);
 
   // Send metrics
   if (send_to_autotest) {
-    MetricsLibrary::SendToAutotest(name, value);
+    MetricsLibrary::SendToAutotest(name, sample);
   }
   if (send_to_chrome) {
-    MetricsLibrary::SendToChrome(name, value);
+    MetricsLibrary::SendToChrome(name, sample, min, max, nbuckets);
   }
   return 0;
 }
diff --git a/metrics/metrics_daemon.cc b/metrics/metrics_daemon.cc
index 9bb9c20..9400851 100644
--- a/metrics/metrics_daemon.cc
+++ b/metrics/metrics_daemon.cc
@@ -17,7 +17,7 @@
 
 MetricsDaemon::NetworkState
 MetricsDaemon::network_states_[MetricsDaemon::kNumberNetworkStates] = {
-#define STATE(name, capname) { #name, "Connman" # capname },
+#define STATE(name, capname) { #name, "Network.Connman" # capname },
 #include "network_states.h"
 };
 
@@ -113,11 +113,11 @@
     if (diff.tv_sec >= INT_MAX / 1000) {
       diff_ms = INT_MAX;
     }
-    if (testing_) {
-      TestPublishMetric(network_states_[old_id].stat_name, diff_ms);
-    } else {
-      ChromePublishMetric(network_states_[old_id].stat_name, diff_ms);
-    }
+    PublishMetric(network_states_[old_id].stat_name,
+                  diff_ms,
+                  1,
+                  8 * 60 * 60 * 1000,  // 8 hours in milliseconds
+                  100);
   }
   network_state_id_ = new_id;
   network_state_start_ = now;
@@ -133,10 +133,12 @@
   return static_cast<NetworkStateId>(-1);
 }
 
-void MetricsDaemon::ChromePublishMetric(const char* name, int value) {
-  MetricsLibrary::SendToChrome(name, value);
-}
-
-void MetricsDaemon::TestPublishMetric(const char* name, int value) {
-  LOG(INFO) << "received metric: " << name << " " << value;
+void MetricsDaemon::PublishMetric(const char* name, int sample,
+                                  int min, int max, int nbuckets) {
+  if (testing_) {
+    LOG(INFO) << "received metric: " << name << " " << sample <<
+        " " << min << " " << max << " " << nbuckets;
+  } else {
+    MetricsLibrary::SendToChrome(name, sample, min, max, nbuckets);
+  }
 }
diff --git a/metrics/metrics_daemon.h b/metrics/metrics_daemon.h
index dc097b5..b18e366 100644
--- a/metrics/metrics_daemon.h
+++ b/metrics/metrics_daemon.h
@@ -63,11 +63,11 @@
   // Given a string with the name of a state, returns the id for the state.
   NetworkStateId GetNetworkStateId(const char* state_name);
 
-  // Sends a stat to Chrome for transport to UMA.
-  void ChromePublishMetric(const char* name, int value);
-
-  // Prints a stat for testing.
-  void TestPublishMetric(const char* name, int value);
+  // Sends a stat to Chrome for transport to UMA (or prints it for
+  // testing). See MetricsLibrary::SendToChrome in metrics_library.h
+  // for a description of the arguments.
+  void PublishMetric(const char* name, int sample,
+                     int min, int max, int nbuckets);
 
 #if 0
   // Fetches a name-value hash table from DBus.
diff --git a/metrics/metrics_library.cc b/metrics/metrics_library.cc
index f482145..681cf96 100644
--- a/metrics/metrics_library.cc
+++ b/metrics/metrics_library.cc
@@ -21,8 +21,10 @@
 #define READ_WRITE_ALL_FILE_FLAGS \
   (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
 
-static const char kAutotestPath[] = "/tmp/.chromeos-metrics-autotest";
-static const char kChromePath[] = "/tmp/.chromeos-metrics";
+static const char kAutotestPath[] =
+    "/var/log/metrics/autotest-events";
+static const char kChromePath[] =
+    "/var/log/metrics/uma-events";
 static const int32_t kBufferSize = 1024;
 
 using namespace std;
@@ -42,7 +44,7 @@
   }
 }
 
-// Sends message of size length to Chrome and returns true on success.
+// Sends message of size |length| to Chrome and returns true on success.
 static bool SendMessageToChrome(int32_t length, const char *message) {
   int chrome_fd = open(kChromePath,
                        O_WRONLY | O_APPEND | O_CREAT,
@@ -81,12 +83,12 @@
   return success;
 }
 
-// Formats a name/value message for Chrome in buffer and returns the
+// Formats a name/value message for Chrome in |buffer| and returns the
 // length of the message or a negative value on error.
 //
 // Message format is: | LENGTH(binary) | NAME | \0 | VALUE | \0 |
 //
-// The arbitrary format argument covers the non-LENGTH portion of the
+// The arbitrary |format| argument covers the non-LENGTH portion of the
 // message. The caller is responsible to store the \0 character
 // between NAME and VALUE (e.g. "%s%c%d", name, '\0', value).
 static int32_t FormatChromeMessage(int32_t buffer_size, char *buffer,
@@ -119,7 +121,8 @@
   return message_length;
 }
 
-bool MetricsLibrary::SendToAutotest(string name, int value) {
+// static
+bool MetricsLibrary::SendToAutotest(const string& name, int value) {
   FILE *autotest_file = fopen(kAutotestPath, "a+");
   if (autotest_file == NULL) {
     PrintError("fopen", kAutotestPath, errno);
@@ -131,12 +134,15 @@
   return true;
 }
 
-bool MetricsLibrary::SendToChrome(string name, int value) {
+// static
+bool MetricsLibrary::SendToChrome(const string& name, int sample,
+                                  int min, int max, int nbuckets) {
   // Format the message.
   char message[kBufferSize];
   int32_t message_length =
       FormatChromeMessage(kBufferSize, message,
-                          "%s%c%d", name.c_str(), '\0', value);
+                          "histogram%c%s %d %d %d %d", '\0',
+                          name.c_str(), sample, min, max, nbuckets);
 
   if (message_length < 0)
     return false;
diff --git a/metrics/metrics_library.h b/metrics/metrics_library.h
index ebc972c..5977e72 100644
--- a/metrics/metrics_library.h
+++ b/metrics/metrics_library.h
@@ -16,13 +16,25 @@
 
 // TODO(sosa@chromium.org): Add testing for send methods
 
-// Library used to send metrics both Autotest and Chrome
+// Library used to send metrics both Autotest and Chrome.
 class MetricsLibrary {
  public:
-  // Sends histogram data to Chrome and returns true on success.
-  static bool SendToChrome(std::string name, int value);
+  // Sends histogram data to Chrome for transport to UMA and returns
+  // true on success. This method results in the equivalent of an
+  // asynchronous non-blocking RPC to UMA_HISTOGRAM_CUSTOM_COUNTS
+  // inside Chrome (see base/histogram.h).
+  //
+  // |sample| is the sample value to be recorded (|min| <= |sample| < |max|).
+  // |min| is the minimum value of the histogram samples (|min| > 0).
+  // |max| is the maximum value of the histogram samples.
+  // |nbuckets| is the number of histogram buckets.
+  // [0,min) is the implicit underflow bucket.
+  // [|max|,infinity) is the implicit overflow bucket.
+  static bool SendToChrome(const std::string& name, int sample,
+                           int min, int max, int nbuckets);
+
   // Sends to Autotest and returns true on success.
-  static bool SendToAutotest(std::string name, int value);
+  static bool SendToAutotest(const std::string& name, int value);
 };
 
 #endif /* METRICS_LIBRARY_H_ */