OSDN Git Service

Refactor MetricProducer so that a big chunk of boiler plate code can be removed.
authorYao Chen <yaochen@google.com>
Fri, 20 Oct 2017 23:59:25 +0000 (16:59 -0700)
committerYao Chen <yaochen@google.com>
Sat, 21 Oct 2017 00:14:44 +0000 (17:14 -0700)
Test: statsd_test
Change-Id: I62489b94c6dfceb0b08ce4147c331a8a785eabb4

cmds/statsd/Android.mk
cmds/statsd/src/metrics/CountMetricProducer.cpp
cmds/statsd/src/metrics/CountMetricProducer.h
cmds/statsd/src/metrics/DurationMetricProducer.cpp
cmds/statsd/src/metrics/DurationMetricProducer.h
cmds/statsd/src/metrics/MetricProducer.cpp [new file with mode: 0644]
cmds/statsd/src/metrics/MetricProducer.h

index 3c2f2d5..1804e53 100644 (file)
@@ -37,6 +37,7 @@ statsd_common_src := \
     src/matchers/matcher_util.cpp \
     src/matchers/SimpleLogMatchingTracker.cpp \
     src/metrics/CountAnomalyTracker.cpp \
+    src/metrics/MetricProducer.cpp \
     src/metrics/CountMetricProducer.cpp \
     src/metrics/DurationMetricProducer.cpp \
     src/metrics/MetricsManager.cpp \
index 1f07914..28cb503 100644 (file)
@@ -124,52 +124,23 @@ void CountMetricProducer::onConditionChanged(const bool conditionMet) {
     mCondition = conditionMet;
 }
 
-void CountMetricProducer::onMatchedLogEvent(const size_t matcherIndex, const LogEvent& event) {
+void CountMetricProducer::onMatchedLogEventInternal(
+        const size_t matcherIndex, const HashableDimensionKey& eventKey,
+        const map<string, HashableDimensionKey>& conditionKey, bool condition,
+        const LogEvent& event) {
     uint64_t eventTimeNs = event.GetTimestampNs();
-    // this is old event, maybe statsd restarted?
-    if (eventTimeNs < mStartTimeNs) {
-        return;
-    }
 
     flushCounterIfNeeded(eventTimeNs);
 
-    if (mConditionSliced) {
-        map<string, HashableDimensionKey> conditionKeys;
-        for (const auto& link : mConditionLinks) {
-            VLOG("Condition link key_in_main size %d", link.key_in_main_size());
-            HashableDimensionKey conditionKey = getDimensionKeyForCondition(event, link);
-            conditionKeys[link.condition()] = conditionKey;
-        }
-        if (mWizard->query(mConditionTrackerIndex, conditionKeys) != ConditionState::kTrue) {
-            VLOG("metric %lld sliced condition not met", mMetric.metric_id());
-            return;
-        }
-    } else {
-        if (!mCondition) {
-            VLOG("metric %lld condition not met", mMetric.metric_id());
-            return;
-        }
-    }
-
-    HashableDimensionKey hashableKey;
-
-    if (mDimension.size() > 0) {
-        vector<KeyValuePair> key = getDimensionKey(event, mDimension);
-        hashableKey = getHashableKey(key);
-        // Add the HashableDimensionKey->vector<KeyValuePair> to the map, because StatsLogReport
-        // expects vector<KeyValuePair>.
-        if (mDimensionKeyMap.find(hashableKey) == mDimensionKeyMap.end()) {
-            mDimensionKeyMap[hashableKey] = key;
-        }
-    } else {
-        hashableKey = DEFAULT_DIMENSION_KEY;
+    if (condition == false) {
+        return;
     }
 
-    auto it = mCurrentSlicedCounter.find(hashableKey);
+    auto it = mCurrentSlicedCounter.find(eventKey);
 
     if (it == mCurrentSlicedCounter.end()) {
         // create a counter for the new key
-        mCurrentSlicedCounter[hashableKey] = 1;
+        mCurrentSlicedCounter[eventKey] = 1;
 
     } else {
         // increment the existing value
@@ -177,8 +148,8 @@ void CountMetricProducer::onMatchedLogEvent(const size_t matcherIndex, const Log
         count++;
     }
 
-    VLOG("metric %lld %s->%d", mMetric.metric_id(), hashableKey.c_str(),
-         mCurrentSlicedCounter[hashableKey]);
+    VLOG("metric %lld %s->%d", mMetric.metric_id(), eventKey.c_str(),
+         mCurrentSlicedCounter[eventKey]);
 }
 
 // When a new matched event comes in, we check if event falls into the current
@@ -215,4 +186,4 @@ void CountMetricProducer::flushCounterIfNeeded(const uint64_t eventTimeNs) {
 
 }  // namespace statsd
 }  // namespace os
-}  // namespace android
+}  // namespace android
\ No newline at end of file
index f0d6025..8bbdb01 100644 (file)
@@ -41,8 +41,6 @@ public:
 
     virtual ~CountMetricProducer();
 
