diff options
| author | 2017-09-06 12:53:50 -0700 | |
|---|---|---|
| committer | 2017-09-13 16:58:40 -0700 | |
| commit | ab273e2e13f87d57f66395c52df424710b8066e1 (patch) | |
| tree | 822a1160eb1cdb41800f4b65fd2237a58ff23e67 | |
| parent | 175b19b53ce65aea6fc2c2fa71a44f336f8a7b1a (diff) | |
Add a DropboxWriter in statsd.
+ The DropboxWriter keeps data in cache, and flush to files once the
size exceeds the maximum value.
+ Different components should create their owner DropboxWriter with
different tags, e.g., anomly detection, experiment metrics, etc.
+ Copied stats_log related protos from g3
Test: run statsd, and adb shell dumpsys dropbox
Will add unit tests.
Change-Id: If06e9a9953be32082252b340a97124d732656b40
| -rw-r--r-- | cmds/statsd/Android.mk | 37 | ||||
| -rw-r--r-- | cmds/statsd/src/DropboxWriter.cpp | 61 | ||||
| -rw-r--r-- | cmds/statsd/src/DropboxWriter.h | 66 | ||||
| -rw-r--r-- | cmds/statsd/src/StatsLogProcessor.cpp | 68 | ||||
| -rw-r--r-- | cmds/statsd/src/StatsLogProcessor.h | 46 | ||||
| -rw-r--r-- | cmds/statsd/src/main.cpp | 6 | ||||
| -rw-r--r-- | cmds/statsd/src/stats_constants.proto | 31 | ||||
| -rw-r--r-- | cmds/statsd/src/stats_log.proto | 77 | ||||
| -rw-r--r-- | cmds/statsd/src/statsd_config.proto | 449 |
9 files changed, 833 insertions, 8 deletions
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk index db8c89dafaba..0e6d29206cd1 100644 --- a/cmds/statsd/Android.mk +++ b/cmds/statsd/Android.mk @@ -14,6 +14,23 @@ LOCAL_PATH:= $(call my-dir) +# ================ +# proto static lib +# ================ +include $(CLEAR_VARS) + +LOCAL_MODULE := statsd_proto +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-proto-files-under, src) + +LOCAL_PROTOC_FLAGS := +LOCAL_PROTOC_OPTIMIZE_TYPE := lite + +include $(BUILD_STATIC_LIBRARY) + +STATSD_PROTO_INCLUDES := $(local-generated-sources-dir)/src/$(LOCAL_PATH) + # ========= # statsd # ========= @@ -27,7 +44,12 @@ LOCAL_SRC_FILES := \ src/StatsService.cpp \ src/LogEntryPrinter.cpp \ src/LogReader.cpp \ - src/main.cpp + src/main.cpp \ + src/DropboxWriter.cpp \ + src/StatsLogProcessor.cpp \ + src/stats_log.proto \ + src/statsd_config.proto \ + src/stats_constants.proto \ LOCAL_CFLAGS += \ -Wall \ @@ -47,7 +69,10 @@ else endif LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/../../core/java -LOCAL_C_INCLUDES += $(LOCAL_PATH)/src +LOCAL_C_INCLUDES += $(LOCAL_PATH)/src \ + STATSD_PROTO_INCLUDES + +LOCAL_STATIC_LIBRARIES := statsd_proto LOCAL_SHARED_LIBRARIES := \ libbase \ @@ -56,7 +81,8 @@ LOCAL_SHARED_LIBRARIES := \ libincident \ liblog \ libselinux \ - libutils + libutils \ + libservices \ LOCAL_MODULE_CLASS := EXECUTABLES @@ -82,7 +108,8 @@ LOCAL_CFLAGS += \ -Wno-unused-function \ -Wno-unused-parameter -LOCAL_C_INCLUDES += $(LOCAL_PATH)/src +LOCAL_C_INCLUDES += $(LOCAL_PATH)/src \ + STATSD_PROTO_INCLUDES LOCAL_SRC_FILES := \ ../../core/java/android/os/IStatsManager.aidl \ @@ -93,6 +120,7 @@ LOCAL_SRC_FILES := \ LOCAL_STATIC_LIBRARIES := \ libgmock \ + statsd_proto LOCAL_SHARED_LIBRARIES := \ libbase \ @@ -103,4 +131,3 @@ LOCAL_SHARED_LIBRARIES := \ libutils include $(BUILD_NATIVE_TEST) - diff --git a/cmds/statsd/src/DropboxWriter.cpp b/cmds/statsd/src/DropboxWriter.cpp new file mode 100644 index 000000000000..a251056d9e81 --- /dev/null +++ b/cmds/statsd/src/DropboxWriter.cpp @@ -0,0 +1,61 @@ +/* + * 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 <android/os/DropBoxManager.h> +#include <cutils/log.h> + +#include "DropboxWriter.h" + +using android::os::DropBoxManager; +using android::binder::Status; +using android::sp; +using android::String16; +using std::vector; + +DropboxWriter::DropboxWriter(const string& tag) + : mTag(tag), mLogList(), mBufferSize(0) { +} + +void DropboxWriter::addEntry(const StatsLogEntry& entry) { + flushIfNecessary(entry); + StatsLogEntry* newEntry = mLogList.add_stats_log_entry(); + newEntry->CopyFrom(entry); + mBufferSize += entry.ByteSize(); +} + +void DropboxWriter::flushIfNecessary(const StatsLogEntry& entry) { + // The serialized size of the StatsLogList is approximately the sum of the serialized size of + // every StatsLogEntry inside it. + if (entry.ByteSize() + mBufferSize > kMaxSerializedBytes) { + flush(); + } +} + +void DropboxWriter::flush() { + // now we get an exact byte size of the output + const int numBytes = mLogList.ByteSize(); + vector<uint8_t> buffer(numBytes); + sp<DropBoxManager> dropbox = new DropBoxManager(); + mLogList.SerializeToArray(&buffer[0], numBytes); + Status status = dropbox->addData(String16(mTag.c_str()), &buffer[0], + numBytes, 0 /* no flag */); + if (!status.isOk()) { + ALOGE("failed to write to dropbox"); + //TODO: What to do if flush fails?? + } + mLogList.Clear(); + mBufferSize = 0; +} diff --git a/cmds/statsd/src/DropboxWriter.h b/cmds/statsd/src/DropboxWriter.h new file mode 100644 index 000000000000..176ac8b944a7 --- /dev/null +++ b/cmds/statsd/src/DropboxWriter.h @@ -0,0 +1,66 @@ +/* + * 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 DROPBOX_WRITER_H +#define DROPBOX_WRITER_H + +#include <frameworks/base/cmds/statsd/src/stats_log.pb.h> + +using std::string; +using android::os::statsd::StatsLogEntry; +using android::os::statsd::StatsLogList; + +class DropboxWriter { +public: + /* tag will be part of the file name, and used as the key to build the file index inside + DropBoxManagerService. + */ + DropboxWriter(const string& tag); + + void addEntry(const StatsLogEntry& entry); + + /* Request a flush to dropbox. */ + void flush(); + +private: + /* Max *serialized* size of the logs kept in memory before flushing to dropbox. + Proto lite does not implement the SpaceUsed() function which gives the in memory byte size. + So we cap memory usage by limiting the serialized size. Note that protobuf's in memory size + is higher than its serialized size. DropboxManager will compress the file when the data is + larger than 4KB. So the final file size is less than this number. + */ + static const size_t kMaxSerializedBytes = 16 * 1024; + + const string mTag; + + /* StatsLogList is a wrapper for storing a list of StatsLogEntry */ + StatsLogList mLogList; + + /* Current *serialized* size of the logs kept in memory. + To save computation, we will not calculate the size of the StatsLogList every time when a new + entry is added, which would recursively call ByteSize() on every log entry. Instead, we keep + the sum of all individual stats log entry sizes. The size of a proto is approximately the sum + of the size of all member protos. + */ + size_t mBufferSize = 0; + + /* Check if the buffer size exceeds the max buffer size when the new entry is added, and flush + the logs to dropbox if true. */ + void flushIfNecessary(const StatsLogEntry& entry); + +}; + +#endif //DROPBOX_WRITER_H diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp new file mode 100644 index 000000000000..f49dfde804f4 --- /dev/null +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -0,0 +1,68 @@ +/* + * 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 <StatsLogProcessor.h> + +#include <log/event_tag_map.h> +#include <log/logprint.h> +#include <utils/Errors.h> + +#include <frameworks/base/cmds/statsd/src/stats_log.pb.h> + +using namespace android; +using android::os::statsd::StatsLogEntry; + +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); +} + +StatsLogProcessor::~StatsLogProcessor() +{ + if (m_tags != NULL) { + android_closeEventTagMap(m_tags); + } + android_log_format_free(m_format); +} + +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) { + StatsLogEntry logEntry; + logEntry.set_uid(entry.uid); + logEntry.set_pid(entry.pid); + logEntry.set_start_report_millis(entry.tv_sec / 1000 + entry.tv_nsec / 1000 / 1000); + logEntry.add_pairs()->set_value_str(entry.message, entry.messageLen); + m_dropbox_writer.addEntry(logEntry); + } +} + diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h new file mode 100644 index 000000000000..23066ab974d8 --- /dev/null +++ b/cmds/statsd/src/StatsLogProcessor.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 STATS_LOG_PROCESSOR_H +#define STATS_LOG_PROCESSOR_H + +#include "LogReader.h" +#include "DropboxWriter.h" + +#include <log/logprint.h> +#include <stdio.h> + +class StatsLogProcessor : public LogListener +{ +public: + StatsLogProcessor(); + virtual ~StatsLogProcessor(); + + virtual void OnLogEvent(const log_msg& msg); + +private: + /** + * Numeric to string tag name mapping. + */ + EventTagMap* m_tags; + + /** + * Pretty printing format. + */ + AndroidLogFormat* m_format; + + DropboxWriter m_dropbox_writer; +}; +#endif //STATS_LOG_PROCESSOR_H diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp index 93405cb6bf95..2c721c74f117 100644 --- a/cmds/statsd/src/main.cpp +++ b/cmds/statsd/src/main.cpp @@ -19,6 +19,7 @@ #include "LogEntryPrinter.h" #include "LogReader.h" #include "StatsService.h" +#include "StatsLogProcessor.h" #include <binder/IInterface.h> #include <binder/IPCThreadState.h> @@ -55,9 +56,8 @@ log_reader_thread_func(void* cookie) sp<LogReader> reader = new LogReader(); // Put the printer one first, so it will print before the real ones. - if (true) { - reader->AddListener(new LogEntryPrinter(STDOUT_FILENO)); - } + reader->AddListener(new LogEntryPrinter(STDOUT_FILENO)); + reader->AddListener(new StatsLogProcessor()); // TODO: Construct and add real LogListners here. diff --git a/cmds/statsd/src/stats_constants.proto b/cmds/statsd/src/stats_constants.proto new file mode 100644 index 000000000000..1787ae3cba2e --- /dev/null +++ b/cmds/statsd/src/stats_constants.proto @@ -0,0 +1,31 @@ +/* + * 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. + */ +syntax = "proto2"; + +package android.os.statsd; + +option optimize_for = LITE_RUNTIME; + +option java_package = "com.android.internal.logging"; +option java_outer_classname = "StatsConstantsProto"; + +message StatsConstants { + // Event type. + enum Type { + WAKELOCK = 1; + SCREEN= 2; + } +} diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto new file mode 100644 index 000000000000..ec92023c873a --- /dev/null +++ b/cmds/statsd/src/stats_log.proto @@ -0,0 +1,77 @@ +/* + * 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. + */ +syntax = "proto2"; + +package android.os.statsd; + +option optimize_for = LITE_RUNTIME; + +option java_package = "com.android.os"; +option java_outer_classname = "StatsLog"; + +import "frameworks/base/cmds/statsd/src/statsd_config.proto"; +import "frameworks/base/cmds/statsd/src/stats_constants.proto"; + +// StatsLogEntry is a generic proto holding a single metrics data. +message StatsLogEntry { + // Type of stats. + optional android.os.statsd.StatsConstants.Type type = 1; + + // Aggregation type of the data. + optional android.os.statsd.TrackedAggregateType aggregate_type = 2; + + // Start timestamp of the interval. Timestamp for event-type data will have + // equal value for start_report_millis and end_report_millis. + optional int64 start_report_millis = 3; + + // End timestamp of the interval. + optional int64 end_report_millis = 4; + + // Package information for application-level data. + optional string package_name = 5; + optional int32 package_version = 6; + optional string package_version_string = 7; + + // UID associated with the data. + optional int32 uid = 8; + + // PID associated with the data. + optional int32 pid = 9; + + // Payload contains key value pairs of the data from statsd. + message KeyValuePair { + // Integer representation of data type. + optional int32 key = 1; + + oneof value { + string value_str = 2; + int64 value_int = 3; + bool value_bool = 4; + } + } + repeated KeyValuePair pairs = 10; + + // Next tag: 11 +} + +// Data captured for a given metric during a given period of time. +message StatsLogList { + // Unique ID for this metric. + optional int32 metric_id = 1; + + // List of stats log entry. + repeated StatsLogEntry stats_log_entry = 2; +} diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto new file mode 100644 index 000000000000..2d034e50f4b5 --- /dev/null +++ b/cmds/statsd/src/statsd_config.proto @@ -0,0 +1,449 @@ +/* + * 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. + */ + + +// Version 1. +// Important: Update the version line above before copy-pasting this file +// from/to Google3 and Android repository. +// This proto needs to be manually synced between Google3 and Android versions. + +/* + * Note about semantics of the buckets: + * In this current proto scheme, the buckets are updated only when an event + * occurs. In the case of durations, this means that we update at the end of a + * duration. + * + * For example, suppose we have buckets at every 10 min: + * 0, 10, 20, 30, 40, etc. + * And then suppose a wakelock is first held starting at min 5 and lasts for 21 + * mins. Then the buckets for 0-10 and 10-20 don't contain anything and inside + * the bucket for 20-30, we add the value of 21 minutes. + * + * Also note that buckets are only aligned to wall-clock (no custom time-bases). + */ + +syntax = "proto2"; +package android.os.statsd; + +option optimize_for = LITE_RUNTIME; + +option java_package = "com.android.internal.os"; +option java_outer_classname = "StatsdConfigProto"; + +// KeyMatcher specifies how to match the key. +message KeyMatcher { + oneof contents { + int32 key = 1; // ID of the key to match. + + // Special matcher for package name. This will match either the package name + // or the UID (statsD will map the UID of the source event to a package + // name). Specify the package name to match in eq_string. + bool use_package = 2; + } +} + +// FieldMatcher allows us to match specific fields/keys in an event. +message FieldMatcher { + optional KeyMatcher key_matcher = 1; + + oneof value_matcher { + // Equality matchers + bool eq_bool = 2; + string eq_string = 3; + int32 eq_int32 = 4; + int64 eq_int64 = 5; + + // Numeric comparisons; + int32 lt_int32 = 6; + int32 gt_int32 = 7; + int64 lt_int64 = 8; + int64 gt_int64 = 9; + float lt_float = 10; + float gt_float = 11; + } +} + +enum OperationType { + AND = 1; + OR = 2; + NOT = 3; // Must have only a single operand when using NOT operator. + NAND = 4; // NAND and NOR as conveniences to avoid NOT+(AND/OR)-layers. + NOR = 5; +} + +enum TrackedAggregateType { + // IS_RUNNING; // whether it is currently running + VALUE_COUNT = 1; // count number of events + VALUE_SUM = 2; + VALUE_MAX = 3; + VALUE_MIN = 4; + DURATION_SUM = 5; // cumulative total time + DURATION_MAX = 6; // longest continuously-on time + DURATION_MIN = 7; // shortest continuously-on time + //DURATION_CURRENT = 6; // current continuously-on time (not bucketed) +} + +// Assume the events come in with a tag and an array of (key, value) tuples +// where the key must be an int32 and value can be any type. +message LineMatcher { + // For now, we assume that we don't flatten the tags (ie, one tag corresponds + // to screen-on and screen-off events and key 1 represents ON or OFF). + repeated int32 tag = 1; // Must match at least one of the tags. + + message Nested { + optional OperationType operation = 1; + repeated LineMatcher matcher = 2; + } + oneof contents { + FieldMatcher requirement = 2; + Nested nested = 3; + } +} + +// Defines when an AggregateCounter or EventMatcher applies. +message Condition { + message Nested { + optional OperationType operation = 1; + repeated Condition nested_conditions = 2; // operands that are themselves + // conditions (recursively) + } + + // Leaf node of condition. + message RangeMatcher { + optional LineMatcher start = 1; + optional LineMatcher stop = 2; + optional bool count_nesting = 3 + [default = true]; // true if "start start stop" is still + // considered running + + // Configure which fields define the slices. These fields must be present in + // both the start and stop lines. Note that this can be a subset of all the + // slices defined in the AggregateCounter. + // For example, if the counter slices on both app name and wake lock name, + // we can define that this range only slices on app name. + repeated KeyMatcher slice = 4; + } + + oneof contents { + RangeMatcher range = 1; // Represents a leaf node. + Nested nested = 2; // Represents a non-leaf node. + } +} + +// Emits matching events to statsd event buffer. +message EventMatcher { + // Tracks what configuration led to uploading of this event. + optional int32 metric_id = 1; + + // LineMatcher for the event to emit. + optional LineMatcher what = 2; + + optional Condition condition = 3; + + // TODO: Have a clear use-case for this in P or-else drop this for P. + message Filter { + } + optional Filter filter = 4; +} + +// Hard-code the possible metrics that we can pull. +// For example, NETSTATS_BY_UID would provide network usage per uid. +// We should treat the results like a batch of individual log events, and we +// should process them one-by-one to re-use our LineMatcher logic. +enum PulledMetricSource { + NETSTATS = 1; +} + +message AggregateCounter { // previously called Timer + // Specifies which fields in the message act as dimensions. + // For both pushed and pulled metrics, we assume every record has all the + // dimensions set. + message Slicer { + repeated KeyMatcher keys = 1; + } + optional Slicer slicer = 1; + + message ValueSource { + message PushedMetric { + // LineMatcher for the event to apply. + // Slicing (which keys act as dimensions) should not be specified here. + optional LineMatcher what = 1; + + // Only needed if one key should be treated as the value. + optional int32 value_key = 2; + } + + // The values for pulled metrics are computed and aggregated at the end of + // the condition. + message PulledMetric { + optional bool compute_diff = + 1; // If we want the diff (if this + // metric is pulled when condition opens/closes). + optional PulledMetricSource metric = 2; + + // We treat the pulled metrics as a batch of log-records that look like + // they came from LogD. + optional LineMatcher what = 3; + optional int32 value_field = 4; + } + + oneof value { + PushedMetric pushed_metric = 1; + + // Pulled metrics are computed when the duration closes (and are also + // fetched at the open if we need to compute a diff). + // Pulled metrics require a condition being defined. + // These metrics are not pulled at the end of every bucket. + PulledMetric pulled_metric = 2; + + // Polled Metrics are pulled at the end of every bucket. + // Since the buckets are only planned to be on wall-clock for Android P, + // condition is NOT supported for polled metrics. + PulledMetric polled_metric = 3; + } + } + optional ValueSource value = 2; + + message TrackedAggregate { + // Must be an integer that is uniquely chosen so we can identify the metric + // on server. We will provide a tool on server to help generate this. + optional int32 metric_id = 1; + + optional TrackedAggregateType type = 2; + + // Alert if the value, when summed over the Counter's number_of_buckets + // most-recent bins, exceeds min_threshold or is below max_threshold. For + // Anomaly Detection. + message Alert { + message IncidentdDetails { + optional string + alert_name = 1; // for humans and incidentd to identify this issue + repeated int32 incidentd_sections = 2; // tells incidentd what to do if + // alert triggers + } + optional IncidentdDetails incidentd_details = 1; + optional int32 number_of_buckets = 2; + // NOTE: that we assume the aggregate is only int. + optional int64 trigger_if_gt = 3; // min threshold + optional int64 trigger_if_lt = 4; // max_threshold; + optional int32 refractory_period_secs = 5; // alarm cannot fire a second + // time until elapsed + } + repeated Alert alerts = 3; // Support diff alert params for same aggregate. + } // end TrackedAggregate + repeated TrackedAggregate tracked_aggregates = 3; + + optional Condition condition = 4; + + message Bucket { + // TODO: Consider switching to second granularity. + // In practice, this must be chosen from a pre-defined list. So that we have + // flexiblity, we don't hard-code this as an enum today. + optional int64 bucket_size_msec = 1; + optional int32 max_number_of_bits = 2; // Max bits per bucket. + } + optional Bucket bucket = 5; + + message MiscellaneousEffect { + optional LineMatcher matcher = 1; // When to trigger the effect + + enum Effect { + STOP_ALL = 1; // Needed for stop-all events, where nested start value is + // forced to 0. + } + repeated Effect effects = 2; + } // end MiscellaneousEffect + repeated MiscellaneousEffect misc_effects = 6; +} // end Counter + +// Alarm configs not tied to a particular Counter. +message GlobalAlertParameters { + // No alarm can fire after any other alarm fired until this many seconds has + // elapsed. + optional int32 global_refractory_period_seconds = 1; +} + +// The config defining all metrics to be captured. +message StatsdConfig { + // Event matchers. + repeated EventMatcher event_matchers = 1; + + // Aggregate counters. + repeated AggregateCounter aggregate_counters = 2; +} + +/* Sample configurations start here: +----Screen on time---- +AggregateCounter < + condition < + range < + start < + tag: SCREEN_ON + requirement < + key_matcher< + key: SCREEN_ON_VALUE + eq_bool: true + stop < + tag: SCREEN_ON + requirement < + key_matcher< + key: SCREEN_ON_VALUE + eq_bool: false + metric_id: # set on server + tracked_aggregates < + DURATION_SUM + (For brevity, omit the bucket options but they can also be set) + +----Screen off time---- +Should be like aboe but reversing start and stop + +----Log the screen change events---- +EventMatcher < + metric_id: # set on server + what < + tag: SCREEN_ON + +----Number of crashes (across system)---- +AggregateCounter < + metric_id: # set on server + tracked_aggregates < + VALUE_COUNT + value < + pushed_metric < + what < + tag: CRASH_TAG + +----Network Usage in bytes Per App While in Background---- +AggregateCounter < + metric_id: # set on server + slicer < + keys < + use_package_name: true + tracked_aggregates < + VALUE_SUM + value < + pulled_metric < + compute_diff: true + metric: Enum corresponding to network usage in bytes + condition < + range < + sliced: true + start < + tag: APP_FOREGROUND_TRANSITION (assume false means move to background) + requirement < + key_matcher< + key: APP_FOREGROUND_STATE + eq_bool: false + stop < + tag: APP_FOREGROUND_TRANSITION (assume false means move to background) + requirement < + key_matcher< + key: APP_FOREGROUND_STATE + eq_bool: true + +----Wakelock Acquire time per app and wakelock + while unplugged and screen off and in background process state---- +AggregateCounter < + metric_id: # set on server + slicer < + keys < + use_package_name: true + keys < + key: Key corresponding to wake_lock ID + tracked_aggregates < + DURATION_SUM + condition < + nested < + operation: AND + nested_conditions < + range < + start < + tag: PLUGGED_IN (assume false means uncharged) + requirement < + key_matcher< + key: PLUGGED_IN_STATE + eq_bool: false + stop < + tag: PLUGGED_IN (assume false means uncharged) + requirement < + key_matcher< + key: PLUGGED_IN_STATE + eq_bool: true + nested_conditions < + range < + start < + tag: SCREEN_ON + requirement < + key_matcher< + key: SCREEN_ON_STATE + eq_bool: false + stop < + tag: SCREEN_ON + requirement < + key_matcher< + key: SCREEN_ON_STATE + eq_bool: true + nested_conditions < + range < + start < + tag: PROCESS_CHANGE + requirement < + key_matcher< + key: PROCESS_STATE_VALUE + eq_int32: BACKGROUND_PROCESS + stop < + tag: PROCESS_CHANGE + nested < + operation: NOT + matcher< (This is an example of using the NOT to define stop) + requirement < (Note this requirement should match the start.) + key_matcher< + key: PROCESS_STATE_VALUE + eq_int32: BACKGROUND_PROCESS + slice< + use_package_name: true + + +----Number of crashes (per app) ---- +AggregateCounter < + metric_id: # set on server + slicer < + keys< + use_package_name: true + tracked_aggregates < + VALUE_COUNT + value < + pushed_metric < + what < + tag: CRASH_TAG + +---- Number of transitions to background (per app) ---- +AggregateCounter < + metric_id: # set on server + slicer < + keys< + use_package_name: true + tracked_aggregates < + VALUE_COUNT + value < + pushed_metric < + what < + tag: APP_FOREGROUND_TRANSITION + requirement< + key: APP_FOREGROUND_TRANSITION_STATE + eq_bool: false + +*/ |