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

Commit f5acabe9 authored by Yao Chen's avatar Yao Chen
Browse files

Add StatsdStats in statsd's dumpsys

Bug: 72123656
Test: manual + statsd_test

Change-Id: I8ad9bb3abfa94ee099aa5fc3f28ad9b6fb7340f7
parent af7b167f
Loading
Loading
Loading
Loading
+3 −9
Original line number Diff line number Diff line
@@ -185,6 +185,7 @@ status_t StatsService::dump(int fd, const Vector<String16>& args) {
 */
void StatsService::dump_impl(FILE* out) {
    mConfigManager->Dump(out);
    StatsdStats::getInstance().dumpStats(out);
}

/**
@@ -296,9 +297,8 @@ void StatsService::print_cmd_help(FILE* out) {
    fprintf(out, "  NAME          The name of the configuration\n");
    fprintf(out, "\n");
    fprintf(out, "\n");
    fprintf(out, "usage: adb shell cmd stats print-stats [reset]\n");
    fprintf(out, "usage: adb shell cmd stats print-stats\n");
    fprintf(out, "  Prints some basic stats.\n");
    fprintf(out, "  reset: 1 to reset the statsd stats. default=0.\n");
}

status_t StatsService::cmd_trigger_broadcast(FILE* out, Vector<String8>& args) {
@@ -487,14 +487,8 @@ status_t StatsService::cmd_print_stats(FILE* out, const Vector<String8>& args) {
        fprintf(out, "Config %s uses %zu bytes\n", key.ToString().c_str(),
                mProcessor->GetMetricsSize(key));
    }
    fprintf(out, "Detailed statsd stats in logcat...\n");
    StatsdStats& statsdStats = StatsdStats::getInstance();
    bool reset = false;
    if (args.size() > 1) {
        reset = strtol(args[1].string(), NULL, 10);
    }
    vector<uint8_t> output;
    statsdStats.dumpStats(&output, reset);
    statsdStats.dumpStats(out);
    return NO_ERROR;
}

+112 −62
Original line number Diff line number Diff line
@@ -357,73 +357,135 @@ void StatsdStats::addSubStatsToConfigLocked(const ConfigKey& key,
    }
}

void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) {
void StatsdStats::dumpStats(FILE* out) const {
    lock_guard<std::mutex> lock(mLock);

    if (DEBUG) {
    time_t t = mStartTimeSec;
    struct tm* tm = localtime(&t);
    char timeBuffer[80];
        strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %I:%M%p", tm);
        VLOG("=================StatsdStats dump begins====================");
        VLOG("Stats collection start second: %s", timeBuffer);
    }
    ProtoOutputStream proto;
    proto.write(FIELD_TYPE_INT32 | FIELD_ID_BEGIN_TIME, mStartTimeSec);
    proto.write(FIELD_TYPE_INT32 | FIELD_ID_END_TIME, (int32_t)time(nullptr));

    VLOG("%lu Config in icebox: ", (unsigned long)mIceBox.size());
    strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %I:%M%p\n", tm);
    fprintf(out, "Stats collection start second: %s\n", timeBuffer);
    fprintf(out, "%lu Config in icebox: \n", (unsigned long)mIceBox.size());
    for (const auto& configStats : mIceBox) {
        const int numBytes = configStats.ByteSize();
        vector<char> buffer(numBytes);
        configStats.SerializeToArray(&buffer[0], numBytes);
        proto.write(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_CONFIG_STATS, &buffer[0],
                    buffer.size());

        // surround the whole block with DEBUG, so that compiler can strip out the code
        // in production.
        if (DEBUG) {
            VLOG("*****ICEBOX*****");
            VLOG("Config {%d-%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, "
                 "#matcher=%d, #alert=%d,  #valid=%d",
        fprintf(out,
                "Config {%d-%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, "
                "#matcher=%d, #alert=%d,  valid=%d\n",
                configStats.uid(), (long long)configStats.id(), configStats.creation_time_sec(),
                configStats.deletion_time_sec(), configStats.metric_count(),
                configStats.condition_count(), configStats.matcher_count(),
                configStats.alert_count(), configStats.is_valid());

        for (const auto& broadcastTime : configStats.broadcast_sent_time_sec()) {
                VLOG("\tbroadcast time: %d", broadcastTime);
            fprintf(out, "\tbroadcast time: %d\n", broadcastTime);
        }

        for (const auto& dataDropTime : configStats.data_drop_time_sec()) {
                VLOG("\tdata drop time: %d", dataDropTime);
            fprintf(out, "\tdata drop time: %d\n", dataDropTime);
        }
    }
    }

    fprintf(out, "%lu Active Configs\n", (unsigned long)mConfigStats.size());
    for (auto& pair : mConfigStats) {
        auto& key = pair.first;
        auto& configStats = pair.second;
        if (DEBUG) {
            VLOG("********Active Configs***********");
            VLOG("Config {%d-%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, "
                 "#matcher=%d, #alert=%d,  #valid=%d",

        fprintf(out,
                "Config {%d-%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, "
                "#matcher=%d, #alert=%d,  valid=%d\n",
                configStats.uid(), (long long)configStats.id(), configStats.creation_time_sec(),
                configStats.deletion_time_sec(), configStats.metric_count(),
                configStats.condition_count(), configStats.matcher_count(),
                configStats.alert_count(), configStats.is_valid());
        for (const auto& broadcastTime : configStats.broadcast_sent_time_sec()) {
                VLOG("\tbroadcast time: %d", broadcastTime);
            fprintf(out, "\tbroadcast time: %d\n", broadcastTime);
        }

        for (const auto& dataDropTime : configStats.data_drop_time_sec()) {
                VLOG("\tdata drop time: %d", dataDropTime);
            fprintf(out, "\tdata drop time: %d\n", dataDropTime);
        }

        for (const auto& dumpTime : configStats.dump_report_time_sec()) {
                VLOG("\tdump report time: %d", dumpTime);
            fprintf(out, "\tdump report time: %d\n", dumpTime);
        }

        // Add matcher stats
        auto matcherIt = mMatcherStats.find(key);
        if (matcherIt != mMatcherStats.end()) {
            const auto& matcherStats = matcherIt->second;
            for (const auto& stats : matcherStats) {
                fprintf(out, "matcher %lld matched %d times\n", (long long)stats.first,
                        stats.second);
            }
        }
        // Add condition stats
        auto conditionIt = mConditionStats.find(key);
        if (conditionIt != mConditionStats.end()) {
            const auto& conditionStats = conditionIt->second;
            for (const auto& stats : conditionStats) {
                fprintf(out, "condition %lld max output tuple size %d\n", (long long)stats.first,
                        stats.second);
            }
        }
        // Add metrics stats
        auto metricIt = mMetricsStats.find(key);
        if (metricIt != mMetricsStats.end()) {
            const auto& conditionStats = metricIt->second;
            for (const auto& stats : conditionStats) {
                fprintf(out, "metrics %lld max output tuple size %d\n", (long long)stats.first,
                        stats.second);
            }
        }
        // Add anomaly detection alert stats
        auto alertIt = mAlertStats.find(key);
        if (alertIt != mAlertStats.end()) {
            const auto& alertStats = alertIt->second;
            for (const auto& stats : alertStats) {
                fprintf(out, "alert %lld declared %d times\n", (long long)stats.first,
                        stats.second);
            }
        }
    }
    fprintf(out, "********Pushed Atom stats***********\n");
    const size_t atomCounts = mPushedAtomStats.size();
    for (size_t i = 2; i < atomCounts; i++) {
        if (mPushedAtomStats[i] > 0) {
            fprintf(out, "Atom %lu->%d\n", (unsigned long)i, mPushedAtomStats[i]);
        }
    }

    fprintf(out, "********Pulled Atom stats***********\n");
    for (const auto& pair : mPulledAtomStats) {
        fprintf(out, "Atom %d->%ld, %ld, %ld\n", (int)pair.first, (long)pair.second.totalPull,
             (long)pair.second.totalPullFromCache, (long)pair.second.minPullIntervalSec);
    }

    if (mAnomalyAlarmRegisteredStats > 0) {
        fprintf(out, "********AnomalyAlarmStats stats***********\n");
        fprintf(out, "Anomaly alarm registrations: %d\n", mAnomalyAlarmRegisteredStats);
    }

    fprintf(out,
            "UID map stats: bytes=%d, snapshots=%d, changes=%d, snapshots lost=%d, changes "
            "lost=%d\n",
            mUidMapStats.bytes_used(), mUidMapStats.snapshots(), mUidMapStats.changes(),
            mUidMapStats.dropped_snapshots(), mUidMapStats.dropped_changes());
}

void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) {
    lock_guard<std::mutex> lock(mLock);

    ProtoOutputStream proto;
    proto.write(FIELD_TYPE_INT32 | FIELD_ID_BEGIN_TIME, mStartTimeSec);
    proto.write(FIELD_TYPE_INT32 | FIELD_ID_END_TIME, (int32_t)time(nullptr));

    for (const auto& configStats : mIceBox) {
        const int numBytes = configStats.ByteSize();
        vector<char> buffer(numBytes);
        configStats.SerializeToArray(&buffer[0], numBytes);
        proto.write(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_CONFIG_STATS, &buffer[0],
                    buffer.size());
    }

    for (auto& pair : mConfigStats) {
        auto& configStats = pair.second;
        addSubStatsToConfigLocked(pair.first, configStats);

        const int numBytes = configStats.ByteSize();
@@ -439,7 +501,6 @@ void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) {
        configStats.clear_alert_stats();
    }

    VLOG("********Pushed Atom stats***********");
    const size_t atomCounts = mPushedAtomStats.size();
    for (size_t i = 2; i < atomCounts; i++) {
        if (mPushedAtomStats[i] > 0) {
@@ -448,34 +509,24 @@ void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) {
            proto.write(FIELD_TYPE_INT32 | FIELD_ID_ATOM_STATS_TAG, (int32_t)i);
            proto.write(FIELD_TYPE_INT32 | FIELD_ID_ATOM_STATS_COUNT, mPushedAtomStats[i]);
            proto.end(token);

            VLOG("Atom %lu->%d\n", (unsigned long)i, mPushedAtomStats[i]);
        }
    }

    VLOG("********Pulled Atom stats***********");
    for (const auto& pair : mPulledAtomStats) {
        android::os::statsd::writePullerStatsToStream(pair, &proto);
        VLOG("Atom %d->%ld, %ld, %ld\n", (int) pair.first, (long) pair.second.totalPull, (long) pair.second.totalPullFromCache, (long) pair.second.minPullIntervalSec);
    }

    if (mAnomalyAlarmRegisteredStats > 0) {
        VLOG("********AnomalyAlarmStats stats***********");
        long long token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_ANOMALY_ALARM_STATS);
        proto.write(FIELD_TYPE_INT32 | FIELD_ID_ANOMALY_ALARMS_REGISTERED,
                    mAnomalyAlarmRegisteredStats);
        proto.end(token);
        VLOG("Anomaly alarm registrations: %d", mAnomalyAlarmRegisteredStats);
    }

    const int numBytes = mUidMapStats.ByteSize();
    vector<char> buffer(numBytes);
    mUidMapStats.SerializeToArray(&buffer[0], numBytes);
    proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UIDMAP_STATS, &buffer[0], buffer.size());
    VLOG("UID map stats: bytes=%d, snapshots=%d, changes=%d, snapshots lost=%d, changes "
         "lost=%d",
         mUidMapStats.bytes_used(), mUidMapStats.snapshots(), mUidMapStats.changes(),
         mUidMapStats.dropped_snapshots(), mUidMapStats.dropped_changes());

    output->clear();
    size_t bufferSize = proto.size();
@@ -495,7 +546,6 @@ void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) {
    }

    VLOG("reset=%d, returned proto size %lu", reset, (unsigned long)bufferSize);
    VLOG("=================StatsdStats dump ends====================");
}

}  // namespace statsd
+5 −0
Original line number Diff line number Diff line
@@ -189,6 +189,11 @@ public:
     */
    void dumpStats(std::vector<uint8_t>* buffer, bool reset);

    /**
     * Output statsd stats in human readable format to [out] file.
     */
    void dumpStats(FILE* out) const;

    typedef struct {
        long totalPull;
        long totalPullFromCache;