-    void onMatchedLogEvent(const size_t matcherIndex, const LogEvent& event) override;
-
     void onConditionChanged(const bool conditionMet) override;
 
     void finish() override;
@@ -54,6 +52,11 @@ public:
     // TODO: Implement this later.
     virtual void notifyAppUpgrade(const string& apk, const int uid, const int version) override{};
 
+protected:
+    void onMatchedLogEventInternal(const size_t matcherIndex, const HashableDimensionKey& eventKey,
+                                   const std::map<std::string, HashableDimensionKey>& conditionKey,
+                                   bool condition, const LogEvent& event) override;
+
 private:
     const CountMetric mMetric;
 
index aa597f4..38e55fd 100644 (file)
@@ -137,11 +137,10 @@ StatsLogReport DurationMetricProducer::onDumpReport() {
     return report;
 };
 
-void DurationMetricProducer::onMatchedLogEvent(const size_t matcherIndex, const LogEvent& event) {
-    if (event.GetTimestampNs() < mStartTimeNs) {
-        return;
-    }
-
+void DurationMetricProducer::onMatchedLogEventInternal(
+        const size_t matcherIndex, const HashableDimensionKey& eventKey,
+        const map<string, HashableDimensionKey>& conditionKeys, bool condition,
+        const LogEvent& event) {
     flushDurationIfNeeded(event.GetTimestampNs());
 
     if (matcherIndex == mStopAllIndex) {
@@ -149,49 +148,20 @@ void DurationMetricProducer::onMatchedLogEvent(const size_t matcherIndex, const
         return;
     }
 
-    HashableDimensionKey hashableKey;
-    if (mDimension.size() > 0) {
-        // hook up sliced counter with AnomalyMonitor.
-        vector<KeyValuePair> key = getDimensionKey(event, mDimension);
-        hashableKey = getHashableKey(key);
-        // Add the HashableDimensionKey->DimensionKey to the map, because StatsLogReport expects
-        // vector<KeyValuePair>.
-        if (mDimensionKeyMap.find(hashableKey) == mDimensionKeyMap.end()) {
-            mDimensionKeyMap[hashableKey] = key;
-        }
-    } else {
-        hashableKey = DEFAULT_DIMENSION_KEY;
-    }
-
-    if (mCurrentSlicedDuration.find(hashableKey) == mCurrentSlicedDuration.end() &&
-        mConditionSliced) {
+    if (mCurrentSlicedDuration.find(eventKey) == mCurrentSlicedDuration.end() && mConditionSliced) {
         // add the durationInfo for the current bucket.
-        auto& durationInfo = mCurrentSlicedDuration[hashableKey];
-        auto& conditionKeys = durationInfo.conditionKeys;
-        // get and cache the keys for query condition.
-        for (const auto& link : mConditionLinks) {
-            HashableDimensionKey conditionKey = getDimensionKeyForCondition(event, link);
-            conditionKeys[link.condition()] = conditionKey;
-        }
-    }
-
-    bool conditionMet;
-    if (mConditionSliced) {
-        const auto& conditionKeys = mCurrentSlicedDuration[hashableKey].conditionKeys;
-        conditionMet =
-                mWizard->query(mConditionTrackerIndex, conditionKeys) == ConditionState::kTrue;
-    } else {
-        conditionMet = mCondition;
+        auto& durationInfo = mCurrentSlicedDuration[eventKey];
+        durationInfo.conditionKeys = conditionKeys;
     }
 
     if (matcherIndex == mStartIndex) {
-        VLOG("Metric %lld Key: %s Start, Condition %d", mMetric.metric_id(), hashableKey.c_str(),
-             conditionMet);
-        noteStart(hashableKey, conditionMet, event.GetTimestampNs());
+        VLOG("Metric %lld Key: %s Start, Condition %d", mMetric.metric_id(), eventKey.c_str(),
+             condition);
+        noteStart(eventKey, condition, event.GetTimestampNs());
     } else if (matcherIndex == mStopIndex) {
-        VLOG("Metric %lld Key: %s Stop, Condition %d", mMetric.metric_id(), hashableKey.c_str(),
-             conditionMet);
-        noteStop(hashableKey, event.GetTimestampNs());
+        VLOG("Metric %lld Key: %s Stop, Condition %d", mMetric.metric_id(), eventKey.c_str(),
+             condition);
+        noteStop(eventKey, event.GetTimestampNs());
     }
 }
 
index 44c3254..19e2437 100644 (file)
@@ -61,8 +61,6 @@ public:
 
     virtual ~DurationMetricProducer();
 
-    void onMatchedLogEvent(const size_t matcherIndex, const LogEvent& event) override;
-
     void onConditionChanged(const bool conditionMet) override;
 
     void finish() override;
@@ -74,6 +72,11 @@ public:
     // TODO: Implement this later.
     virtual void notifyAppUpgrade(const string& apk, const int uid, const int version) override{};
 
+protected:
+    void onMatchedLogEventInternal(const size_t matcherIndex, const HashableDimensionKey& eventKey,
+                                   const std::map<std::string, HashableDimensionKey>& conditionKeys,
+                                   bool condition, const LogEvent& event) override;
+
 private:
     const DurationMetric mMetric;
 
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
new file mode 100644 (file)
index 0000000..3c8ce6e
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "MetricProducer.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+using std::map;
+
+void MetricProducer::onMatchedLogEvent(const size_t matcherIndex, const LogEvent& event) {
+    uint64_t eventTimeNs = event.GetTimestampNs();
+    // this is old event, maybe statsd restarted?
+    if (eventTimeNs < mStartTimeNs) {
+        return;
+    }
+
+    HashableDimensionKey eventKey;
+
+    if (mDimension.size() > 0) {
+        vector<KeyValuePair> key = getDimensionKey(event, mDimension);
+        eventKey = getHashableKey(key);
+        // Add the HashableDimensionKey->vector<KeyValuePair> to the map, because StatsLogReport
+        // expects vector<KeyValuePair>.
+        if (mDimensionKeyMap.find(eventKey) == mDimensionKeyMap.end()) {
+            mDimensionKeyMap[eventKey] = key;
+        }
+    } else {
+        eventKey = DEFAULT_DIMENSION_KEY;
+    }
+
+    bool condition;
+
+    map<string, HashableDimensionKey> conditionKeys;
+    if (mConditionSliced) {
+        for (const auto& link : mConditionLinks) {
+            HashableDimensionKey conditionKey = getDimensionKeyForCondition(event, link);
+            conditionKeys[link.condition()] = conditionKey;
+        }
+        if (mWizard->query(mConditionTrackerIndex, conditionKeys) != ConditionState::kTrue) {
+            condition = false;
+        } else {
+            condition = true;
+        }
+    } else {
+        condition = mCondition;
+    }
+
+    onMatchedLogEventInternal(matcherIndex, eventKey, conditionKeys, condition, event);
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
\ No newline at end of file
index afaab64..496b145 100644 (file)
@@ -48,7 +48,7 @@ public:
     virtual ~MetricProducer(){};
 
     // Consume the parsed stats log entry that already matched the "what" of the metric.
-    virtual void onMatchedLogEvent(const size_t matcherIndex, const LogEvent& event) = 0;
+    void onMatchedLogEvent(const size_t matcherIndex, const LogEvent& event);
 
     virtual void onConditionChanged(const bool condition) = 0;
 
@@ -86,6 +86,26 @@ protected:
     std::unordered_map<HashableDimensionKey, std::vector<KeyValuePair>> mDimensionKeyMap;
 
     std::vector<EventConditionLink> mConditionLinks;
+
+    /*
+     * Individual metrics can implement their own business logic here. All pre-processing is done.
+     *
+     * [matcherIndex]: the index of the matcher which matched this event. This is interesting to
+     *                 DurationMetric, because it has start/stop/stop_all 3 matchers.
+     * [eventKey]: the extracted dimension key for the final output. if the metric doesn't have
+     *             dimensions, it will be DEFAULT_DIMENSION_KEY
+     * [conditionKey]: the keys of conditions which should be used to query the condition for this
+     *                 target event (from EventConditionLink). This is passed to individual metrics
+     *                 because DurationMetric needs it to be cached.
+     * [condition]: whether condition is met. If condition is sliced, this is the result coming from
+     *              query with ConditionWizard; If condition is not sliced, this is the
+     *              nonSlicedCondition.
+     * [event]: the log event, just in case the metric needs its data, e.g., EventMetric.
+     */
+    virtual void onMatchedLogEventInternal(
+            const size_t matcherIndex, const HashableDimensionKey& eventKey,
+            const std::map<std::string, HashableDimensionKey>& conditionKey, bool condition,
+            const LogEvent& event) = 0;
 };
 
 }  // namespace statsd