add drop byte info in statsdstats

Test: manual test and unit test
Change-Id: I8675b399f83b2bb43be4fc2e6c8f28db37b8863b
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index f4c70be..12e2560 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -442,7 +442,7 @@
     if (totalBytes >
         StatsdStats::kMaxMetricsBytesPerConfig) {  // Too late. We need to start clearing data.
         metricsManager.dropData(timestampNs);
-        StatsdStats::getInstance().noteDataDropped(key);
+        StatsdStats::getInstance().noteDataDropped(key, totalBytes);
         VLOG("StatsD had to toss out metrics for %s", key.ToString().c_str());
     } else if ((totalBytes > StatsdStats::kBytesPerConfigTriggerGetData) ||
                (mOnDiskDataConfigs.find(key) != mOnDiskDataConfigs.end())) {
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index bf0bfec..023d835 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -73,7 +73,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_DATA_DROP_TIME = 11;
+const int FIELD_ID_CONFIG_STATS_DATA_DROP_BYTES = 21;
 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;
@@ -205,11 +206,11 @@
     it->second->broadcast_sent_time_sec.push_back(timeSec);
 }
 
-void StatsdStats::noteDataDropped(const ConfigKey& key) {
-    noteDataDropped(key, getWallClockSec());
+void StatsdStats::noteDataDropped(const ConfigKey& key, const size_t totalBytes) {
+    noteDataDropped(key, totalBytes, getWallClockSec());
 }
 
-void StatsdStats::noteDataDropped(const ConfigKey& key, int32_t timeSec) {
+void StatsdStats::noteDataDropped(const ConfigKey& key, const size_t totalBytes, int32_t timeSec) {
     lock_guard<std::mutex> lock(mLock);
     auto it = mConfigStats.find(key);
     if (it == mConfigStats.end()) {
@@ -218,8 +219,10 @@
     }
     if (it->second->data_drop_time_sec.size() == kMaxTimestampCount) {
         it->second->data_drop_time_sec.pop_front();
+        it->second->data_drop_bytes.pop_front();
     }
     it->second->data_drop_time_sec.push_back(timeSec);
+    it->second->data_drop_bytes.push_back(totalBytes);
 }
 
 void StatsdStats::noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes) {
@@ -382,6 +385,7 @@
     for (auto& config : mConfigStats) {
         config.second->broadcast_sent_time_sec.clear();
         config.second->data_drop_time_sec.clear();
+        config.second->data_drop_bytes.clear();
         config.second->dump_report_stats.clear();
         config.second->annotations.clear();
         config.second->matcher_stats.clear();
@@ -421,8 +425,12 @@
             dprintf(out, "\tbroadcast time: %d\n", broadcastTime);
         }
 
-        for (const auto& dataDropTime : configStats->data_drop_time_sec) {
-            dprintf(out, "\tdata drop time: %d\n", dataDropTime);
+        auto dropTimePtr = configStats->data_drop_time_sec.begin();
+        auto dropBytesPtr = configStats->data_drop_bytes.begin();
+        for (int i = 0; i < (int)configStats->data_drop_time_sec.size();
+             i++, dropTimePtr++, dropBytesPtr++) {
+            dprintf(out, "\tdata drop time: %d with size %lld", *dropTimePtr,
+                    (long long)*dropBytesPtr);
         }
     }
     dprintf(out, "%lu Active Configs\n", (unsigned long)mConfigStats.size());
@@ -445,9 +453,13 @@
                     (long long)broadcastTime);
         }
 
-        for (const auto& dataDropTime : configStats->data_drop_time_sec) {
-            dprintf(out, "\tdata drop time: %s(%lld)\n", buildTimeString(dataDropTime).c_str(),
-                    (long long)dataDropTime);
+        auto dropTimePtr = configStats->data_drop_time_sec.begin();
+        auto dropBytesPtr = configStats->data_drop_bytes.begin();
+        for (int i = 0; i < (int)configStats->data_drop_time_sec.size();
+             i++, dropTimePtr++, dropBytesPtr++) {
+            dprintf(out, "\tdata drop time: %s(%lld) with %lld bytes\n",
+                    buildTimeString(*dropTimePtr).c_str(), (long long)*dropTimePtr,
+                    (long long)*dropBytesPtr);
         }
 
         for (const auto& dump : configStats->dump_report_stats) {
@@ -540,9 +552,15 @@
                      broadcast);
     }
 
