diff options
Diffstat (limited to 'cmds/statsd/src/StatsLogProcessor.cpp')
-rw-r--r-- | cmds/statsd/src/StatsLogProcessor.cpp | 123 |
1 files changed, 68 insertions, 55 deletions
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index df84b6a4dc34..a9f5208ef812 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -77,7 +77,6 @@ const int FIELD_ID_TIME_TO_LIVE_NANOS = 2; #define NS_PER_HOUR 3600 * NS_PER_SEC -#define STATS_DATA_DIR "/data/misc/stats-data" #define STATS_ACTIVE_METRIC_DIR "/data/misc/stats-active-metric" // Cool down period for writing data to disk to avoid overwriting files. @@ -106,6 +105,19 @@ StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap, StatsLogProcessor::~StatsLogProcessor() { } +static void flushProtoToBuffer(ProtoOutputStream& proto, vector<uint8_t>* outData) { + outData->clear(); + outData->resize(proto.size()); + size_t pos = 0; + sp<android::util::ProtoReader> reader = proto.data(); + while (reader->readBuffer() != NULL) { + size_t toRead = reader->currentToRead(); + std::memcpy(&((*outData)[pos]), reader->readBuffer(), toRead); + pos += toRead; + reader->move(toRead); + } +} + void StatsLogProcessor::onAnomalyAlarmFired( const int64_t& timestampNs, unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet) { @@ -366,25 +378,29 @@ void StatsLogProcessor::onDumpReport(const ConfigKey& key, const int64_t dumpTim proto->end(configKeyToken); // End of ConfigKey. + bool keepFile = false; + auto it = mMetricsManagers.find(key); + if (it != mMetricsManagers.end() && it->second->shouldPersistLocalHistory()) { + keepFile = true; + } + // Then, check stats-data directory to see there's any file containing // ConfigMetricsReport from previous shutdowns to concatenate to reports. - StorageManager::appendConfigMetricsReport(key, proto, erase_data); + StorageManager::appendConfigMetricsReport( + key, proto, erase_data && !keepFile /* should remove file after appending it */, + dumpReportReason == ADB_DUMP /*if caller is adb*/); - auto it = mMetricsManagers.find(key); if (it != mMetricsManagers.end()) { // This allows another broadcast to be sent within the rate-limit period if we get close to // filling the buffer again soon. mLastBroadcastTimes.erase(key); - // Start of ConfigMetricsReport (reports). - uint64_t reportsToken = - proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS); - onConfigMetricsReportLocked(key, dumpTimeStampNs, - include_current_partial_bucket, - erase_data, dumpReportReason, - dumpLatency, proto); - proto->end(reportsToken); - // End of ConfigMetricsReport (reports). + vector<uint8_t> buffer; + onConfigMetricsReportLocked(key, dumpTimeStampNs, include_current_partial_bucket, + erase_data, dumpReportReason, dumpLatency, + false /* is this data going to be saved on disk */, &buffer); + proto->write(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS, + reinterpret_cast<char*>(buffer.data()), buffer.size()); } else { ALOGW("Config source %s does not exist", key.ToString().c_str()); } @@ -404,16 +420,8 @@ void StatsLogProcessor::onDumpReport(const ConfigKey& key, const int64_t dumpTim dumpReportReason, dumpLatency, &proto); if (outData != nullptr) { - outData->clear(); - outData->resize(proto.size()); - size_t pos = 0; - sp<android::util::ProtoReader> reader = proto.data(); - while (reader->readBuffer() != NULL) { - size_t toRead = reader->currentToRead(); - std::memcpy(&((*outData)[pos]), reader->readBuffer(), toRead); - pos += toRead; - reader->move(toRead); - } + flushProtoToBuffer(proto, outData); + VLOG("output data size %zu", outData->size()); } StatsdStats::getInstance().noteMetricsReportSent(key, proto.size()); @@ -422,13 +430,11 @@ void StatsLogProcessor::onDumpReport(const ConfigKey& key, const int64_t dumpTim /* * onConfigMetricsReportLocked dumps serialized ConfigMetricsReport into outData. */ -void StatsLogProcessor::onConfigMetricsReportLocked(const ConfigKey& key, - const int64_t dumpTimeStampNs, - const bool include_current_partial_bucket, - const bool erase_data, - const DumpReportReason dumpReportReason, - const DumpLatency dumpLatency, - ProtoOutputStream* proto) { +void StatsLogProcessor::onConfigMetricsReportLocked( + const ConfigKey& key, const int64_t dumpTimeStampNs, + const bool include_current_partial_bucket, const bool erase_data, + const DumpReportReason dumpReportReason, const DumpLatency dumpLatency, + const bool dataSavedOnDisk, vector<uint8_t>* buffer) { // We already checked whether key exists in mMetricsManagers in // WriteDataToDisk. auto it = mMetricsManagers.find(key); @@ -440,35 +446,46 @@ void StatsLogProcessor::onConfigMetricsReportLocked(const ConfigKey& key, std::set<string> str_set; + ProtoOutputStream tempProto; // First, fill in ConfigMetricsReport using current data on memory, which // starts from filling in StatsLogReport's. - it->second->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, - erase_data, dumpLatency, &str_set, proto); + it->second->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, erase_data, + dumpLatency, &str_set, &tempProto); // Fill in UidMap if there is at least one metric to report. // This skips the uid map if it's an empty config. if (it->second->getNumMetrics() > 0) { - uint64_t uidMapToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP); + uint64_t uidMapToken = tempProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP); mUidMap->appendUidMap( dumpTimeStampNs, key, it->second->hashStringInReport() ? &str_set : nullptr, - it->second->versionStringsInReport(), it->second->installerInReport(), proto); - proto->end(uidMapToken); + it->second->versionStringsInReport(), it->second->installerInReport(), &tempProto); + tempProto.end(uidMapToken); } // Fill in the timestamps. - proto->write(FIELD_TYPE_INT64 | FIELD_ID_LAST_REPORT_ELAPSED_NANOS, - (long long)lastReportTimeNs); - proto->write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_ELAPSED_NANOS, - (long long)dumpTimeStampNs); - proto->write(FIELD_TYPE_INT64 | FIELD_ID_LAST_REPORT_WALL_CLOCK_NANOS, - (long long)lastReportWallClockNs); - proto->write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS, - (long long)getWallClockNs()); + tempProto.write(FIELD_TYPE_INT64 | FIELD_ID_LAST_REPORT_ELAPSED_NANOS, + (long long)lastReportTimeNs); + tempProto.write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_ELAPSED_NANOS, + (long long)dumpTimeStampNs); + tempProto.write(FIELD_TYPE_INT64 | FIELD_ID_LAST_REPORT_WALL_CLOCK_NANOS, + (long long)lastReportWallClockNs); + tempProto.write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS, + (long long)getWallClockNs()); // Dump report reason - proto->write(FIELD_TYPE_INT32 | FIELD_ID_DUMP_REPORT_REASON, dumpReportReason); + tempProto.write(FIELD_TYPE_INT32 | FIELD_ID_DUMP_REPORT_REASON, dumpReportReason); for (const auto& str : str_set) { - proto->write(FIELD_TYPE_STRING | FIELD_COUNT_REPEATED | FIELD_ID_STRINGS, str); + tempProto.write(FIELD_TYPE_STRING | FIELD_COUNT_REPEATED | FIELD_ID_STRINGS, str); + } + + flushProtoToBuffer(tempProto, buffer); + + // save buffer to disk if needed + if (erase_data && !dataSavedOnDisk && it->second->shouldPersistLocalHistory()) { + VLOG("save history to disk"); + string file_name = StorageManager::getDataHistoryFileName((long)getWallClockSec(), + key.GetUid(), key.GetId()); + StorageManager::writeFile(file_name.c_str(), buffer->data(), buffer->size()); } } @@ -584,18 +601,14 @@ void StatsLogProcessor::WriteDataToDiskLocked(const ConfigKey& key, !mMetricsManagers.find(key)->second->shouldWriteToDisk()) { return; } - ProtoOutputStream proto; + vector<uint8_t> buffer; onConfigMetricsReportLocked(key, timestampNs, true /* include_current_partial_bucket*/, - true /* erase_data */, dumpReportReason, dumpLatency, &proto); - string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_DATA_DIR, - (long)getWallClockSec(), key.GetUid(), (long long)key.GetId()); - android::base::unique_fd fd(open(file_name.c_str(), - O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR)); - if (fd == -1) { - ALOGE("Attempt to write %s but failed", file_name.c_str()); - return; - } - proto.flush(fd.get()); + true /* erase_data */, dumpReportReason, dumpLatency, true, + &buffer); + string file_name = + StorageManager::getDataFileName((long)getWallClockSec(), key.GetUid(), key.GetId()); + StorageManager::writeFile(file_name.c_str(), buffer.data(), buffer.size()); + // We were able to write the ConfigMetricsReport to disk, so we should trigger collection ASAP. mOnDiskDataConfigs.insert(key); } |