Merge "Flush the partial bucket when startd shuts down or config updated." into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
9d4c397781
@@ -212,7 +212,10 @@ void StatsLogProcessor::OnConfigUpdatedLocked(
|
||||
sp<MetricsManager> newMetricsManager =
|
||||
new MetricsManager(key, config, mTimeBaseSec, (timestampNs - 1) / NS_PER_SEC + 1, mUidMap,
|
||||
mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
|
||||
|
||||
auto it = mMetricsManagers.find(key);
|
||||
if (it != mMetricsManagers.end()) {
|
||||
WriteDataToDiskLocked(it->first);
|
||||
}
|
||||
if (newMetricsManager->isConfigValid()) {
|
||||
mUidMap->OnConfigUpdated(key);
|
||||
if (newMetricsManager->shouldAddUidMapListener()) {
|
||||
@@ -251,19 +254,10 @@ void StatsLogProcessor::dumpStates(FILE* out, bool verbose) {
|
||||
* onDumpReport dumps serialized ConfigMetricsReportList into outData.
|
||||
*/
|
||||
void StatsLogProcessor::onDumpReport(const ConfigKey& key, const int64_t dumpTimeStampNs,
|
||||
const bool include_current_partial_bucket,
|
||||
vector<uint8_t>* outData) {
|
||||
std::lock_guard<std::mutex> lock(mMetricsMutex);
|
||||
|
||||
auto it = mMetricsManagers.find(key);
|
||||
if (it == mMetricsManagers.end()) {
|
||||
ALOGW("Config source %s does not exist", key.ToString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
ProtoOutputStream proto;
|
||||
|
||||
// Start of ConfigKey.
|
||||
@@ -273,18 +267,26 @@ void StatsLogProcessor::onDumpReport(const ConfigKey& key, const int64_t dumpTim
|
||||
proto.end(configKeyToken);
|
||||
// End of ConfigKey.
|
||||
|
||||
// Start of ConfigMetricsReport (reports).
|
||||
uint64_t reportsToken =
|
||||
proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS);
|
||||
onConfigMetricsReportLocked(key, dumpTimeStampNs, &proto);
|
||||
proto.end(reportsToken);
|
||||
// End of ConfigMetricsReport (reports).
|
||||
|
||||
|
||||
// Then, check stats-data directory to see there's any file containing
|
||||
// ConfigMetricsReport from previous shutdowns to concatenate to reports.
|
||||
StorageManager::appendConfigMetricsReport(key, &proto);
|
||||
|
||||
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, &proto);
|
||||
proto.end(reportsToken);
|
||||
// End of ConfigMetricsReport (reports).
|
||||
} else {
|
||||
ALOGW("Config source %s does not exist", key.ToString().c_str());
|
||||
}
|
||||
|
||||
if (outData != nullptr) {
|
||||
outData->clear();
|
||||
outData->resize(proto.size());
|
||||
@@ -298,7 +300,7 @@ void StatsLogProcessor::onDumpReport(const ConfigKey& key, const int64_t dumpTim
|
||||
}
|
||||
}
|
||||
|
||||
StatsdStats::getInstance().noteMetricsReportSent(key);
|
||||
StatsdStats::getInstance().noteMetricsReportSent(key, proto.size());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -306,16 +308,20 @@ void StatsLogProcessor::onDumpReport(const ConfigKey& key, const int64_t dumpTim
|
||||
*/
|
||||
void StatsLogProcessor::onConfigMetricsReportLocked(const ConfigKey& key,
|
||||
const int64_t dumpTimeStampNs,
|
||||
const bool include_current_partial_bucket,
|
||||
ProtoOutputStream* proto) {
|
||||
// We already checked whether key exists in mMetricsManagers in
|
||||
// WriteDataToDisk.
|
||||
auto it = mMetricsManagers.find(key);
|
||||
if (it == mMetricsManagers.end()) {
|
||||
return;
|
||||
}
|
||||
int64_t lastReportTimeNs = it->second->getLastReportTimeNs();
|
||||
int64_t lastReportWallClockNs = it->second->getLastReportWallClockNs();
|
||||
|
||||
// First, fill in ConfigMetricsReport using current data on memory, which
|
||||
// starts from filling in StatsLogReport's.
|
||||
it->second->onDumpReport(dumpTimeStampNs, proto);
|
||||
it->second->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, proto);
|
||||
|
||||
// Fill in UidMap.
|
||||
uint64_t uidMapToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP);
|
||||
@@ -331,7 +337,6 @@ void StatsLogProcessor::onConfigMetricsReportLocked(const ConfigKey& key,
|
||||
(long long)lastReportWallClockNs);
|
||||
proto->write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS,
|
||||
(long long)getWallClockNs());
|
||||
|
||||
}
|
||||
|
||||
void StatsLogProcessor::resetIfConfigTtlExpiredLocked(const int64_t timestampNs) {
|
||||
@@ -361,6 +366,7 @@ void StatsLogProcessor::OnConfigRemoved(const ConfigKey& key) {
|
||||
std::lock_guard<std::mutex> lock(mMetricsMutex);
|
||||
auto it = mMetricsManagers.find(key);
|
||||
if (it != mMetricsManagers.end()) {
|
||||
WriteDataToDiskLocked(key);
|
||||
mMetricsManagers.erase(it);
|
||||
mUidMap->OnConfigRemoved(key);
|
||||
}
|
||||
@@ -406,22 +412,30 @@ void StatsLogProcessor::flushIfNecessaryLocked(
|
||||
}
|
||||
}
|
||||
|
||||
void StatsLogProcessor::WriteDataToDiskLocked(const ConfigKey& key) {
|
||||
ProtoOutputStream proto;
|
||||
onConfigMetricsReportLocked(key, getElapsedRealtimeNs(),
|
||||
true /* include_current_partial_bucket*/, &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());
|
||||
}
|
||||
|
||||
void StatsLogProcessor::WriteDataToDiskLocked() {
|
||||
for (auto& pair : mMetricsManagers) {
|
||||
WriteDataToDiskLocked(pair.first);
|
||||
}
|
||||
}
|
||||
|
||||
void StatsLogProcessor::WriteDataToDisk() {
|
||||
std::lock_guard<std::mutex> lock(mMetricsMutex);
|
||||
for (auto& pair : mMetricsManagers) {
|
||||
const ConfigKey& key = pair.first;
|
||||
ProtoOutputStream proto;
|
||||
onConfigMetricsReportLocked(key, getElapsedRealtimeNs(), &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) {
|
||||
VLOG("Attempt to write %s but failed", file_name.c_str());
|
||||
return;
|
||||
}
|
||||
proto.flush(fd.get());
|
||||
}
|
||||
WriteDataToDiskLocked();
|
||||
}
|
||||
|
||||
} // namespace statsd
|
||||
|
||||
@@ -48,7 +48,8 @@ public:
|
||||
|
||||
size_t GetMetricsSize(const ConfigKey& key) const;
|
||||
|
||||
void onDumpReport(const ConfigKey& key, const int64_t dumpTimeNs, vector<uint8_t>* outData);
|
||||
void onDumpReport(const ConfigKey& key, const int64_t dumpTimeNs,
|
||||
const bool include_current_partial_bucket, vector<uint8_t>* outData);
|
||||
|
||||
/* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */
|
||||
void onAnomalyAlarmFired(
|
||||
@@ -102,7 +103,11 @@ private:
|
||||
void OnConfigUpdatedLocked(
|
||||
const int64_t currentTimestampNs, const ConfigKey& key, const StatsdConfig& config);
|
||||
|
||||
void WriteDataToDiskLocked();
|
||||
void WriteDataToDiskLocked(const ConfigKey& key);
|
||||
|
||||
void onConfigMetricsReportLocked(const ConfigKey& key, const int64_t dumpTimeStampNs,
|
||||
const bool include_current_partial_bucket,
|
||||
util::ProtoOutputStream* proto);
|
||||
|
||||
/* Check if we should send a broadcast if approaching memory limits and if we're over, we
|
||||
|
||||
@@ -501,7 +501,7 @@ status_t StatsService::cmd_dump_report(FILE* out, FILE* err, const Vector<String
|
||||
if (good) {
|
||||
vector<uint8_t> data;
|
||||
mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), getElapsedRealtimeNs(),
|
||||
&data);
|
||||
false /* include_current_bucket*/, &data);
|
||||
// TODO: print the returned StatsLogReport to file instead of printing to logcat.
|
||||
if (proto) {
|
||||
for (size_t i = 0; i < data.size(); i ++) {
|
||||
@@ -800,7 +800,8 @@ Status StatsService::getData(int64_t key, vector<uint8_t>* output) {
|
||||
VLOG("StatsService::getData with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid());
|
||||
if (checkCallingPermission(String16(kPermissionDump))) {
|
||||
ConfigKey configKey(ipc->getCallingUid(), key);
|
||||
mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(), output);
|
||||
mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(),
|
||||
false /* include_current_bucket*/, output);
|
||||
return Status::ok();
|
||||
} else {
|
||||
return Status::fromExceptionCode(binder::Status::EX_SECURITY);
|
||||
|
||||
@@ -76,7 +76,8 @@ const int FIELD_ID_CONFIG_STATS_ALERT_COUNT = 8;
|
||||
const int FIELD_ID_CONFIG_STATS_VALID = 9;
|
||||
const int FIELD_ID_CONFIG_STATS_BROADCAST = 10;
|
||||
const int FIELD_ID_CONFIG_STATS_DATA_DROP = 11;
|
||||
const int FIELD_ID_CONFIG_STATS_DUMP_REPORT = 12;
|
||||
const int FIELD_ID_CONFIG_STATS_DUMP_REPORT_TIME = 12;
|
||||
const int FIELD_ID_CONFIG_STATS_DUMP_REPORT_BYTES = 20;
|
||||
const int FIELD_ID_CONFIG_STATS_MATCHER_STATS = 13;
|
||||
const int FIELD_ID_CONFIG_STATS_CONDITION_STATS = 14;
|
||||
const int FIELD_ID_CONFIG_STATS_METRIC_STATS = 15;
|
||||
@@ -215,21 +216,22 @@ void StatsdStats::noteDataDropped(const ConfigKey& key, int32_t timeSec) {
|
||||
it->second->data_drop_time_sec.push_back(timeSec);
|
||||
}
|
||||
|
||||
void StatsdStats::noteMetricsReportSent(const ConfigKey& key) {
|
||||
noteMetricsReportSent(key, getWallClockSec());
|
||||
void StatsdStats::noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes) {
|
||||
noteMetricsReportSent(key, num_bytes, getWallClockSec());
|
||||
}
|
||||
|
||||
void StatsdStats::noteMetricsReportSent(const ConfigKey& key, int32_t timeSec) {
|
||||
void StatsdStats::noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes,
|
||||
int32_t timeSec) {
|
||||
lock_guard<std::mutex> lock(mLock);
|
||||
auto it = mConfigStats.find(key);
|
||||
if (it == mConfigStats.end()) {
|
||||
ALOGE("Config key %s not found!", key.ToString().c_str());
|
||||
return;
|
||||
}
|
||||
if (it->second->dump_report_time_sec.size() == kMaxTimestampCount) {
|
||||
it->second->dump_report_time_sec.pop_front();
|
||||
if (it->second->dump_report_stats.size() == kMaxTimestampCount) {
|
||||
it->second->dump_report_stats.pop_front();
|
||||
}
|
||||
it->second->dump_report_time_sec.push_back(timeSec);
|
||||
it->second->dump_report_stats.push_back(std::make_pair(timeSec, num_bytes));
|
||||
}
|
||||
|
||||
void StatsdStats::noteUidMapDropped(int deltas) {
|
||||
@@ -383,7 +385,7 @@ void StatsdStats::resetInternalLocked() {
|
||||
for (auto& config : mConfigStats) {
|
||||
config.second->broadcast_sent_time_sec.clear();
|
||||
config.second->data_drop_time_sec.clear();
|
||||
config.second->dump_report_time_sec.clear();
|
||||
config.second->dump_report_stats.clear();
|
||||
config.second->annotations.clear();
|
||||
config.second->matcher_stats.clear();
|
||||
config.second->condition_stats.clear();
|
||||
@@ -442,8 +444,8 @@ void StatsdStats::dumpStats(FILE* out) const {
|
||||
fprintf(out, "\tdata drop time: %d\n", dataDropTime);
|
||||
}
|
||||
|
||||
for (const auto& dumpTime : configStats->dump_report_time_sec) {
|
||||
fprintf(out, "\tdump report time: %d\n", dumpTime);
|
||||
for (const auto& dump : configStats->dump_report_stats) {
|
||||
fprintf(out, "\tdump report time: %d bytes: %lld\n", dump.first, (long long)dump.second);
|
||||
}
|
||||
|
||||
for (const auto& stats : pair.second->matcher_stats) {
|
||||
@@ -536,9 +538,16 @@ void addConfigStatsToProto(const ConfigStats& configStats, ProtoOutputStream* pr
|
||||
drop);
|
||||
}
|
||||
|
||||
for (const auto& dump : configStats.dump_report_time_sec) {
|
||||
proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DUMP_REPORT | FIELD_COUNT_REPEATED,
|
||||
dump);
|
||||
for (const auto& dump : configStats.dump_report_stats) {
|
||||
proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DUMP_REPORT_TIME |
|
||||
FIELD_COUNT_REPEATED,
|
||||
dump.first);
|
||||
}
|
||||
|
||||
for (const auto& dump : configStats.dump_report_stats) {
|
||||
proto->write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_STATS_DUMP_REPORT_BYTES |
|
||||
FIELD_COUNT_REPEATED,
|
||||
(long long)dump.second);
|
||||
}
|
||||
|
||||
for (const auto& annotation : configStats.annotations) {
|
||||
|
||||
@@ -43,7 +43,7 @@ struct ConfigStats {
|
||||
|
||||
std::list<int32_t> broadcast_sent_time_sec;
|
||||
std::list<int32_t> data_drop_time_sec;
|
||||
std::list<int32_t> dump_report_time_sec;
|
||||
std::list<std::pair<int32_t, int64_t>> dump_report_stats;
|
||||
|
||||
// Stores how many times a matcher have been matched. The map size is capped by kMaxConfigCount.
|
||||
std::map<const int64_t, int> matcher_stats;
|
||||
@@ -177,7 +177,7 @@ public:
|
||||
*
|
||||
* The report may be requested via StatsManager API, or through adb cmd.
|
||||
*/
|
||||
void noteMetricsReportSent(const ConfigKey& key);
|
||||
void noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes);
|
||||
|
||||
/**
|
||||
* Report the size of output tuple of a condition.
|
||||
@@ -355,7 +355,7 @@ private:
|
||||
|
||||
void noteDataDropped(const ConfigKey& key, int32_t timeSec);
|
||||
|
||||
void noteMetricsReportSent(const ConfigKey& key, int32_t timeSec);
|
||||
void noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes, int32_t timeSec);
|
||||
|
||||
void noteBroadcastSent(const ConfigKey& key, int32_t timeSec);
|
||||
|
||||
|
||||
@@ -123,8 +123,13 @@ void CountMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition
|
||||
}
|
||||
|
||||
void CountMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
|
||||
const bool include_current_partial_bucket,
|
||||
ProtoOutputStream* protoOutput) {
|
||||
flushIfNeededLocked(dumpTimeNs);
|
||||
if (include_current_partial_bucket) {
|
||||
flushLocked(dumpTimeNs);
|
||||
} else {
|
||||
flushIfNeededLocked(dumpTimeNs);
|
||||
}
|
||||
if (mPastBuckets.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,9 @@ protected:
|
||||
const LogEvent& event) override;
|
||||
|
||||
private:
|
||||
|
||||
void onDumpReportLocked(const int64_t dumpTimeNs,
|
||||
const bool include_current_partial_bucket,
|
||||
android::util::ProtoOutputStream* protoOutput) override;
|
||||
|
||||
// Internal interface to handle condition change.
|
||||
|
||||
@@ -439,8 +439,13 @@ void DurationMetricProducer::dropDataLocked(const int64_t dropTimeNs) {
|
||||
}
|
||||
|
||||
void DurationMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
|
||||
const bool include_current_partial_bucket,
|
||||
ProtoOutputStream* protoOutput) {
|
||||
flushIfNeededLocked(dumpTimeNs);
|
||||
if (include_current_partial_bucket) {
|
||||
flushLocked(dumpTimeNs);
|
||||
} else {
|
||||
flushIfNeededLocked(dumpTimeNs);
|
||||
}
|
||||
if (mPastBuckets.empty()) {
|
||||
VLOG(" Duration metric, empty return");
|
||||
return;
|
||||
|
||||
@@ -62,6 +62,7 @@ private:
|
||||
bool condition, const LogEvent& event);
|
||||
|
||||
void onDumpReportLocked(const int64_t dumpTimeNs,
|
||||
const bool include_current_partial_bucket,
|
||||
android::util::ProtoOutputStream* protoOutput) override;
|
||||
|
||||
// Internal interface to handle condition change.
|
||||
|
||||
@@ -101,6 +101,7 @@ std::unique_ptr<std::vector<uint8_t>> serializeProtoLocked(ProtoOutputStream& pr
|
||||
}
|
||||
|
||||
void EventMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
|
||||
const bool include_current_partial_bucket,
|
||||
ProtoOutputStream* protoOutput) {
|
||||
if (mProto->size() <= 0) {
|
||||
return;
|
||||
|
||||
@@ -47,6 +47,7 @@ private:
|
||||
const LogEvent& event) override;
|
||||
|
||||
void onDumpReportLocked(const int64_t dumpTimeNs,
|
||||
const bool include_current_partial_bucket,
|
||||
android::util::ProtoOutputStream* protoOutput) override;
|
||||
|
||||
// Internal interface to handle condition change.
|
||||
|
||||
@@ -156,8 +156,14 @@ void GaugeMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
|
||||
}
|
||||
|
||||
void GaugeMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
|
||||
const bool include_current_partial_bucket,
|
||||
ProtoOutputStream* protoOutput) {
|
||||
VLOG("Gauge metric %lld report now...", (long long)mMetricId);
|
||||
if (include_current_partial_bucket) {
|
||||
flushLocked(dumpTimeNs);
|
||||
} else {
|
||||
flushIfNeededLocked(dumpTimeNs);
|
||||
}
|
||||
|
||||
flushIfNeededLocked(dumpTimeNs);
|
||||
if (mPastBuckets.empty()) {
|
||||
|
||||
@@ -88,6 +88,7 @@ protected:
|
||||
|
||||
private:
|
||||
void onDumpReportLocked(const int64_t dumpTimeNs,
|
||||
const bool include_current_partial_bucket,
|
||||
android::util::ProtoOutputStream* protoOutput) override;
|
||||
|
||||
// for testing
|
||||
|
||||
@@ -112,9 +112,11 @@ public:
|
||||
|
||||
// Output the metrics data to [protoOutput]. All metrics reports end with the same timestamp.
|
||||
// This method clears all the past buckets.
|
||||
void onDumpReport(const int64_t dumpTimeNs, android::util::ProtoOutputStream* protoOutput) {
|
||||
void onDumpReport(const int64_t dumpTimeNs,
|
||||
const bool include_current_partial_bucket,
|
||||
android::util::ProtoOutputStream* protoOutput) {
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
return onDumpReportLocked(dumpTimeNs, protoOutput);
|
||||
return onDumpReportLocked(dumpTimeNs, include_current_partial_bucket, protoOutput);
|
||||
}
|
||||
|
||||
void dumpStates(FILE* out, bool verbose) const {
|
||||
@@ -168,15 +170,25 @@ protected:
|
||||
virtual void onSlicedConditionMayChangeLocked(bool overallCondition,
|
||||
const int64_t eventTime) = 0;
|
||||
virtual void onDumpReportLocked(const int64_t dumpTimeNs,
|
||||
const bool include_current_partial_bucket,
|
||||
android::util::ProtoOutputStream* protoOutput) = 0;
|
||||
virtual size_t byteSizeLocked() const = 0;
|
||||
virtual void dumpStatesLocked(FILE* out, bool verbose) const = 0;
|
||||
|
||||
/**
|
||||
* Flushes the current bucket if the eventTime is after the current bucket's end time.
|
||||
* Flushes the current bucket if the eventTime is after the current bucket's end time. This will
|
||||
also flush the current partial bucket in memory.
|
||||
*/
|
||||
virtual void flushIfNeededLocked(const int64_t& eventTime){};
|
||||
|
||||
/**
|
||||
* Flushes all the data including the current partial bucket.
|
||||
*/
|
||||
virtual void flushLocked(const int64_t& eventTime) {
|
||||
flushIfNeededLocked(eventTime);
|
||||
flushCurrentBucketLocked(eventTime);
|
||||
};
|
||||
|
||||
/**
|
||||
* For metrics that aggregate (ie, every metric producer except for EventMetricProducer),
|
||||
* we need to be able to flush the current buckets on demand (ie, end the current bucket and
|
||||
|
||||
@@ -190,14 +190,16 @@ void MetricsManager::dropData(const int64_t dropTimeNs) {
|
||||
}
|
||||
}
|
||||
|
||||
void MetricsManager::onDumpReport(const int64_t dumpTimeStampNs, ProtoOutputStream* protoOutput) {
|
||||
void MetricsManager::onDumpReport(const int64_t dumpTimeStampNs,
|
||||
const bool include_current_partial_bucket,
|
||||
ProtoOutputStream* protoOutput) {
|
||||
VLOG("=========================Metric Reports Start==========================");
|
||||
// one StatsLogReport per MetricProduer
|
||||
for (const auto& producer : mAllMetricProducers) {
|
||||
if (mNoReportMetricIds.find(producer->getMetricId()) == mNoReportMetricIds.end()) {
|
||||
uint64_t token =
|
||||
protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_METRICS);
|
||||
producer->onDumpReport(dumpTimeStampNs, protoOutput);
|
||||
producer->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, protoOutput);
|
||||
protoOutput->end(token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,8 +90,8 @@ public:
|
||||
|
||||
virtual void dropData(const int64_t dropTimeNs);
|
||||
|
||||
// Config source owner can call onDumpReport() to get all the metrics collected.
|
||||
virtual void onDumpReport(const int64_t dumpTimeNs,
|
||||
const bool include_current_partial_bucket,
|
||||
android::util::ProtoOutputStream* protoOutput);
|
||||
|
||||
// Computes the total byte size of all metrics managed by a single config source.
|
||||
|
||||
@@ -147,9 +147,14 @@ void ValueMetricProducer::dropDataLocked(const int64_t dropTimeNs) {
|
||||
}
|
||||
|
||||
void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
|
||||
const bool include_current_partial_bucket,
|
||||
ProtoOutputStream* protoOutput) {
|
||||
VLOG("metric %lld dump report now...", (long long)mMetricId);
|
||||
flushIfNeededLocked(dumpTimeNs);
|
||||
if (include_current_partial_bucket) {
|
||||
flushLocked(dumpTimeNs);
|
||||
} else {
|
||||
flushIfNeededLocked(dumpTimeNs);
|
||||
}
|
||||
if (mPastBuckets.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ protected:
|
||||
|
||||
private:
|
||||
void onDumpReportLocked(const int64_t dumpTimeNs,
|
||||
const bool include_current_partial_bucket,
|
||||
android::util::ProtoOutputStream* protoOutput) override;
|
||||
|
||||
// Internal interface to handle condition change.
|
||||
|
||||
@@ -243,10 +243,10 @@ message StatsdStatsReport {
|
||||
optional int32 matcher_count = 7;
|
||||
optional int32 alert_count = 8;
|
||||
optional bool is_valid = 9;
|
||||
|
||||
repeated int32 broadcast_sent_time_sec = 10;
|
||||
repeated int32 data_drop_time_sec = 11;
|
||||
repeated int32 dump_report_time_sec = 12;
|
||||
repeated int32 dump_report_data_size = 20;
|
||||
repeated MatcherStats matcher_stats = 13;
|
||||
repeated ConditionStats condition_stats = 14;
|
||||
repeated MetricStats metric_stats = 15;
|
||||
|
||||
@@ -139,7 +139,7 @@ TEST(StatsLogProcessorTest, TestUidMapHasSnapshot) {
|
||||
|
||||
// Expect to get no metrics, but snapshot specified above in uidmap.
|
||||
vector<uint8_t> bytes;
|
||||
p.onDumpReport(key, 1, &bytes);
|
||||
p.onDumpReport(key, 1, false, &bytes);
|
||||
|
||||
ConfigMetricsReportList output;
|
||||
output.ParseFromArray(bytes.data(), bytes.size());
|
||||
@@ -167,7 +167,7 @@ TEST(StatsLogProcessorTest, TestReportIncludesSubConfig) {
|
||||
|
||||
// Expect to get no metrics, but snapshot specified above in uidmap.
|
||||
vector<uint8_t> bytes;
|
||||
p.onDumpReport(key, 1, &bytes);
|
||||
p.onDumpReport(key, 1, false, &bytes);
|
||||
|
||||
ConfigMetricsReportList output;
|
||||
output.ParseFromArray(bytes.data(), bytes.size());
|
||||
|
||||
@@ -144,7 +144,7 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) {
|
||||
}
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
EXPECT_EQ(reports.reports_size(), 1);
|
||||
@@ -286,7 +286,7 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) {
|
||||
}
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
EXPECT_EQ(reports.reports_size(), 1);
|
||||
|
||||
@@ -172,7 +172,8 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondi
|
||||
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1,
|
||||
false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
|
||||
@@ -488,7 +489,8 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_AND_CombinationConditi
|
||||
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
|
||||
&buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
|
||||
@@ -731,7 +733,7 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_AND_Combination
|
||||
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCon
|
||||
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
|
||||
@@ -342,7 +342,7 @@ TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondi
|
||||
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
|
||||
@@ -521,7 +521,7 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_OR_CombinationCondit
|
||||
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
|
||||
@@ -718,7 +718,7 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_OR_CombinationConditio
|
||||
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
|
||||
|
||||
@@ -142,7 +142,8 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_SimpleCondition) {
|
||||
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
|
||||
&buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
|
||||
@@ -433,7 +434,8 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_SimpleCondition) {
|
||||
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
|
||||
&buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
|
||||
@@ -650,7 +652,7 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_SimpleCondition
|
||||
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
|
||||
}
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
EXPECT_EQ(1, reports.reports_size());
|
||||
|
||||
@@ -200,7 +200,7 @@ TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1) {
|
||||
}
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
EXPECT_EQ(reports.reports_size(), 1);
|
||||
@@ -314,7 +314,7 @@ TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2) {
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
EXPECT_EQ(reports.reports_size(), 1);
|
||||
|
||||
@@ -127,7 +127,7 @@ TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1)
|
||||
FeedEvents(config, processor);
|
||||
vector<uint8_t> buffer;
|
||||
ConfigMetricsReportList reports;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
|
||||
@@ -161,7 +161,7 @@ TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2)
|
||||
vector<uint8_t> buffer;
|
||||
ConfigMetricsReportList reports;
|
||||
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
EXPECT_EQ(reports.reports_size(), 1);
|
||||
@@ -208,7 +208,7 @@ TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3)
|
||||
processor->OnLogEvent(event.get());
|
||||
}
|
||||
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
EXPECT_EQ(reports.reports_size(), 1);
|
||||
@@ -237,7 +237,7 @@ TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration1)
|
||||
FeedEvents(config, processor);
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
@@ -262,7 +262,7 @@ TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration2)
|
||||
FeedEvents(config, processor);
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
EXPECT_EQ(reports.reports_size(), 1);
|
||||
@@ -304,7 +304,7 @@ TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration3)
|
||||
processor->OnLogEvent(event.get());
|
||||
}
|
||||
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, &buffer);
|
||||
processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
EXPECT_EQ(reports.reports_size(), 1);
|
||||
|
||||
@@ -129,9 +129,9 @@ TEST(StatsdStatsTest, TestSubStats) {
|
||||
stats.noteDataDropped(key);
|
||||
|
||||
// dump report -> 3
|
||||
stats.noteMetricsReportSent(key);
|
||||
stats.noteMetricsReportSent(key);
|
||||
stats.noteMetricsReportSent(key);
|
||||
stats.noteMetricsReportSent(key, 0);
|
||||
stats.noteMetricsReportSent(key, 0);
|
||||
stats.noteMetricsReportSent(key, 0);
|
||||
|
||||
vector<uint8_t> output;
|
||||
stats.dumpStats(&output, true); // Dump and reset stats
|
||||
@@ -143,6 +143,7 @@ TEST(StatsdStatsTest, TestSubStats) {
|
||||
EXPECT_EQ(2, configReport.broadcast_sent_time_sec_size());
|
||||
EXPECT_EQ(1, configReport.data_drop_time_sec_size());
|
||||
EXPECT_EQ(3, configReport.dump_report_time_sec_size());
|
||||
EXPECT_EQ(3, configReport.dump_report_data_size_size());
|
||||
EXPECT_EQ(1, configReport.annotation_size());
|
||||
EXPECT_EQ(123, configReport.annotation(0).field_int64());
|
||||
EXPECT_EQ(456, configReport.annotation(0).field_int32());
|
||||
@@ -268,7 +269,7 @@ TEST(StatsdStatsTest, TestTimestampThreshold) {
|
||||
for (int i = 0; i < StatsdStats::kMaxTimestampCount; i++) {
|
||||
stats.noteDataDropped(key, timestamps[i]);
|
||||
stats.noteBroadcastSent(key, timestamps[i]);
|
||||
stats.noteMetricsReportSent(key, timestamps[i]);
|
||||
stats.noteMetricsReportSent(key, 0, timestamps[i]);
|
||||
}
|
||||
|
||||
int32_t newTimestamp = 10000;
|
||||
@@ -276,7 +277,7 @@ TEST(StatsdStatsTest, TestTimestampThreshold) {
|
||||
// now it should trigger removing oldest timestamp
|
||||
stats.noteDataDropped(key, 10000);
|
||||
stats.noteBroadcastSent(key, 10000);
|
||||
stats.noteMetricsReportSent(key, 10000);
|
||||
stats.noteMetricsReportSent(key, 0, 10000);
|
||||
|
||||
EXPECT_TRUE(stats.mConfigStats.find(key) != stats.mConfigStats.end());
|
||||
const auto& configStats = stats.mConfigStats[key];
|
||||
@@ -284,7 +285,7 @@ TEST(StatsdStatsTest, TestTimestampThreshold) {
|
||||
size_t maxCount = StatsdStats::kMaxTimestampCount;
|
||||
EXPECT_EQ(maxCount, configStats->broadcast_sent_time_sec.size());
|
||||
EXPECT_EQ(maxCount, configStats->data_drop_time_sec.size());
|
||||
EXPECT_EQ(maxCount, configStats->dump_report_time_sec.size());
|
||||
EXPECT_EQ(maxCount, configStats->dump_report_stats.size());
|
||||
|
||||
// the oldest timestamp is the second timestamp in history
|
||||
EXPECT_EQ(1, configStats->broadcast_sent_time_sec.front());
|
||||
@@ -294,7 +295,7 @@ TEST(StatsdStatsTest, TestTimestampThreshold) {
|
||||
// the last timestamp is the newest timestamp.
|
||||
EXPECT_EQ(newTimestamp, configStats->broadcast_sent_time_sec.back());
|
||||
EXPECT_EQ(newTimestamp, configStats->data_drop_time_sec.back());
|
||||
EXPECT_EQ(newTimestamp, configStats->dump_report_time_sec.back());
|
||||
EXPECT_EQ(newTimestamp, configStats->dump_report_stats.back().first);
|
||||
}
|
||||
|
||||
} // namespace statsd
|
||||
|
||||
Reference in New Issue
Block a user