Add metric computation skeleton to statsd.
This cl is to let statsd understand statsd_config, and compute metrics
defined in the config.
+ StatsLogProcessor is given a StatsdConfig (hard coded right now).
We construct a MetricProducer for each of the metric, and the metrics
share Condition and LogEntryMatchers
+ Added the CountMetricProducer type for CountMetric.
We can now count times of SCREEN_ON events given a config.
TODO: 1) conditions are not implemented.
2) slicings are not implemented in CountMetric
3) move the interaction to dropbox to a separate thread
4) decide how the in memory metrics would be used by anomaly detection
Test: manual test.
$ adb shell /system/bin/statsd
$ cat config_file.dat | adb shell cmd stats config
Change-Id: I38f4059c0dc5a827c338131d4a6fa7d4cbe865db
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 280f9af..117fb5e 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];
+ // TODO: Use EventMetric to filter the events we want to log.
+ EventMetricData eventMetricData = parse(msg);
+ m_dropbox_writer.addEventMetricData(eventMetricData);
- 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);
+ // 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