Add support for dimension, and link with condition and added DurationMetric
Now we support following metrics:
<Duration> of [app holding a wake lock], while [*this app*] is [in background] [AND] [screen is off]
[Slice] the output by [app name, wake lock name], with bucket size [30sec]
+ Also added onDumpReport() api in MetricsManager, it can be called from client to fetch the data from
statsd
+ Also added command line tool to dump the StatsLogReport from all metrics for debugging.
+ Synced proto from google3. with a pending cl (cr/172359050)
TODO: We need to add tons of tests to test the Metrics. I will work on it after this CL so people
can be unblocked.
I locally test the duration metric with wake lock with an app that generates StatsLog events.
Test: statsd_test
and manual test, and run:
adb shell cmd stats dump-report
We have a default config, which contains a metrics to count PROCESS_START event sliced by
package name.
Change-Id: I4838cc6cf025c143b7e84f43040703a78121fd25
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index b72e04e..87616d3 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -64,7 +64,6 @@
// ======================================================================
StatsService::StatsService(const sp<Looper>& handlerLooper)
: mStatsPullerManager(),
-
mAnomalyMonitor(new AnomalyMonitor(2)) // TODO: Put this comment somewhere better
{
mUidMap = new UidMap();
@@ -89,7 +88,7 @@
void StatsService::init_build_type_callback(void* cookie, const char* /*name*/, const char* value,
uint32_t serial) {
- if (0 == strcmp("eng", value)) {
+ if (0 == strcmp("eng", value) || 0 == strcmp("userdebug", value)) {
reinterpret_cast<StatsService*>(cookie)->mEngBuild = true;
}
}
@@ -187,10 +186,13 @@
return cmd_print_stats_log(out, args);
}
- // adb shell cmd stats print-stats-log
if (!args[0].compare(String8("print-uid-map"))) {
return cmd_print_uid_map(out);
}
+
+ if (!args[0].compare(String8("dump-report"))) {
+ return cmd_dump_report(out, err, args);
+ }
}
print_cmd_help(out);
@@ -248,7 +250,9 @@
}
}
} else {
- fprintf(err, "The config can only be set for other UIDs on eng builds.\n");
+ fprintf(err,
+ "The config can only be set for other UIDs on eng or userdebug "
+ "builds.\n");
}
}
@@ -287,6 +291,54 @@
return UNKNOWN_ERROR;
}
+status_t StatsService::cmd_dump_report(FILE* out, FILE* err, const Vector<String8>& args) {
+ if (mProcessor != nullptr) {
+ const int argCount = args.size();
+ bool good = false;
+ int uid;
+ string name;
+ if (argCount == 2) {
+ // Automatically pick the UID
+ uid = IPCThreadState::self()->getCallingUid();
+ // TODO: What if this isn't a binder call? Should we fail?
+ name.assign(args[2].c_str(), args[2].size());
+ good = true;
+ } else if (argCount == 3) {
+ // If it's a userdebug or eng build, then the shell user can
+ // impersonate other uids.
+ if (mEngBuild) {
+ const char* s = args[1].c_str();
+ if (*s != '\0') {
+ char* end = NULL;
+ uid = strtol(s, &end, 0);
+ if (*end == '\0') {
+ name.assign(args[2].c_str(), args[2].size());
+ good = true;
+ }
+ }
+ } else {
+ fprintf(out,
+ "The metrics can only be dumped for other UIDs on eng or userdebug "
+ "builds.\n");
+ }
+ }
+ if (good) {
+ mProcessor->onDumpReport(ConfigKey(uid, name));
+ // TODO: print the returned StatsLogReport to file instead of printing to logcat.
+ fprintf(out, "Dump report for Config [%d,%s]\n", uid, name.c_str());
+ fprintf(out, "See the StatsLogReport in logcat...\n");
+ return android::OK;
+ } else {
+ // If arg parsing failed, print the help text and return an error.
+ print_cmd_help(out);
+ return UNKNOWN_ERROR;
+ }
+ } else {
+ fprintf(out, "Log processor does not exist...\n");
+ return UNKNOWN_ERROR;
+ }
+}
+
status_t StatsService::cmd_print_stats_log(FILE* out, const Vector<String8>& args) {
long msec = 0;