-    for (const auto& drop : configStats.data_drop_time_sec) {
-        proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DATA_DROP | FIELD_COUNT_REPEATED,
-                     drop);
+    for (const auto& drop_time : configStats.data_drop_time_sec) {
+        proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DATA_DROP_TIME | FIELD_COUNT_REPEATED,
+                     drop_time);
+    }
+
+    for (const auto& drop_bytes : configStats.data_drop_bytes) {
+        proto->write(
+                FIELD_TYPE_INT64 | FIELD_ID_CONFIG_STATS_DATA_DROP_BYTES | FIELD_COUNT_REPEATED,
+                (long long)drop_bytes);
     }
 
     for (const auto& dump : configStats.dump_report_stats) {
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index a8188c8..7d95b54 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -43,6 +43,8 @@
 
     std::list<int32_t> broadcast_sent_time_sec;
     std::list<int32_t> data_drop_time_sec;
+    // Number of bytes dropped at corresponding time.
+    std::list<int64_t> data_drop_bytes;
     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.
@@ -169,7 +171,7 @@
     /**
      * Report a config's metrics data has been dropped.
      */
-    void noteDataDropped(const ConfigKey& key);
+    void noteDataDropped(const ConfigKey& key, const size_t totalBytes);
 
     /**
      * Report metrics data report has been sent.
@@ -350,7 +352,7 @@
 
     void resetInternalLocked();
 
-    void noteDataDropped(const ConfigKey& key, int32_t timeSec);
+    void noteDataDropped(const ConfigKey& key, const size_t totalBytes, int32_t timeSec);
 
     void noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes, int32_t timeSec);
 
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 10ed7f3..e8f74d3 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -328,6 +328,7 @@
         optional bool is_valid = 9;
         repeated int32 broadcast_sent_time_sec = 10;
         repeated int32 data_drop_time_sec = 11;
+        repeated int64 data_drop_bytes = 21;
         repeated int32 dump_report_time_sec = 12;
         repeated int32 dump_report_data_size = 20;
         repeated MatcherStats matcher_stats = 13;
diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
index 967ef3c..f37f908 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -126,7 +126,7 @@
     stats.noteBroadcastSent(key);
 
     // data drop -> 1
-    stats.noteDataDropped(key);
+    stats.noteDataDropped(key, 123);
 
     // dump report -> 3
     stats.noteMetricsReportSent(key, 0);
@@ -142,6 +142,8 @@
     const auto& configReport = report.config_stats(0);
     EXPECT_EQ(2, configReport.broadcast_sent_time_sec_size());
     EXPECT_EQ(1, configReport.data_drop_time_sec_size());
+    EXPECT_EQ(1, configReport.data_drop_bytes_size());
+    EXPECT_EQ(123, configReport.data_drop_bytes(0));
     EXPECT_EQ(3, configReport.dump_report_time_sec_size());
     EXPECT_EQ(3, configReport.dump_report_data_size_size());
     EXPECT_EQ(1, configReport.annotation_size());
@@ -275,7 +277,7 @@
     int32_t newTimestamp = 10000;
 
     // now it should trigger removing oldest timestamp
-    stats.noteDataDropped(key, 10000);
+    stats.noteDataDropped(key, 123, 10000);
     stats.noteBroadcastSent(key, 10000);
     stats.noteMetricsReportSent(key, 0, 10000);
 
@@ -295,6 +297,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(123, configStats->data_drop_bytes.back());
     EXPECT_EQ(newTimestamp, configStats->dump_report_stats.back().first);
 }