Loading cmds/statsd/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -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 \ Loading cmds/statsd/src/DropboxReader.cpp +20 −21 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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. Loading @@ -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; Loading @@ -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; } } Loading @@ -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"); } cmds/statsd/src/DropboxReader.h +5 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading cmds/statsd/src/DropboxWriter.cpp +14 −16 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ */ #include <android/os/DropBoxManager.h> #include <cutils/log.h> #include "DropboxWriter.h" Loading @@ -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; } cmds/statsd/src/DropboxWriter.h +6 −7 Original line number Diff line number Diff line Loading @@ -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: Loading @@ -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(); Loading @@ -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. Loading @@ -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 Loading
cmds/statsd/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -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 \ Loading
cmds/statsd/src/DropboxReader.cpp +20 −21 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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. Loading @@ -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; Loading @@ -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; } } Loading @@ -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"); }
cmds/statsd/src/DropboxReader.h +5 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading
cmds/statsd/src/DropboxWriter.cpp +14 −16 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ */ #include <android/os/DropBoxManager.h> #include <cutils/log.h> #include "DropboxWriter.h" Loading @@ -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; }
cmds/statsd/src/DropboxWriter.h +6 −7 Original line number Diff line number Diff line Loading @@ -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: Loading @@ -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(); Loading @@ -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. Loading @@ -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