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

Commit 482d272d authored by Yao Chen's avatar Yao Chen
Browse files

Add a cmd line tool to StatsService to parse log files from Dropbox

Test: adb shell cmd stats all-logs
Change-Id: I7803c9c021a971619f60fbf6bdfabd33d2f476ef
parent ab273e2e
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ LOCAL_SRC_FILES := \
    src/stats_log.proto \
    src/statsd_config.proto \
    src/stats_constants.proto \
    src/DropboxReader.cpp \


LOCAL_CFLAGS += \
    -Wall \
@@ -83,6 +85,7 @@ LOCAL_SHARED_LIBRARIES := \
        libselinux \
        libutils \
        libservices \
        libandroidfw \

LOCAL_MODULE_CLASS := EXECUTABLES

+120 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <android/os/DropBoxManager.h>
#include <android-base/file.h>
#include <cutils/log.h>
#include <androidfw/ZipUtils.h>
#include <stdio.h>

#include "DropboxReader.h"

using android::sp;
using android::String16;
using android::binder::Status;
using android::base::unique_fd;
using android::os::DropBoxManager;
using android::os::statsd::StatsLogEntry;
using android::ZipUtils;
using std::vector;

status_t DropboxReader::readStatsLogs(FILE* out, const string& tag, long msec) {
    sp<DropBoxManager> dropbox = new DropBoxManager();
    StatsLogList logList;

    long timestamp = msec;
    // instead of while(true), put a hard limit 1000. Dropbox won't have more than 1000 files.
    for(int i = 0; i < 1000; i++ ) {
        DropBoxManager::Entry entry;
        Status status = dropbox->getNextEntry(String16(tag.c_str()),
                timestamp, &entry);
        if (!status.isOk()) {
            ALOGD("No more entries, or failed to read. We can't tell unfortunately.");
            return android::OK;
        }

        const unique_fd& fd = entry.getFd();

        // use this timestamp for next query.
        timestamp = entry.getTimestamp();

        if (entry.getFlags() & DropBoxManager::IS_GZIPPED) {
            if (!parseFromGzipFile(fd, logList)) {
                // Failed to parse from the file. Continue to fetch the next entry.
                continue;
            }
        } else {
            if (!parseFromFile(fd, logList)) {
                // Failed to parse from the file. Continue to fetch the next entry.
                continue;
            }
        }

        printLog(out, logList);
    }
    return android::OK;
}

bool DropboxReader::parseFromGzipFile(const unique_fd& fd, StatsLogList& list) {
    FILE *file = fdopen(fd, "r");
    bool result = false;
    bool scanResult;
    int method;
    long compressedLen;
    long uncompressedLen;
    unsigned long crc32;
    scanResult = ZipUtils::examineGzip(file, &method, &uncompressedLen,
            &compressedLen, &crc32);
    if (scanResult && method == kCompressDeflated) {
        vector<uint8_t> buf(uncompressedLen);
        if (ZipUtils::inflateToBuffer(file, &buf[0], uncompressedLen, compressedLen)) {
            if (list.ParseFromArray(&buf[0], uncompressedLen)) {
                result = true;
            }
        }
    } else {
        ALOGE("This isn't a valid deflated gzip file");
    }
    fclose(file);
    return result;
}

// parse a non zipped file.
bool DropboxReader::parseFromFile(const unique_fd& fd, StatsLogList& list) {
    string content;
    if (!android::base::ReadFdToString(fd, &content)) {
        ALOGE("Failed to read file");
        return false;
    }
    if (!list.ParseFromString(content)) {
        ALOGE("failed to parse log entry from data");
        return false;
    }
    return true;
}

void DropboxReader::printLog(FILE* out, const StatsLogList& list) {
    for (int i = 0; i < list.stats_log_entry_size(); i++) {
        const StatsLogEntry entry = list.stats_log_entry(i);
        // TODO: print pretty
        fprintf(out, "time_msec=%lld, type=%d, aggregate_type=%d, uid=%d, pid=%d ",
                entry.start_report_millis(), entry.type(), entry.aggregate_type(),
                entry.uid(), entry.pid());
        for (int j = 0; j < entry.pairs_size(); j++) {
            fprintf(out, "msg=%s ", entry.pairs(j).value_str().c_str());
        }
        fprintf(out, "\n");
    }
}
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef DROPBOX_READER_H
#define DROPBOX_READER_H

#include <frameworks/base/cmds/statsd/src/stats_log.pb.h>

#include <stdint.h>
#include <stdio.h>

using android::base::unique_fd;
using android::os::statsd::StatsLogList;
using android::status_t;
using std::string;

class DropboxReader {
public:
    // msec is the start timestamp.
    static status_t readStatsLogs(FILE* out, const string& tag, long msec);

private:
    static bool parseFromFile(const unique_fd& fd, StatsLogList& list);
    static bool parseFromGzipFile(const unique_fd& fd, StatsLogList& list);
    static void printLog(FILE* out, const StatsLogList& list);
    enum {
      kCompressStored = 0,    // no compression
      kCompressDeflated = 8,  // standard deflate
    };
};

#endif //DROPBOX_READER_H
 No newline at end of file
+22 −7
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#define LOG_TAG "statsd"

#include "StatsService.h"
#include "DropboxReader.h"

#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
@@ -27,6 +28,7 @@

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

using namespace android;

@@ -118,15 +120,13 @@ StatsService::dump(int fd, const Vector<String16>& args)
status_t
StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args)
{
    fprintf(out, "StatsService::command:");
    ALOGD("StatsService::command:");
    const int N = args.size();
    for (int i=0; i<N; i++) {
        fprintf(out, " %s", String8(args[i]).string());
        ALOGD("   %s", String8(args[i]).string());
    if (args.size() > 0) {
        if (!args[0].compare(String8("print-stats-log")) && args.size() > 1) {
            return doPrintStatsLog(out, args);
        }
    }
    fprintf(out, "\n");

    printCmdHelp(out);
    return NO_ERROR;
}

@@ -144,3 +144,18 @@ StatsService::systemRunning()
    return Status::ok();
}

status_t
StatsService::doPrintStatsLog(FILE* out, const Vector<String8>& args) {
    long msec = 0;

    if (args.size() > 2) {
        msec = strtol(args[2].string(), NULL, 10);
    }
    return DropboxReader::readStatsLogs(out, args[1].string(), msec);
}

void
StatsService::printCmdHelp(FILE* out) {
    fprintf(out, "Usage:\n");
    fprintf(out, "\t print-stats-log [tag_required] [timestamp_nsec_optional]\n");
}
+4 −0
Original line number Diff line number Diff line
@@ -45,6 +45,10 @@ public:
    virtual status_t command(FILE* in, FILE* out, FILE* err, Vector<String8>& args);

    virtual Status systemRunning();

private:
    status_t doPrintStatsLog(FILE* out, const Vector<String8>& args);
    void printCmdHelp(FILE* out);
};

#endif // STATS_SERVICE_H
Loading