Merge "Tracks the total number of buckets."
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index d661ee8..71d39ff 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -493,6 +493,11 @@
     getAtomMetricStats(metricId).invalidatedBucket++;
 }
 
+void StatsdStats::noteBucketCount(int64_t metricId) {
+    lock_guard<std::mutex> lock(mLock);
+    getAtomMetricStats(metricId).bucketCount++;
+}
+
 void StatsdStats::noteBucketBoundaryDelayNs(int64_t metricId, int64_t timeDelayNs) {
     lock_guard<std::mutex> lock(mLock);
     AtomMetricStats& pullStats = getAtomMetricStats(metricId);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index e039be2..7c2d846 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -403,6 +403,11 @@
     void noteInvalidatedBucket(int64_t metricId);
 
     /**
+     * Tracks the total number of buckets (include skipped/invalid buckets).
+     */
+    void noteBucketCount(int64_t metricId);
+
+    /**
      * For pulls at bucket boundaries, it represents the misalignment between the real timestamp and
      * the end of the bucket.
      */
@@ -464,6 +469,7 @@
         int64_t minBucketBoundaryDelayNs = 0;
         int64_t maxBucketBoundaryDelayNs = 0;
         long bucketUnknownCondition = 0;
+        long bucketCount = 0;
     } AtomMetricStats;
 
 private:
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 96d1447..254d7d5 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -371,6 +371,7 @@
         }
     }
 
+    StatsdStats::getInstance().noteBucketCount(mMetricId);
     // Only resets the counters, but doesn't setup the times nor numbers.
     // (Do not clear since the old one is still referenced in mAnomalyTrackers).
     mCurrentSlicedCounter = std::make_shared<DimToValMap>();
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 5e4594b..7dc4e2d 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -601,6 +601,7 @@
             whatIt++;
         }
     }
+    StatsdStats::getInstance().noteBucketCount(mMetricId);
 }
 
 void DurationMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 7b001b3..2b6cac8 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -576,6 +576,7 @@
         }
     }
 
+    StatsdStats::getInstance().noteBucketCount(mMetricId);
     mCurrentSlicedBucket = std::make_shared<DimToGaugeAtomsMap>();
 }
 
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index e94b75c..e7f7af2 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -769,6 +769,7 @@
     if (!mCurrentBucketIsInvalid) {
         appendToFullBucket(eventTimeNs, fullBucketEndTimeNs);
     }
+    StatsdStats::getInstance().noteBucketCount(mMetricId);
     initCurrentSlicedBucket();
     mCurrentBucketIsInvalid = false;
     mCurrentBucketStartTimeNs = nextBucketStartTimeNs;
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 623d8bc..166e087 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -426,6 +426,7 @@
       optional int64 min_bucket_boundary_delay_ns = 9;
       optional int64 max_bucket_boundary_delay_ns = 10;
       optional int64 bucket_unknown_condition = 11;
+      optional int64 bucket_count = 12;
     }
     repeated AtomMetricStats atom_metric_stats = 17;
 
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index ca645e1..31f160d 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -85,6 +85,7 @@
 const int FIELD_ID_MIN_BUCKET_BOUNDARY_DELAY_NS = 9;
 const int FIELD_ID_MAX_BUCKET_BOUNDARY_DELAY_NS = 10;
 const int FIELD_ID_BUCKET_UNKNOWN_CONDITION = 11;
+const int FIELD_ID_BUCKET_COUNT = 12;
 
 namespace {
 
@@ -515,6 +516,8 @@
                        (long long)pair.second.maxBucketBoundaryDelayNs);
     protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_UNKNOWN_CONDITION,
                        (long long)pair.second.bucketUnknownCondition);
+    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_COUNT,
+                       (long long)pair.second.bucketCount);
     protoOutput->end(token);
 }