Add support for user actions to the metrics library and the metrics clients.
BUG=10696
TEST=unit tests, tested on the device through metrics_client and inspecting
the uma-events file.
Change-Id: Ie39dd8b5ab968c328993076369a4ba14cb7fcd81
Review URL: http://codereview.chromium.org/6094010
diff --git a/metrics/README b/metrics/README
index 1519648..2ecec5f 100644
--- a/metrics/README
+++ b/metrics/README
@@ -29,19 +29,9 @@
<metrics/metrics_library.h> header file. The file is installed in
$SYSROOT/usr/include/ when the metrics library is built and installed.
-- The API includes two methods:
-
- bool MetricsLibrary::SendToUMA(const std::string& name, int sample,
- int min, int max, int nbuckets)
- sends a sample for a regular (exponential) histogram.
-
- bool MetricsLibrary::SendEnumToUMA(const std::string& name, int sample,
- int max)
- sends a sample for an enumeration (linear) histogram.
-
- Before using these methods, a MetricsLibrary object needs to be constructed
- and initialized through its Init method. See the complete API documentation in
- metrics_library.h under src/platform/metrics/.
+- The API is documented in metrics_library.h under src/platform/metrics/. Before
+ using the API methods, a MetricsLibrary object needs to be constructed and
+ initialized through its Init method.
For more information on the C API see c_metrics_library.h.
@@ -88,9 +78,9 @@
================================================================================
metrics_client is a simple shell command-line utility for sending histogram
-samples. It's installed under /usr/bin on the target platform and uses
-libmetrics to send the data to Chrome. The utility is useful for generating
-metrics from shell scripts.
+samples and user actions. It's installed under /usr/bin on the target platform
+and uses libmetrics to send the data to Chrome. The utility is useful for
+generating metrics from shell scripts.
For usage information and command-line options, run "metrics_client" on the
target platform or look for "Usage:" in metrics_client.cc.
diff --git a/metrics/c_metrics_library.cc b/metrics/c_metrics_library.cc
index e97f9ac..3450918 100644
--- a/metrics/c_metrics_library.cc
+++ b/metrics/c_metrics_library.cc
@@ -43,6 +43,14 @@
return lib->SendEnumToUMA(std::string(name), sample, max);
}
+extern "C" int CMetricsLibrarySendUserActionToUMA(CMetricsLibrary handle,
+ const char* action) {
+ MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
+ if (lib == NULL)
+ return 0;
+ return lib->SendUserActionToUMA(std::string(action));
+}
+
extern "C" int CMetricsLibraryAreMetricsEnabled(CMetricsLibrary handle) {
MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
if (lib == NULL)
diff --git a/metrics/c_metrics_library.h b/metrics/c_metrics_library.h
index e691ad6..9500aad 100644
--- a/metrics/c_metrics_library.h
+++ b/metrics/c_metrics_library.h
@@ -28,6 +28,10 @@
int CMetricsLibrarySendEnumToUMA(CMetricsLibrary handle,
const char* name, int sample, int max);
+// C wrapper for MetricsLibrary::SendUserActionToUMA.
+int CMetricsLibrarySendUserActionToUMA(CMetricsLibrary handle,
+ const char* action);
+
// C wrapper for MetricsLibrary::AreMetricsEnabled.
int CMetricsLibraryAreMetricsEnabled(CMetricsLibrary handle);
diff --git a/metrics/metrics_client.cc b/metrics/metrics_client.cc
index ce22e98..5aedd8b 100644
--- a/metrics/metrics_client.cc
+++ b/metrics/metrics_client.cc
@@ -11,6 +11,7 @@
fprintf(stderr,
"Usage: metrics_client [-ab] [-t] name sample min max nbuckets\n"
" metrics_client [-ab] -e name sample max\n"
+ " metrics_client -u action\n"
" metrics_client [-cg]\n"
"\n"
" default: send metric with integer values to Chrome only\n"
@@ -20,7 +21,8 @@
" -c: return exit status 0 if user consents to stats, 1 otherwise\n"
" -e: send linear/enumeration histogram data\n"
" -g: return exit status 0 if machine in guest mode, 1 otherwise\n"
- " -t: convert sample from double seconds to int milliseconds\n");
+ " -t: convert sample from double seconds to int milliseconds\n"
+ " -u: send a user action to Chrome\n");
exit(1);
}
@@ -59,6 +61,14 @@
return 0;
}
+static int SendUserAction(char* argv[], int action_index) {
+ const char* action = argv[action_index];
+ MetricsLibrary metrics_lib;
+ metrics_lib.Init();
+ metrics_lib.SendUserActionToUMA(action);
+ return 0;
+}
+
static int HasConsent() {
MetricsLibrary metrics_lib;
metrics_lib.Init();
@@ -74,6 +84,7 @@
int main(int argc, char** argv) {
enum Mode {
kModeSendStats,
+ kModeSendUserAction,
kModeHasConsent,
kModeIsGuestMode
} mode = kModeSendStats;
@@ -85,7 +96,7 @@
// Parse arguments
int flag;
- while ((flag = getopt(argc, argv, "abcegt")) != -1) {
+ while ((flag = getopt(argc, argv, "abcegtu")) != -1) {
switch (flag) {
case 'a':
mode = kModeSendStats;
@@ -109,18 +120,23 @@
case 't':
secs_to_msecs = true;
break;
+ case 'u':
+ mode = kModeSendUserAction;
+ break;
default:
print_usage = true;
break;
}
}
- int name_index = optind;
+ int arg_index = optind;
int expected_args = 0;
if (mode == kModeSendStats)
expected_args = send_enum ? 3 : 5;
+ else if (mode == kModeSendUserAction)
+ expected_args = 1;
- if ((name_index + expected_args) != argc) {
+ if ((arg_index + expected_args) != argc) {
ShowUsage();
}
@@ -130,11 +146,13 @@
ShowUsage();
}
return SendStats(argv,
- name_index,
+ arg_index,
send_enum,
secs_to_msecs,
send_to_autotest,
send_to_chrome);
+ case kModeSendUserAction:
+ return SendUserAction(argv, arg_index);
case kModeHasConsent:
return HasConsent();
case kModeIsGuestMode:
diff --git a/metrics/metrics_library.cc b/metrics/metrics_library.cc
index f720972..05e63ac 100644
--- a/metrics/metrics_library.cc
+++ b/metrics/metrics_library.cc
@@ -221,7 +221,6 @@
FormatChromeMessage(kBufferSize, message,
"histogram%c%s %d %d %d %d", '\0',
name.c_str(), sample, min, max, nbuckets);
-
if (message_length < 0)
return false;
@@ -237,7 +236,19 @@
FormatChromeMessage(kBufferSize, message,
"linearhistogram%c%s %d %d", '\0',
name.c_str(), sample, max);
+ if (message_length < 0)
+ return false;
+ // Send the message.
+ return SendMessageToChrome(message_length, message);
+}
+
+bool MetricsLibrary::SendUserActionToUMA(const std::string& action) {
+ // Format the message.
+ char message[kBufferSize];
+ int32_t message_length =
+ FormatChromeMessage(kBufferSize, message,
+ "useraction%c%s", '\0', action.c_str());
if (message_length < 0)
return false;
diff --git a/metrics/metrics_library.h b/metrics/metrics_library.h
index fb31c20..b9b817a 100644
--- a/metrics/metrics_library.h
+++ b/metrics/metrics_library.h
@@ -69,6 +69,15 @@
// normal, while 100 is high).
bool SendEnumToUMA(const std::string& name, int sample, int max);
+ // Sends a user action to Chrome for transport to UMA and returns true on
+ // success. This method results in the equivalent of an asynchronous
+ // non-blocking RPC to UserMetrics::RecordAction (see the comments in
+ // chrome/browser/chromeos/external_metrics.cc and
+ // chrome/browser/metrics/user_metrics.h on how to register new user actions).
+ //
+ // |action| is the user-generated event (e.g., "MuteKeyPressed").
+ bool SendUserActionToUMA(const std::string& action);
+
// Sends to Autotest and returns true on success.
static bool SendToAutotest(const std::string& name, int value);
diff --git a/metrics/metrics_library_test.cc b/metrics/metrics_library_test.cc
index 0cd695b..3e49f69 100644
--- a/metrics/metrics_library_test.cc
+++ b/metrics/metrics_library_test.cc
@@ -214,6 +214,23 @@
EXPECT_FALSE(file_util::PathExists(kTestUMAEventsFile));
}
+TEST_F(MetricsLibraryTest, SendUserActionToUMA) {
+ char buf[100];
+ const int kLen = 30;
+ EXPECT_TRUE(lib_.SendUserActionToUMA("SomeKeyPressed"));
+ EXPECT_EQ(kLen, file_util::ReadFile(kTestUMAEventsFile, buf, 100));
+
+ char exp[kLen];
+ sprintf(exp, "%c%c%c%cuseraction%cSomeKeyPressed", kLen, 0, 0, 0, 0);
+ EXPECT_EQ(0, memcmp(exp, buf, kLen));
+}
+
+TEST_F(MetricsLibraryTest, SendUserActionToUMANotEnabled) {
+ SetMetricsEnabled(false);
+ EXPECT_TRUE(lib_.SendUserActionToUMA("SomeOtherKeyPressed"));
+ EXPECT_FALSE(file_util::PathExists(kTestUMAEventsFile));
+}
+
class CMetricsLibraryTest : public testing::Test {
protected:
virtual void SetUp() {
@@ -268,6 +285,17 @@
EXPECT_EQ(0, memcmp(exp, buf, kLen));
}
+TEST_F(CMetricsLibraryTest, SendUserActionToUMA) {
+ char buf[100];
+ const int kLen = 30;
+ EXPECT_TRUE(CMetricsLibrarySendUserActionToUMA(lib_, "SomeKeyPressed"));
+ EXPECT_EQ(kLen, file_util::ReadFile(kTestUMAEventsFile, buf, 100));
+
+ char exp[kLen];
+ sprintf(exp, "%c%c%c%cuseraction%cSomeKeyPressed", kLen, 0, 0, 0, 0);
+ EXPECT_EQ(0, memcmp(exp, buf, kLen));
+}
+
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();