diff options
| -rw-r--r-- | cmds/statsd/Android.mk | 3 | ||||
| -rw-r--r-- | cmds/statsd/src/DropboxWriter.h | 5 | ||||
| -rw-r--r-- | cmds/statsd/src/StatsLogProcessor.cpp | 72 | ||||
| -rw-r--r-- | cmds/statsd/src/StatsLogProcessor.h | 26 | ||||
| -rw-r--r-- | cmds/statsd/src/StatsService.h | 1 | ||||
| -rw-r--r-- | cmds/statsd/src/matchers/LogEntryMatcherManager.cpp | 156 | ||||
| -rw-r--r-- | cmds/statsd/src/matchers/LogEntryMatcherManager.h | 46 | ||||
| -rw-r--r-- | cmds/statsd/src/metrics/ConditionTracker.cpp | 54 | ||||
| -rw-r--r-- | cmds/statsd/src/metrics/ConditionTracker.h | 51 | ||||
| -rw-r--r-- | cmds/statsd/src/metrics/CountMetricProducer.cpp | 107 | ||||
| -rw-r--r-- | cmds/statsd/src/metrics/CountMetricProducer.h | 67 | ||||
| -rw-r--r-- | cmds/statsd/src/metrics/MetricProducer.h | 46 | ||||
| -rw-r--r-- | cmds/statsd/src/metrics/MetricsManager.cpp | 132 | ||||
| -rw-r--r-- | cmds/statsd/src/metrics/MetricsManager.h | 64 | ||||
| -rw-r--r-- | cmds/statsd/src/parse_util.cpp | 18 | ||||
| -rw-r--r-- | cmds/statsd/src/parse_util.h | 12 | ||||
| -rw-r--r-- | cmds/statsd/tests/LogEntryMatcher_test.cpp | 280 |
17 files changed, 868 insertions, 272 deletions
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk index 7cf5246b6830..e2e1a7f80266 100644 --- a/cmds/statsd/Android.mk +++ b/cmds/statsd/Android.mk @@ -54,6 +54,9 @@ LOCAL_SRC_FILES := \ src/statsd_config.proto \ src/DropboxReader.cpp \ src/matchers/LogEntryMatcherManager.cpp \ + src/metrics/CountMetricProducer.cpp \ + src/metrics/ConditionTracker.cpp \ + src/metrics/MetricsManager.cpp \ LOCAL_CFLAGS += \ diff --git a/cmds/statsd/src/DropboxWriter.h b/cmds/statsd/src/DropboxWriter.h index 6107685c187f..d72f1032744a 100644 --- a/cmds/statsd/src/DropboxWriter.h +++ b/cmds/statsd/src/DropboxWriter.h @@ -17,7 +17,8 @@ #ifndef DROPBOX_WRITER_H #define DROPBOX_WRITER_H -#include <frameworks/base/cmds/statsd/src/stats_log.pb.h> +#include <utils/RefBase.h> +#include "frameworks/base/cmds/statsd/src/stats_log.pb.h" using std::string; @@ -25,7 +26,7 @@ namespace android { namespace os { namespace statsd { -class DropboxWriter { +class DropboxWriter : public virtual RefBase { public: /* tag will be part of the file name, and used as the key to build the file index inside DropBoxManagerService. diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 280f9afcc66c..117fb5e2cefc 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -16,52 +16,74 @@ #include <StatsLogProcessor.h> +#include <cutils/log.h> +#include <frameworks/base/cmds/statsd/src/stats_log.pb.h> #include <log/log_event_list.h> +#include <metrics/CountMetricProducer.h> #include <parse_util.h> #include <utils/Errors.h> using namespace android; +using std::make_unique; +using std::unique_ptr; +using std::vector; namespace android { namespace os { namespace statsd { StatsLogProcessor::StatsLogProcessor() : m_dropbox_writer("all-logs") { - // Initialize the EventTagMap, which is how we know the names of the numeric event tags. - // If this fails, we can't print well, but something will print. - m_tags = android_openEventTagMap(NULL); - - // Printing format - m_format = android_log_format_new(); - android_log_setPrintFormat(m_format, FORMAT_THREADTIME); + // hardcoded config + // this should be called from StatsService when it receives a statsd_config + UpdateConfig(0, buildFakeConfig()); } StatsLogProcessor::~StatsLogProcessor() { - if (m_tags != NULL) { - android_closeEventTagMap(m_tags); - } - android_log_format_free(m_format); } +StatsdConfig StatsLogProcessor::buildFakeConfig() { + // HACK: Hard code a test metric for counting screen on events... + StatsdConfig config; + config.set_config_id(12345L); + + CountMetric* metric = config.add_count_metric(); + metric->set_metric_id(20150717L); + metric->set_what("SCREEN_IS_ON"); + metric->mutable_bucket()->set_bucket_size_millis(30 * 1000L); + + LogEntryMatcher* eventMatcher = config.add_log_entry_matcher(); + eventMatcher->set_name("SCREEN_IS_ON"); + + SimpleLogEntryMatcher* simpleLogEntryMatcher = eventMatcher->mutable_simple_log_entry_matcher(); + simpleLogEntryMatcher->add_tag(2 /*SCREEN_STATE_CHANGE*/); + simpleLogEntryMatcher->add_key_value_matcher()->mutable_key_matcher() + ->set_key(1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); + simpleLogEntryMatcher->mutable_key_value_matcher(0) + ->set_eq_int(2/*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/); + return config; +} + +// TODO: what if statsd service restarts? How do we know what logs are already processed before? void StatsLogProcessor::OnLogEvent(const log_msg& msg) { - status_t err; - AndroidLogEntry entry; - char buf[1024]; - - err = android_log_processBinaryLogBuffer(&(const_cast<log_msg*>(&msg)->entry_v1), &entry, - m_tags, buf, sizeof(buf)); - - // dump all statsd logs to dropbox for now. - // TODO: Add filtering, aggregation, etc. - if (err == NO_ERROR) { - EventMetricData eventMetricData = parse(msg); - m_dropbox_writer.addEventMetricData(eventMetricData); + // TODO: Use EventMetric to filter the events we want to log. + EventMetricData eventMetricData = parse(msg); + m_dropbox_writer.addEventMetricData(eventMetricData); + + // pass the event to metrics managers. + for (auto& pair : mMetricsManagers) { + pair.second->onLogEvent(msg); } } -void StatsLogProcessor::UpdateConfig(const int config_source, StatsdConfig config) { - m_configs[config_source] = config; +void StatsLogProcessor::UpdateConfig(const int config_source, const StatsdConfig& config) { + auto it = mMetricsManagers.find(config_source); + if (it != mMetricsManagers.end()) { + it->second->finish(); + } + ALOGD("Updated configuration for source %i", config_source); + + mMetricsManagers.insert({config_source, std::make_unique<MetricsManager>(config)}); } } // namespace statsd diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h index 4546d33fa2a1..88c63fa5a149 100644 --- a/cmds/statsd/src/StatsLogProcessor.h +++ b/cmds/statsd/src/StatsLogProcessor.h @@ -17,8 +17,13 @@ #define STATS_LOG_PROCESSOR_H #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" +#include "DropboxWriter.h" +#include "LogReader.h" +#include "metrics/MetricsManager.h" #include "parse_util.h" +#include <log/logprint.h> +#include <stdio.h> #include <unordered_map> namespace android { @@ -32,26 +37,15 @@ public: virtual void OnLogEvent(const log_msg& msg); - virtual void UpdateConfig(const int config_source, StatsdConfig config); + void UpdateConfig(const int config_source, const StatsdConfig& config); private: - /** - * Numeric to string tag name mapping. - */ - EventTagMap* m_tags; - - /** - * Pretty printing format. - */ - AndroidLogFormat* m_format; - + // TODO: use EventMetrics to log the events. DropboxWriter m_dropbox_writer; - /** - * Configs that have been specified, keyed by the source. This allows us to override the config - * from a source later. - */ - std::unordered_map<int, StatsdConfig> m_configs; + std::unordered_map<int, std::unique_ptr<MetricsManager>> mMetricsManagers; + + static StatsdConfig buildFakeConfig(); }; } // namespace statsd diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h index a956cbf83fd4..eb6aa49b0be1 100644 --- a/cmds/statsd/src/StatsService.h +++ b/cmds/statsd/src/StatsService.h @@ -24,7 +24,6 @@ #include <android/os/IStatsCompanionService.h> #include <binder/IResultReceiver.h> #include <binder/IShellCallback.h> -#include <frameworks/base/cmds/statsd/src/statsd_config.pb.h> #include <utils/Looper.h> #include <deque> diff --git a/cmds/statsd/src/matchers/LogEntryMatcherManager.cpp b/cmds/statsd/src/matchers/LogEntryMatcherManager.cpp index bb0951ce4fab..ab7b2b1dc57b 100644 --- a/cmds/statsd/src/matchers/LogEntryMatcherManager.cpp +++ b/cmds/statsd/src/matchers/LogEntryMatcherManager.cpp @@ -15,75 +15,147 @@ */ #include "LogEntryMatcherManager.h" +#include <cutils/log.h> #include <log/event_tag_map.h> +#include <log/log_event_list.h> #include <log/logprint.h> #include <utils/Errors.h> -#include <cutils/log.h> #include <unordered_map> -#include <frameworks/base/cmds/statsd/src/statsd_config.pb.h> +#include "frameworks/base/cmds/statsd/src/stats_log.pb.h" +#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" +#include "parse_util.h" -using std::unordered_map; +using std::set; using std::string; +using std::unordered_map; namespace android { namespace os { namespace statsd { -bool LogEntryMatcherManager::matches(const LogEntryMatcher &matcher, const int tagId, - const unordered_map<int, long> &intMap, - const unordered_map<int, string> &strMap, - const unordered_map<int, float> &floatMap, - const unordered_map<int, bool> &boolMap) { - if (matcher.has_combination()) { // Need to evaluate composite matching +LogEventWrapper LogEntryMatcherManager::parseLogEvent(log_msg msg) { + LogEventWrapper wrapper; + wrapper.timestamp_ns = msg.entry_v1.sec * NS_PER_SEC + msg.entry_v1.nsec; + wrapper.tagId = getTagId(msg); + + // start iterating k,v pairs. + android_log_context context = + create_android_log_parser(const_cast<log_msg*>(&msg)->msg() + sizeof(uint32_t), + const_cast<log_msg*>(&msg)->len() - sizeof(uint32_t)); + android_log_list_element elem; + + if (context) { + memset(&elem, 0, sizeof(elem)); + size_t index = 0; + int32_t key = -1; + do { + elem = android_log_read_next(context); + switch ((int)elem.type) { + case EVENT_TYPE_INT: + if (index % 2 == 0) { + key = elem.data.int32; + } else { + wrapper.intMap[key] = elem.data.int32; + } + index++; + break; + case EVENT_TYPE_FLOAT: + if (index % 2 == 1) { + wrapper.floatMap[key] = elem.data.float32; + } + index++; + break; + case EVENT_TYPE_STRING: + if (index % 2 == 1) { + wrapper.strMap[key] = elem.data.string; + } + index++; + break; + case EVENT_TYPE_LONG: + if (index % 2 == 1) { + wrapper.intMap[key] = elem.data.int64; + } + index++; + break; + case EVENT_TYPE_LIST: + break; + case EVENT_TYPE_LIST_STOP: + break; + case EVENT_TYPE_UNKNOWN: + break; + default: + elem.complete = true; + break; + } + + if (elem.complete) { + break; + } + } while ((elem.type != EVENT_TYPE_UNKNOWN) && !elem.complete); + + android_log_destroy(&context); + } + + return wrapper; +} + +bool LogEntryMatcherManager::matches(const LogEntryMatcher& matcher, const LogEventWrapper& event) { + const int tagId = event.tagId; + const unordered_map<int, long>& intMap = event.intMap; + const unordered_map<int, string>& strMap = event.strMap; + const unordered_map<int, float>& floatMap = event.floatMap; + const unordered_map<int, bool>& boolMap = event.boolMap; + + if (matcher.has_combination()) { // Need to evaluate composite matching switch (matcher.combination().operation()) { case LogicalOperation::AND: for (auto nestedMatcher : matcher.combination().matcher()) { - if (!matches(nestedMatcher, tagId, intMap, strMap, floatMap, boolMap)) { - return false; // return false if any nested matcher is false; + if (!matches(nestedMatcher, event)) { + return false; // return false if any nested matcher is false; } } - return true; // Otherwise, return true. + return true; // Otherwise, return true. case LogicalOperation::OR: for (auto nestedMatcher : matcher.combination().matcher()) { - if (matches(nestedMatcher, tagId, intMap, strMap, floatMap, boolMap)) { - return true; // return true if any nested matcher is true; + if (matches(nestedMatcher, event)) { + return true; // return true if any nested matcher is true; } } return false; case LogicalOperation::NOT: - return !matches(matcher.combination().matcher(0), tagId, intMap, strMap, floatMap, - boolMap); + return !matches(matcher.combination().matcher(0), event); // Case NAND is just inverting the return statement of AND case LogicalOperation::NAND: for (auto nestedMatcher : matcher.combination().matcher()) { auto simple = nestedMatcher.simple_log_entry_matcher(); - if (!matches(nestedMatcher, tagId, intMap, strMap, floatMap, boolMap)) { - return true; // return false if any nested matcher is false; + if (!matches(nestedMatcher, event)) { + return true; // return false if any nested matcher is false; } } - return false; // Otherwise, return true. + return false; // Otherwise, return true. case LogicalOperation::NOR: for (auto nestedMatcher : matcher.combination().matcher()) { - if (matches(nestedMatcher, tagId, intMap, strMap, floatMap, boolMap)) { - return false; // return true if any nested matcher is true; + if (matches(nestedMatcher, event)) { + return false; // return true if any nested matcher is true; } } return true; } return false; } else { - return matchesSimple(matcher.simple_log_entry_matcher(), tagId, intMap, strMap, floatMap, - boolMap); + return matchesSimple(matcher.simple_log_entry_matcher(), event); } } -bool LogEntryMatcherManager::matchesSimple(const SimpleLogEntryMatcher &simpleMatcher, - const int tagId, - const unordered_map<int, long> &intMap, - const unordered_map<int, string> &strMap, - const unordered_map<int, float> &floatMap, - const unordered_map<int, bool> &boolMap) { +bool LogEntryMatcherManager::matchesSimple(const SimpleLogEntryMatcher& simpleMatcher, + const LogEventWrapper& event) { + const int tagId = event.tagId; + const unordered_map<int, long>& intMap = event.intMap; + const unordered_map<int, string>& strMap = event.strMap; + const unordered_map<int, float>& floatMap = event.floatMap; + const unordered_map<int, bool>& boolMap = event.boolMap; + for (int i = 0; i < simpleMatcher.tag_size(); i++) { if (simpleMatcher.tag(i) != tagId) { continue; @@ -177,6 +249,26 @@ bool LogEntryMatcherManager::matchesSimple(const SimpleLogEntryMatcher &simpleMa return false; } -} // namespace statsd -} // namespace os -} // namespace android +set<int> LogEntryMatcherManager::getTagIdsFromMatcher(const LogEntryMatcher& matcher) { + set<int> result; + switch (matcher.contents_case()) { + case LogEntryMatcher::kCombination: + for (auto sub_matcher : matcher.combination().matcher()) { + set<int> tagSet = getTagIdsFromMatcher(sub_matcher); + result.insert(tagSet.begin(), tagSet.end()); + } + break; + case LogEntryMatcher::kSimpleLogEntryMatcher: + for (int i = 0; i < matcher.simple_log_entry_matcher().tag_size(); i++) { + result.insert(matcher.simple_log_entry_matcher().tag(i)); + } + break; + case LogEntryMatcher::CONTENTS_NOT_SET: + break; + } + return result; +} + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/matchers/LogEntryMatcherManager.h b/cmds/statsd/src/matchers/LogEntryMatcherManager.h index 10ac0e2e9145..fc8e6a1378a7 100644 --- a/cmds/statsd/src/matchers/LogEntryMatcherManager.h +++ b/cmds/statsd/src/matchers/LogEntryMatcherManager.h @@ -17,20 +17,30 @@ #ifndef LOG_ENTRY_MATCHER_MANAGER_H #define LOG_ENTRY_MATCHER_MANAGER_H -#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" -#include <log/logprint.h> #include <log/log_read.h> +#include <log/logprint.h> #include <set> -#include <vector> #include <unordered_map> +#include <vector> +#include "frameworks/base/cmds/statsd/src/stats_log.pb.h" +#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" -using std::unordered_map; using std::string; +using std::unordered_map; namespace android { namespace os { namespace statsd { +typedef struct { + int tagId; + long timestamp_ns; + std::unordered_map<int, long> intMap; + std::unordered_map<int, std::string> strMap; + std::unordered_map<int, bool> boolMap; + std::unordered_map<int, float> floatMap; +} LogEventWrapper; + /** * Keeps track per log entry which simple log entry matchers match. */ @@ -38,23 +48,19 @@ class LogEntryMatcherManager { public: LogEntryMatcherManager(); - ~LogEntryMatcherManager() {}; + ~LogEntryMatcherManager(){}; + + static LogEventWrapper parseLogEvent(log_msg msg); + + static std::set<int> getTagIdsFromMatcher(const LogEntryMatcher& matcher); - static bool matches(const LogEntryMatcher &matcher, const int tagId, - const unordered_map<int, long> &intMap, - const unordered_map<int, string> &strMap, - const unordered_map<int, float> &floatMap, - const unordered_map<int, bool> &boolMap); + static bool matches(const LogEntryMatcher& matcher, const LogEventWrapper& wrapper); - static bool matchesSimple(const SimpleLogEntryMatcher &simpleMatcher, - const int tagId, - const unordered_map<int, long> &intMap, - const unordered_map<int, string> &strMap, - const unordered_map<int, float> &floatMap, - const unordered_map<int, bool> &boolMap); + static bool matchesSimple(const SimpleLogEntryMatcher& simpleMatcher, + const LogEventWrapper& wrapper); }; -} // namespace statsd -} // namespace os -} // namespace android -#endif //LOG_ENTRY_MATCHER_MANAGER_H +} // namespace statsd +} // namespace os +} // namespace android +#endif // LOG_ENTRY_MATCHER_MANAGER_H diff --git a/cmds/statsd/src/metrics/ConditionTracker.cpp b/cmds/statsd/src/metrics/ConditionTracker.cpp new file mode 100644 index 000000000000..684ffdb5883a --- /dev/null +++ b/cmds/statsd/src/metrics/ConditionTracker.cpp @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#define LOG_TAG "ConditionTracker" +#define DEBUG true // STOPSHIP if true +#define VLOG(...) \ + if (DEBUG) ALOGD(__VA_ARGS__); + +#include "ConditionTracker.h" +#include <cutils/log.h> + +namespace android { +namespace os { +namespace statsd { + +ConditionTracker::ConditionTracker() : mIsConditionMet(true) { + VLOG("ConditionTracker()"); +} + +ConditionTracker::ConditionTracker(const Condition& condition) + : mCondition(condition), mIsConditionMet(true) { + VLOG("ConditionTracker()"); +} + +ConditionTracker::~ConditionTracker() { + VLOG("~ConditionTracker()"); +} + +void ConditionTracker::evaluateCondition(const LogEventWrapper& event) { + // modify condition. + VLOG("evaluateCondition"); +} + +bool ConditionTracker::isConditionMet() const { + VLOG("isConditionMet() %d", mIsConditionMet); + return mIsConditionMet; +} + +} // namespace statsd +} // namespace os +} // namespace android
\ No newline at end of file diff --git a/cmds/statsd/src/metrics/ConditionTracker.h b/cmds/statsd/src/metrics/ConditionTracker.h new file mode 100644 index 000000000000..b94d5abc2cf5 --- /dev/null +++ b/cmds/statsd/src/metrics/ConditionTracker.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef CONDITION_TRACKER_H +#define CONDITION_TRACKER_H + +#include <utils/RefBase.h> +#include "../matchers/LogEntryMatcherManager.h" +#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" + +namespace android { +namespace os { +namespace statsd { + +class ConditionTracker : public RefBase { +public: + ConditionTracker(); + + ConditionTracker(const Condition& condition); + + ~ConditionTracker(); + + void evaluateCondition(const LogEventWrapper& event); + + bool isConditionMet() const; + +private: + // this is the definition of the Condition. + Condition mCondition; + + bool mIsConditionMet; +}; + +} // namespace statsd +} // namespace os +} // namespace android + +#endif // CONDITION_TRACKER_H diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp new file mode 100644 index 000000000000..fbd013ebf528 --- /dev/null +++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp @@ -0,0 +1,107 @@ +/* + * 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. + */ + +#define LOG_TAG "CountMetric" +#define DEBUG true // STOPSHIP if true +#define VLOG(...) \ + if (DEBUG) ALOGD(__VA_ARGS__); + +#include "CountMetricProducer.h" +#include "parse_util.h" + +#include <cutils/log.h> +#include <limits.h> +#include <stdlib.h> + +using std::unordered_map; + +namespace android { +namespace os { +namespace statsd { + +CountMetricProducer::CountMetricProducer(const CountMetric& metric, + const sp<ConditionTracker> condition) + : mMetric(metric), + mConditionTracker(condition), + mStartTime(std::time(nullptr)), + mCounter(0), + mCurrentBucketStartTime(mStartTime) { + // TODO: evaluate initial conditions. and set mConditionMet. + if (metric.has_bucket() && metric.bucket().has_bucket_size_millis()) { + mBucketSize_sec = metric.bucket().bucket_size_millis() / 1000; + } else { + mBucketSize_sec = LONG_MAX; + } + + VLOG("created. bucket size %lu start_time: %lu", mBucketSize_sec, mStartTime); +} + +CountMetricProducer::CountMetricProducer(const CountMetric& metric) + : CountMetricProducer(metric, new ConditionTracker()) { +} + +CountMetricProducer::~CountMetricProducer() { + VLOG("~CountMetricProducer() called"); +} + +void CountMetricProducer::finish() { + // TODO: write the StatsLogReport to dropbox using + // DropboxWriter. + onDumpReport(); +} + +void CountMetricProducer::onDumpReport() { + VLOG("dump report now..."); +} + +void CountMetricProducer::onMatchedLogEvent(const LogEventWrapper& event) { + time_t eventTime = event.timestamp_ns / 1000000000; + + // this is old event, maybe statsd restarted? + if (eventTime < mStartTime) { + return; + } + + if (mConditionTracker->isConditionMet()) { + flushCounterIfNeeded(eventTime); + mCounter++; + } +} + +// When a new matched event comes in, we check if it falls into the current bucket. And flush the +// counter to the StatsLogReport and adjust the bucket if needed. +void CountMetricProducer::flushCounterIfNeeded(const time_t& eventTime) { + if (mCurrentBucketStartTime + mBucketSize_sec > eventTime) { + return; + } + + // TODO: add a KeyValuePair to StatsLogReport. + ALOGD("CountMetric: dump counter %d", mCounter); + + // reset counter + mCounter = 0; + + // adjust the bucket start time + mCurrentBucketStartTime = + mCurrentBucketStartTime + + ((eventTime - mCurrentBucketStartTime) / mBucketSize_sec) * mBucketSize_sec; + + VLOG("new bucket start time: %lu", mCurrentBucketStartTime); +} + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h new file mode 100644 index 000000000000..766579166972 --- /dev/null +++ b/cmds/statsd/src/metrics/CountMetricProducer.h @@ -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. + */ + +#ifndef COUNT_METRIC_PRODUCER_H +#define COUNT_METRIC_PRODUCER_H + +#include <mutex> +#include <thread> +#include <unordered_map> +#include "../matchers/LogEntryMatcherManager.h" +#include "ConditionTracker.h" +#include "DropboxWriter.h" +#include "MetricProducer.h" +#include "frameworks/base/cmds/statsd/src/stats_log.pb.h" +#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" + +namespace android { +namespace os { +namespace statsd { + +class CountMetricProducer : public MetricProducer { +public: + CountMetricProducer(const CountMetric& countMetric, const sp<ConditionTracker> condition); + + CountMetricProducer(const CountMetric& countMetric); + + virtual ~CountMetricProducer(); + + void onMatchedLogEvent(const LogEventWrapper& event) override; + + void finish() override; + + void onDumpReport() override; + +private: + const CountMetric mMetric; + + const sp<ConditionTracker> mConditionTracker; + + const time_t mStartTime; + // TODO: Add dimensions. + int mCounter; + + time_t mCurrentBucketStartTime; + + long mBucketSize_sec; + + void flushCounterIfNeeded(const time_t& newEventTime); +}; + +} // namespace statsd +} // namespace os +} // namespace android +#endif // COUNT_METRIC_PRODUCER_H diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h new file mode 100644 index 000000000000..44a778b3d903 --- /dev/null +++ b/cmds/statsd/src/metrics/MetricProducer.h @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#ifndef METRIC_PRODUCER_H +#define METRIC_PRODUCER_H + +#include <log/logprint.h> +#include "../matchers/LogEntryMatcherManager.h" + +namespace android { +namespace os { +namespace statsd { + +// A MetricProducer is responsible for compute one single metrics, creating stats log report, and +// writing the report to dropbox. +class MetricProducer { +public: + virtual ~MetricProducer(){}; + + // Consume the stats log if it's interesting to this metric. + virtual void onMatchedLogEvent(const LogEventWrapper& event) = 0; + + // This is called when the metric collecting is done, e.g., when there is a new configuration + // coming. MetricProducer should do the clean up, and dump existing data to dropbox. + virtual void finish() = 0; + + virtual void onDumpReport() = 0; +}; + +} // namespace statsd +} // namespace os +} // namespace android +#endif // METRIC_PRODUCER_H diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp new file mode 100644 index 000000000000..cb7420683380 --- /dev/null +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -0,0 +1,132 @@ +/* + * 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. + */ +#define LOG_TAG "MetricManager" +#define DEBUG true // STOPSHIP if true +#define VLOG(...) \ + if (DEBUG) ALOGD(__VA_ARGS__); + +#include "MetricsManager.h" +#include <cutils/log.h> +#include <log/logprint.h> +#include "CountMetricProducer.h" +#include "parse_util.h" + +using std::make_unique; +using std::set; +using std::string; +using std::unique_ptr; +using std::unordered_map; +using std::vector; + +namespace android { +namespace os { +namespace statsd { + +MetricsManager::MetricsManager(const StatsdConfig& config) : mConfig(config), mLogMatchers() { + std::unordered_map<string, LogEntryMatcher> matcherMap; + std::unordered_map<string, sp<ConditionTracker>> conditionMap; + + for (int i = 0; i < config.log_entry_matcher_size(); i++) { + const LogEntryMatcher& logMatcher = config.log_entry_matcher(i); + mMatchers.push_back(logMatcher); + + matcherMap[config.log_entry_matcher(i).name()] = logMatcher; + + mLogMatchers[logMatcher.name()] = vector<unique_ptr<MetricProducer>>(); + // Collect all the tag ids that are interesting + set<int> tagIds = LogEntryMatcherManager::getTagIdsFromMatcher(logMatcher); + + mTagIds.insert(tagIds.begin(), tagIds.end()); + } + + for (int i = 0; i < config.condition_size(); i++) { + const Condition& condition = config.condition(i); + conditionMap[condition.name()] = new ConditionTracker(condition); + } + + // Build MetricProducers for each metric defined in config. + // (1) build CountMetricProducer + for (int i = 0; i < config.count_metric_size(); i++) { + const CountMetric& metric = config.count_metric(i); + auto it = mLogMatchers.find(metric.what()); + if (it == mLogMatchers.end()) { + ALOGW("cannot find the LogEntryMatcher %s in config", metric.what().c_str()); + continue; + } + + if (metric.has_condition()) { + auto condition_it = conditionMap.find(metric.condition()); + if (condition_it == conditionMap.end()) { + ALOGW("cannot find the Condition %s in the config", metric.condition().c_str()); + continue; + } + it->second.push_back(make_unique<CountMetricProducer>(metric, condition_it->second)); + } else { + it->second.push_back(make_unique<CountMetricProducer>(metric)); + } + } + + // TODO: build other types of metrics too. +} + +MetricsManager::~MetricsManager() { + VLOG("~MetricManager()"); +} + +void MetricsManager::finish() { + for (auto const& entryPair : mLogMatchers) { + for (auto const& metric : entryPair.second) { + metric->finish(); + } + } +} + +// Consume the stats log if it's interesting to this metric. +void MetricsManager::onLogEvent(const log_msg& logMsg) { + int tagId = getTagId(logMsg); + if (mTagIds.find(tagId) == mTagIds.end()) { + // not interesting... + return; + } + // Since at least one of the metrics is interested in this event, we parse it now. + LogEventWrapper event = LogEntryMatcherManager::parseLogEvent(logMsg); + + // Evaluate the conditions. Order matters, this should happen + // before sending the event to metrics + for (auto& condition : mConditionTracker) { + condition->evaluateCondition(event); + } + + // Now find out which LogMatcher matches this event, and let relevant metrics know. + for (auto matcher : mMatchers) { + if (LogEntryMatcherManager::matches(matcher, event)) { + auto it = mLogMatchers.find(matcher.name()); + if (it != mLogMatchers.end()) { + for (auto const& it2 : it->second) { + // Only metrics that matches this event get notified. + it2->onMatchedLogEvent(event); + } + } else { + // TODO: we should remove any redundant matchers that the config provides. + ALOGW("Matcher not used by any metrics."); + } + } + } +} + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h new file mode 100644 index 000000000000..77d7535a1ba1 --- /dev/null +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -0,0 +1,64 @@ +/* + * 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. + */ + +#ifndef METRICS_MANAGER_H +#define METRICS_MANAGER_H + +#include <cutils/log.h> +#include <log/logprint.h> +#include <unordered_map> +#include "../matchers/LogEntryMatcherManager.h" +#include "ConditionTracker.h" +#include "MetricProducer.h" +#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" + +namespace android { +namespace os { +namespace statsd { + +// A MetricsManager is responsible for managing metrics from one single config source. +class MetricsManager { +public: + MetricsManager(const StatsdConfig& config); + + ~MetricsManager(); + + // Consume the stats log if it's interesting to this metric. + void onLogEvent(const log_msg& logMsg); + + void finish(); + +private: + const StatsdConfig mConfig; + + // All event tags that are interesting to my metrics. + std::set<int> mTagIds; + + // The matchers that my metrics share. + std::vector<LogEntryMatcher> mMatchers; + + // The conditions that my metrics share. + std::vector<sp<ConditionTracker>> mConditionTracker; + + // the map from LogEntryMatcher names to the metrics that use this matcher. + std::unordered_map<std::string, std::vector<std::unique_ptr<MetricProducer>>> mLogMatchers; +}; + +} // namespace statsd +} // namespace os +} // namespace android + +#endif // METRICS_MANAGER_H diff --git a/cmds/statsd/src/parse_util.cpp b/cmds/statsd/src/parse_util.cpp index 408a65c77ed2..61421880efd6 100644 --- a/cmds/statsd/src/parse_util.cpp +++ b/cmds/statsd/src/parse_util.cpp @@ -17,22 +17,25 @@ #include <log/log_event_list.h> #include <parse_util.h> -using android::os::statsd::EventMetricData; -using android::os::statsd::KeyValuePair; +namespace android { +namespace os { +namespace statsd { static inline uint32_t get4LE(const char* src) { return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); } -EventMetricData parse(log_msg msg) -{ +int getTagId(log_msg msg) { + return get4LE(msg.msg()); +} + +EventMetricData parse(log_msg msg) { // dump all statsd logs to dropbox for now. // TODO: Add filtering, aggregation, etc. EventMetricData eventMetricData; // set tag. - char* eventData = msg.msg(); - uint32_t tag = get4LE(eventData); + int tag = getTagId(msg); // TODO: Replace the following line when we can serialize on the fly. //eventMetricData.set_tag(tag); @@ -124,3 +127,6 @@ EventMetricData parse(log_msg msg) return eventMetricData; } +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/parse_util.h b/cmds/statsd/src/parse_util.h index e9f4c2735cea..8b82e7bc15a7 100644 --- a/cmds/statsd/src/parse_util.h +++ b/cmds/statsd/src/parse_util.h @@ -21,8 +21,16 @@ #include <log/logprint.h> -using android::os::statsd::EventMetricData; +namespace android { +namespace os { +namespace statsd { -EventMetricData parse(const log_msg msg); +EventMetricData parse(log_msg msg); + +int getTagId(log_msg msg); + +} // namespace statsd +} // namespace os +} // namespace android #endif // PARSE_UTIL_H diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp index 81d93b62eb56..473704a7e7b9 100644 --- a/cmds/statsd/tests/LogEntryMatcher_test.cpp +++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp @@ -14,13 +14,13 @@ #define LOG_TAG "statsd_test" -#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" +#include <gtest/gtest.h> +#include <log/log_event_list.h> +#include <log/log_read.h> +#include <log/logprint.h> #include "../src/matchers/LogEntryMatcherManager.h" #include "../src/parse_util.h" -#include <log/logprint.h> -#include <log/log_read.h> -#include <log/log_event_list.h> -#include <gtest/gtest.h> +#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" #include <stdio.h> @@ -38,12 +38,10 @@ TEST(LogEntryMatcherTest, TestSimpleMatcher) { auto simpleMatcher = matcher.mutable_simple_log_entry_matcher(); simpleMatcher->add_tag(kTagIdWakelock); - unordered_map<int, long> intMap; - unordered_map<int, string> strMap; - unordered_map<int, float> floatMap; - unordered_map<int, bool> boolMap; + LogEventWrapper wrapper; + wrapper.tagId = kTagIdWakelock; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, boolMap)); + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); } TEST(LogEntryMatcherTest, TestBoolMatcher) { @@ -54,24 +52,18 @@ TEST(LogEntryMatcherTest, TestBoolMatcher) { auto keyValue = simpleMatcher->add_key_value_matcher(); keyValue->mutable_key_matcher()->set_key(kKeyIdState); - - unordered_map<int, long> intMap; - unordered_map<int, string> strMap; - unordered_map<int, float> floatMap; - unordered_map<int, bool> boolMap; + LogEventWrapper wrapper; + wrapper.tagId = kTagIdWakelock; keyValue->set_eq_bool(true); - boolMap[kKeyIdState] = true; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); + wrapper.boolMap[kKeyIdState] = true; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); keyValue->set_eq_bool(false); - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); - boolMap[kKeyIdState] = false; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); + wrapper.boolMap[kTagIdWakelock] = false; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); } TEST(LogEntryMatcherTest, TestStringMatcher) { @@ -83,14 +75,12 @@ TEST(LogEntryMatcherTest, TestStringMatcher) { keyValue->mutable_key_matcher()->set_key(kKeyIdState); keyValue->set_eq_string("wakelock_name"); - unordered_map<int, long> intMap; - unordered_map<int, string> strMap; - unordered_map<int, float> floatMap; - unordered_map<int, bool> boolMap; + LogEventWrapper wrapper; + wrapper.tagId = kTagIdWakelock; - strMap[kKeyIdState] = "wakelock_name"; + wrapper.strMap[kKeyIdState] = "wakelock_name"; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, boolMap)); + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); } TEST(LogEntryMatcherTest, TestIntComparisonMatcher) { @@ -101,32 +91,24 @@ TEST(LogEntryMatcherTest, TestIntComparisonMatcher) { auto keyValue = simpleMatcher->add_key_value_matcher(); keyValue->mutable_key_matcher()->set_key(kKeyIdState); - unordered_map<int, long> intMap; - unordered_map<int, string> strMap; - unordered_map<int, float> floatMap; - unordered_map<int, bool> boolMap; + LogEventWrapper wrapper; + wrapper.tagId = kTagIdWakelock; keyValue->set_lt_int(10); - intMap[kKeyIdState] = 11; - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); - intMap[kKeyIdState] = 10; - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); - intMap[kKeyIdState] = 9; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); + wrapper.intMap[kKeyIdState] = 11; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap[kKeyIdState] = 10; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap[kKeyIdState] = 9; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); keyValue->set_gt_int(10); - intMap[kKeyIdState] = 11; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); - intMap[kKeyIdState] = 10; - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); - intMap[kKeyIdState] = 9; - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); + wrapper.intMap[kKeyIdState] = 11; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap[kKeyIdState] = 10; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap[kKeyIdState] = 9; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); } TEST(LogEntryMatcherTest, TestIntWithEqualityComparisonMatcher) { @@ -137,32 +119,24 @@ TEST(LogEntryMatcherTest, TestIntWithEqualityComparisonMatcher) { auto keyValue = simpleMatcher->add_key_value_matcher(); keyValue->mutable_key_matcher()->set_key(kKeyIdState); - unordered_map<int, long> intMap; - unordered_map<int, string> strMap; - unordered_map<int, float> floatMap; - unordered_map<int, bool> boolMap; + LogEventWrapper wrapper; + wrapper.tagId = kTagIdWakelock; keyValue->set_lte_int(10); - intMap[kKeyIdState] = 11; - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); - intMap[kKeyIdState] = 10; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); - intMap[kKeyIdState] = 9; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); + wrapper.intMap[kKeyIdState] = 11; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap[kKeyIdState] = 10; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap[kKeyIdState] = 9; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); keyValue->set_gte_int(10); - intMap[kKeyIdState] = 11; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); - intMap[kKeyIdState] = 10; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); - intMap[kKeyIdState] = 9; - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); + wrapper.intMap[kKeyIdState] = 11; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap[kKeyIdState] = 10; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap[kKeyIdState] = 9; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); } TEST(LogEntryMatcherTest, TestFloatComparisonMatcher) { @@ -173,26 +147,20 @@ TEST(LogEntryMatcherTest, TestFloatComparisonMatcher) { auto keyValue = simpleMatcher->add_key_value_matcher(); keyValue->mutable_key_matcher()->set_key(kKeyIdState); - unordered_map<int, long> intMap; - unordered_map<int, string> strMap; - unordered_map<int, float> floatMap; - unordered_map<int, bool> boolMap; + LogEventWrapper wrapper; + wrapper.tagId = kTagIdWakelock; keyValue->set_lt_float(10.0); - floatMap[kKeyIdState] = 10.1; - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); - floatMap[kKeyIdState] = 9.9; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); + wrapper.floatMap[kKeyIdState] = 10.1; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.floatMap[kKeyIdState] = 9.9; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); keyValue->set_gt_float(10.0); - floatMap[kKeyIdState] = 10.1; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); - floatMap[kKeyIdState] = 9.9; - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, - floatMap, boolMap)); + wrapper.floatMap[kKeyIdState] = 10.1; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.floatMap[kKeyIdState] = 9.9; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); } // Helper for the composite matchers. @@ -209,23 +177,23 @@ TEST(LogEntryMatcherTest, TestAndMatcher) { auto combination = matcher.mutable_combination(); combination->set_operation(LogicalOperation::AND); - addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), kTagIdWakelock, kKeyIdState, 3); - addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), kTagIdWakelock, kKeyIdPackageVersion, 4); - - unordered_map<int, long> intMap; - unordered_map<int, string> strMap; - unordered_map<int, float> floatMap; - unordered_map<int, bool> boolMap; - - intMap[kKeyIdPackageVersion] = 4; - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, boolMap)); - intMap.clear(); - intMap[kKeyIdState] = 3; - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, boolMap)); - intMap.clear(); - intMap[kKeyIdState] = 3; - intMap[kKeyIdPackageVersion] = 4; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, boolMap)); + addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), + kTagIdWakelock, kKeyIdState, 3); + addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), + kTagIdWakelock, kKeyIdPackageVersion, 4); + + LogEventWrapper wrapper; + wrapper.tagId = kTagIdWakelock; + + wrapper.intMap[1003] = 4; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap.clear(); + wrapper.intMap[1] = 3; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap.clear(); + wrapper.intMap[1] = 3; + wrapper.intMap[1003] = 4; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); } TEST(LogEntryMatcherTest, TestOrMatcher) { @@ -239,26 +207,20 @@ TEST(LogEntryMatcherTest, TestOrMatcher) { addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), kTagIdWakelock, kKeyIdPackageVersion, 4); - unordered_map<int, long> intMap; - unordered_map<int, string> strMap; - unordered_map<int, float> floatMap; - unordered_map<int, bool> boolMap; + LogEventWrapper wrapper; + wrapper.tagId = kTagIdWakelock; // Don't set any key-value pairs. - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); - intMap[kKeyIdPackageVersion] = 4; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); - intMap.clear(); - intMap[kKeyIdState] = 3; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); - intMap.clear(); - intMap[kKeyIdState] = 3; - intMap[kKeyIdPackageVersion] = 4; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap[1003] = 4; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap.clear(); + wrapper.intMap[1] = 3; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap.clear(); + wrapper.intMap[1] = 3; + wrapper.intMap[1003] = 4; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); } TEST(LogEntryMatcherTest, TestNotMatcher) { @@ -271,15 +233,12 @@ TEST(LogEntryMatcherTest, TestNotMatcher) { addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), kTagIdWakelock, kKeyIdState, 3); - unordered_map<int, long> intMap; - unordered_map<int, string> strMap; - unordered_map<int, float> floatMap; - unordered_map<int, bool> boolMap; + LogEventWrapper wrapper; + wrapper.tagId = kTagIdWakelock; // Don't set any key-value pairs. - intMap[kKeyIdState] = 3; - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); + wrapper.intMap[kKeyIdState] = 3; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); } TEST(LogEntryMatcherTest, TestNANDMatcher) { @@ -293,20 +252,15 @@ TEST(LogEntryMatcherTest, TestNANDMatcher) { addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), kTagIdWakelock, kKeyIdPackageVersion, 4); - unordered_map<int, long> intMap; - unordered_map<int, string> strMap; - unordered_map<int, float> floatMap; - unordered_map<int, bool> boolMap; + LogEventWrapper wrapper; + wrapper.tagId = kTagIdWakelock; // Don't set any key-value pairs. - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); - intMap[kKeyIdState] = 3; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); - intMap[kKeyIdPackageVersion] = 4; - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap[kKeyIdState] = 3; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap[kKeyIdPackageVersion] = 4; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); } TEST(LogEntryMatcherTest, TestNORMatcher) { @@ -320,20 +274,15 @@ TEST(LogEntryMatcherTest, TestNORMatcher) { addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), kTagIdWakelock, kKeyIdPackageVersion, 4); - unordered_map<int, long> intMap; - unordered_map<int, string> strMap; - unordered_map<int, float> floatMap; - unordered_map<int, bool> boolMap; + LogEventWrapper wrapper; + wrapper.tagId = kTagIdWakelock; // Don't set any key-value pairs. - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); - intMap[kKeyIdState] = 3; - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); - intMap[kKeyIdPackageVersion] = 4; - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap[kKeyIdState] = 3; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap[kKeyIdPackageVersion] = 4; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); } // Tests that a NOT on top of AND is the same as NAND @@ -350,22 +299,17 @@ TEST(LogEntryMatcherTest, TestMultipleLayerMatcher) { addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), kTagIdWakelock, kKeyIdPackageVersion, 4); - unordered_map<int, long> intMap; - unordered_map<int, string> strMap; - unordered_map<int, float> floatMap; - unordered_map<int, bool> boolMap; + LogEventWrapper wrapper; + wrapper.tagId = kTagIdWakelock; // Don't set any key-value pairs. - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); - intMap[kKeyIdState] = 3; - EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); - intMap[kKeyIdPackageVersion] = 4; - EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, kTagIdWakelock, intMap, strMap, floatMap, - boolMap)); + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap[kKeyIdState] = 3; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, wrapper)); + wrapper.intMap[kKeyIdPackageVersion] = 4; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, wrapper)); } #else - GTEST_LOG_(INFO) << "This test does nothing.\n"; +GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif |