1/ Duration anomaly tracker with alarm.
2/ Init anomaly from config based on the public language.
3/ Unit tests for anomaly detection in count/gauge producer.
4/ Revisit the duration tracker logic.

Test: unit test passed.
Change-Id: I2423c0e0f05b1e37626954de9e749303423963f2
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index eba2e06..b0a97b1 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -110,16 +110,16 @@
 }
 
 unique_ptr<DurationTracker> DurationMetricProducer::createDurationTracker(
-        vector<DurationBucket>& bucket) {
+        const HashableDimensionKey& eventKey, vector<DurationBucket>& bucket) {
     switch (mMetric.aggregation_type()) {
         case DurationMetric_AggregationType_SUM:
-            return make_unique<OringDurationTracker>(mWizard, mConditionTrackerIndex, mNested,
-                                                     mCurrentBucketStartTimeNs, mBucketSizeNs,
-                                                     bucket);
+            return make_unique<OringDurationTracker>(eventKey, mWizard, mConditionTrackerIndex,
+                                                     mNested, mCurrentBucketStartTimeNs,
+                                                     mBucketSizeNs, mAnomalyTrackers, bucket);
         case DurationMetric_AggregationType_MAX_SPARSE:
-            return make_unique<MaxDurationTracker>(mWizard, mConditionTrackerIndex, mNested,
-                                                   mCurrentBucketStartTimeNs, mBucketSizeNs,
-                                                   bucket);
+            return make_unique<MaxDurationTracker>(eventKey, mWizard, mConditionTrackerIndex,
+                                                   mNested, mCurrentBucketStartTimeNs,
+                                                   mBucketSizeNs, mAnomalyTrackers, bucket);
     }
 }
 
@@ -131,7 +131,6 @@
 void DurationMetricProducer::onSlicedConditionMayChange(const uint64_t eventTime) {
     VLOG("Metric %s onSlicedConditionMayChange", mMetric.name().c_str());
     // Now for each of the on-going event, check if the condition has changed for them.
-    flushIfNeeded(eventTime);
     for (auto& pair : mCurrentSlicedDuration) {
         pair.second->onSlicedConditionMayChange(eventTime);
     }
@@ -142,27 +141,11 @@
     mCondition = conditionMet;
     // TODO: need to populate the condition change time from the event which triggers the condition
     // change, instead of using current time.
-
-    flushIfNeeded(eventTime);
     for (auto& pair : mCurrentSlicedDuration) {
         pair.second->onConditionChanged(conditionMet, eventTime);
     }
 }
 
-static void addDurationBucketsToReport(StatsLogReport_DurationMetricDataWrapper& wrapper,
-                                       const vector<KeyValuePair>& key,
-                                       const vector<DurationBucketInfo>& buckets) {
-    DurationMetricData* data = wrapper.add_data();
-    for (const auto& kv : key) {
-        data->add_dimension()->CopyFrom(kv);
-    }
-    for (const auto& bucket : buckets) {
-        data->add_bucket_info()->CopyFrom(bucket);
-        VLOG("\t bucket [%lld - %lld] duration(ns): %lld", bucket.start_bucket_nanos(),
-             bucket.end_bucket_nanos(), bucket.duration_nanos());
-    }
-}
-
 std::unique_ptr<std::vector<uint8_t>> DurationMetricProducer::onDumpReport() {
     long long endTime = time(nullptr) * NS_PER_SEC;
 
@@ -231,7 +214,6 @@
     if (mCurrentBucketStartTimeNs + mBucketSizeNs > eventTime) {
         return;
     }
-
     VLOG("flushing...........");
     for (auto it = mCurrentSlicedDuration.begin(); it != mCurrentSlicedDuration.end();) {
         if (it->second->flushIfNeeded(eventTime)) {
@@ -244,6 +226,7 @@
 
     int numBucketsForward = (eventTime - mCurrentBucketStartTimeNs) / mBucketSizeNs;
     mCurrentBucketStartTimeNs += numBucketsForward * mBucketSizeNs;
+    mCurrentBucketNum += numBucketsForward;
 }
 
 void DurationMetricProducer::onMatchedLogEventInternal(
@@ -262,7 +245,7 @@
     HashableDimensionKey atomKey = getHashableKey(getDimensionKey(event, mInternalDimension));
 
     if (mCurrentSlicedDuration.find(eventKey) == mCurrentSlicedDuration.end()) {
-        mCurrentSlicedDuration[eventKey] = createDurationTracker(mPastBuckets[eventKey]);
+        mCurrentSlicedDuration[eventKey] = createDurationTracker(eventKey, mPastBuckets[eventKey]);
     }
 
     auto it = mCurrentSlicedDuration.find(eventKey);