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

Commit 00698daf authored by yro's avatar yro
Browse files

Translate Android log entries to stats_log proto

Test: tested on local device

Change-Id: If9a779a96d31cefaffb1e4424629c14b08e1fc57
parent 87f50c46
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ LOCAL_SRC_FILES := \
    src/LogReader.cpp \
    src/main.cpp \
    src/DropboxWriter.cpp \
    src/parse_util.cpp \
    src/StatsLogProcessor.cpp \
    src/stats_log.proto \
    src/statsd_config.proto \
+20 −21
Original line number Diff line number Diff line
@@ -15,9 +15,7 @@
 */
#include <android/os/DropBoxManager.h>
#include <android-base/file.h>
#include <cutils/log.h>
#include <androidfw/ZipUtils.h>
#include <stdio.h>

#include "DropboxReader.h"

@@ -25,14 +23,14 @@ using android::sp;
using android::String16;
using android::binder::Status;
using android::base::unique_fd;
using android::os::statsd::EventMetricData;
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;
    StatsLogReport logReport;

    long timestamp = msec;
    // instead of while(true), put a hard limit 1000. Dropbox won't have more than 1000 files.
@@ -51,23 +49,23 @@ status_t DropboxReader::readStatsLogs(FILE* out, const string& tag, long msec) {
        timestamp = entry.getTimestamp();

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

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

bool DropboxReader::parseFromGzipFile(const unique_fd& fd, StatsLogList& list) {
bool DropboxReader::parseFromGzipFile(const unique_fd& fd, StatsLogReport& logReport) {
    FILE *file = fdopen(fd, "r");
    bool result = false;
    bool scanResult;
@@ -80,7 +78,7 @@ bool DropboxReader::parseFromGzipFile(const unique_fd& fd, StatsLogList& list) {
    if (scanResult && method == kCompressDeflated) {
        vector<uint8_t> buf(uncompressedLen);
        if (ZipUtils::inflateToBuffer(file, &buf[0], uncompressedLen, compressedLen)) {
            if (list.ParseFromArray(&buf[0], uncompressedLen)) {
            if (logReport.ParseFromArray(&buf[0], uncompressedLen)) {
                result = true;
            }
        }
@@ -92,29 +90,30 @@ bool DropboxReader::parseFromGzipFile(const unique_fd& fd, StatsLogList& list) {
}

// parse a non zipped file.
bool DropboxReader::parseFromFile(const unique_fd& fd, StatsLogList& list) {
bool DropboxReader::parseFromFile(const unique_fd& fd, StatsLogReport& logReport) {
    string content;
    if (!android::base::ReadFdToString(fd, &content)) {
        ALOGE("Failed to read file");
        return false;
    }
    if (!list.ParseFromString(content)) {
    if (!logReport.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());
void DropboxReader::printLog(FILE* out, const StatsLogReport& logReport) {
    fprintf(out, "start_time_msec=%lld, end_time_msec=%lld, ",
            logReport.start_report_millis(), logReport.end_report_millis());
    for (int i = 0; i < logReport.event_metrics().data_size(); i++) {
        EventMetricData eventMetricData = logReport.event_metrics().data(i);
        for (int j = 0; j < eventMetricData.key_value_pair_size(); j++) {
            fprintf(out, "key=%d, ", eventMetricData.key_value_pair(j).key());
            fprintf(out, "value_str=%s ", eventMetricData.key_value_pair(j).value_str().c_str());
            fprintf(out, "value_int=%lld ", eventMetricData.key_value_pair(j).value_int());
            fprintf(out, "value_float=%f ", eventMetricData.key_value_pair(j).value_float());
        }
        fprintf(out, "\n");
    }
    fprintf(out, "\n");
}
+5 −5
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@
#include <stdio.h>

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

@@ -33,9 +33,9 @@ public:
    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);
    static bool parseFromFile(const unique_fd& fd, StatsLogReport& logReport);
    static bool parseFromGzipFile(const unique_fd& fd, StatsLogReport& logReport);
    static void printLog(FILE* out, const StatsLogReport& logReport);
    enum {
      kCompressStored = 0,    // no compression
      kCompressDeflated = 8,  // standard deflate
+14 −16
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
 */

#include <android/os/DropBoxManager.h>
#include <cutils/log.h>

#include "DropboxWriter.h"

@@ -26,36 +25,35 @@ using android::String16;
using std::vector;

DropboxWriter::DropboxWriter(const string& tag)
    : mTag(tag), mLogList(), mBufferSize(0) {
    : mTag(tag), mLogReport(), mBufferSize(0) {
}

void DropboxWriter::addEntry(const StatsLogEntry& entry) {
    flushIfNecessary(entry);
    StatsLogEntry* newEntry = mLogList.add_stats_log_entry();
    newEntry->CopyFrom(entry);
    mBufferSize += entry.ByteSize();
void DropboxWriter::addStatsLogReport(const StatsLogReport& log) {
    mLogReport = log;
    flushIfNecessary(log);
    mBufferSize += log.ByteSize();
}

void DropboxWriter::flushIfNecessary(const StatsLogEntry& entry) {
    // The serialized size of the StatsLogList is approximately the sum of the serialized size of
    // every StatsLogEntry inside it.
    if (entry.ByteSize() + mBufferSize > kMaxSerializedBytes) {
void DropboxWriter::flushIfNecessary(const StatsLogReport& log) {
    // TODO: Decide to flush depending on the serialized size of the StatsLogReport.
    // if (entry.ByteSize() + mBufferSize > kMaxSerializedBytes) {
    //     flush();
    // }
    flush();
}
}

void DropboxWriter::flush() {
    // now we get an exact byte size of the output
    const int numBytes = mLogList.ByteSize();
    const int numBytes = mLogReport.ByteSize();
    vector<uint8_t> buffer(numBytes);
    sp<DropBoxManager> dropbox = new DropBoxManager();
    mLogList.SerializeToArray(&buffer[0], numBytes);
    mLogReport.SerializeToArray(&buffer[0], numBytes);
    Status status = dropbox->addData(String16(mTag.c_str()), &buffer[0],
            numBytes, 0 /* no flag */);
    if (!status.isOk()) {
        ALOGE("failed to write to dropbox");
        //TODO: What to do if flush fails??
    }
    mLogList.Clear();
    mLogReport.Clear();
    mBufferSize = 0;
}
+6 −7
Original line number Diff line number Diff line
@@ -20,8 +20,7 @@
#include <frameworks/base/cmds/statsd/src/stats_log.pb.h>

using std::string;
using android::os::statsd::StatsLogEntry;
using android::os::statsd::StatsLogList;
using android::os::statsd::StatsLogReport;

class DropboxWriter {
public:
@@ -30,7 +29,7 @@ public:
     */
    DropboxWriter(const string& tag);

    void addEntry(const StatsLogEntry& entry);
    void addStatsLogReport(const StatsLogReport& log);

    /* Request a flush to dropbox. */
    void flush();
@@ -46,11 +45,11 @@ private:

    const string mTag;

    /* StatsLogList is a wrapper for storing a list of StatsLogEntry */
    StatsLogList mLogList;
    /* Data that was captured for a single metric over a given interval of time. */
    StatsLogReport mLogReport;

    /* Current *serialized* size of the logs kept in memory.
       To save computation, we will not calculate the size of the StatsLogList every time when a new
       To save computation, we will not calculate the size of the StatsLogReport every time when a new
       entry is added, which would recursively call ByteSize() on every log entry. Instead, we keep
       the sum of all individual stats log entry sizes. The size of a proto is approximately the sum
       of the size of all member protos.
@@ -59,7 +58,7 @@ private:

    /* Check if the buffer size exceeds the max buffer size when the new entry is added, and flush
       the logs to dropbox if true. */
    void flushIfNecessary(const StatsLogEntry& entry);
    void flushIfNecessary(const StatsLogReport& log);

};

Loading