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

Commit 729093df authored by Yao Chen's avatar Yao Chen
Browse files

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
parent c35ca6de
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ statsd_common_src := \
    src/condition/CombinationConditionTracker.cpp \
    src/condition/condition_util.cpp \
    src/condition/SimpleConditionTracker.cpp \
    src/condition/ConditionWizard.cpp \
    src/config/ConfigKey.cpp \
    src/config/ConfigListener.cpp \
    src/config/ConfigManager.cpp \
@@ -37,6 +38,7 @@ statsd_common_src := \
    src/matchers/SimpleLogMatchingTracker.cpp \
    src/metrics/CountAnomalyTracker.cpp \
    src/metrics/CountMetricProducer.cpp \
    src/metrics/DurationMetricProducer.cpp \
    src/metrics/MetricsManager.cpp \
    src/metrics/metrics_manager_util.cpp \
    src/packages/UidMap.cpp \
+10 −0
Original line number Diff line number Diff line
@@ -73,6 +73,16 @@ void StatsLogProcessor::OnConfigUpdated(const ConfigKey& key, const StatsdConfig
    }
}

vector<StatsLogReport> StatsLogProcessor::onDumpReport(const ConfigKey& key) {
    auto it = mMetricsManagers.find(key);
    if (it == mMetricsManagers.end()) {
        ALOGW("Config source %s does not exist", key.ToString().c_str());
        return vector<StatsLogReport>();
    }

    return it->second->onDumpReport();
}

void StatsLogProcessor::OnConfigRemoved(const ConfigKey& key) {
    auto it = mMetricsManagers.find(key);
    if (it != mMetricsManagers.end()) {
+4 −1
Original line number Diff line number Diff line
@@ -41,6 +41,9 @@ public:
    void OnConfigUpdated(const ConfigKey& key, const StatsdConfig& config);
    void OnConfigRemoved(const ConfigKey& key);

    // TODO: Once we have the ProtoOutputStream in c++, we can just return byte array.
    std::vector<StatsLogReport> onDumpReport(const ConfigKey& key);

private:
    // TODO: use EventMetrics to log the events.
    DropboxWriter m_dropbox_writer;
+56 −4
Original line number Diff line number Diff line
@@ -64,7 +64,6 @@ void CompanionDeathRecipient::binderDied(const wp<IBinder>& who) {
// ======================================================================
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_system_properties() {

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 @@ status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>&
            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 @@ status_t StatsService::cmd_config(FILE* in, FILE* out, FILE* err, Vector<String8
                        }
                    }
                } 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 @@ status_t StatsService::cmd_config(FILE* in, FILE* out, FILE* err, Vector<String8
    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;

+5 −0
Original line number Diff line number Diff line
@@ -110,6 +110,11 @@ private:
     */
    status_t cmd_print_stats_log(FILE* out, const Vector<String8>& args);

    /**
     * Print the event log.
     */
    status_t cmd_dump_report(FILE* out, FILE* err, const Vector<String8>& args);

    /**
     * Print the mapping of uids to package names.
     */
Loading