Flush the partial bucket when startd shuts down or config updated.
Test: statsd test
BUG: b/77556036
Change-Id: Ie4a04ace55e07c4529cdff5906ba874f8815f620
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 41527f6..90ce735 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -212,7 +212,10 @@
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 @@
* 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 @@
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 @@
}
}
- StatsdStats::getInstance().noteMetricsReportSent(key);
+ StatsdStats::getInstance().noteMetricsReportSent(key, proto.size());
}
/*
@@ -306,16 +308,20 @@
*/
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 @@
(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 @@
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::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
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index d37429e..1e82b1e 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -48,7 +48,8 @@
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 @@
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
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index dac73ef..f16109c 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -501,7 +501,7 @@
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 @@
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);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 7b2881d..b589d0d 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -76,7 +76,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 @@
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 @@
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 @@
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 @@
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) {
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 914d2af..123a703 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -43,7 +43,7 @@
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 @@
*
* 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 @@
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);
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 98963bd..c77e07b 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -123,8 +123,13 @@
}
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;
}
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 5991c28..cafc882 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -54,7 +54,9 @@
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.
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 19155de..3125fa7 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -439,8 +439,13 @@
}
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;
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 80fb829..80fbdde 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -62,6 +62,7 @@
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.
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index d55cb3f..33ab9aa 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -101,6 +101,7 @@
}
void EventMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
ProtoOutputStream* protoOutput) {
if (mProto->size() <= 0) {
return;
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index fbbc7e2..5c29174 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -47,6 +47,7 @@
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.
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 2561d1d..3c77aae 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -156,8 +156,14 @@
}
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()) {
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index f49180f..04b7df9 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -88,6 +88,7 @@
private:
void onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput) override;
// for testing
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index db5d32c..f931e57 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -112,9 +112,11 @@
// 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,16 +170,26 @@
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
* start new bucket). If this function is called when eventTimeNs is greater than the current
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 22827b0..b7f1bd5 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -190,14 +190,16 @@
}
}
-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);
}
}
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 9a9b33c..6aa260a 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -90,8 +90,8 @@
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.
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index fd623ca..51fac8c 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -147,9 +147,14 @@
}
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;
}
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index c8f7062..b5f6429 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -87,6 +87,7 @@
private:
void onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput) override;
// Internal interface to handle condition change.
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 3b86d2d..36b24c8 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -243,10 +243,10 @@
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;
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 09daf75..fb8877a 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -139,7 +139,7 @@
// 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 @@
// 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());
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
index a97bc41..4dd0da8 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -144,7 +144,7 @@
}
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 @@
}
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);
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
index 63e23ce..eb57d470 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
@@ -172,7 +172,8 @@
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 @@
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 @@
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()));
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
index c2334d8..9729a2e 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
@@ -130,7 +130,7 @@
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 @@
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 @@
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 @@
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()));
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
index ab37140..4e2c36e 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
@@ -142,7 +142,8 @@
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 @@
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 @@
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()));
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
index 2b91324..18a0485 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
@@ -148,7 +148,7 @@
}
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());
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index 1440f29..1952a6f 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -200,7 +200,7 @@
}
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 @@
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);
diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
index bfae8bc..f2d47c7 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -127,7 +127,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
index 5c35d96..e99e402 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -129,9 +129,9 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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