diff options
| -rw-r--r-- | cmds/statsd/src/atoms.proto | 15 | ||||
| -rw-r--r-- | cmds/statsd/src/logd/LogEvent.cpp | 47 | ||||
| -rw-r--r-- | cmds/statsd/src/logd/LogEvent.h | 9 | ||||
| -rw-r--r-- | cmds/statsd/tests/LogEvent_test.cpp | 90 | ||||
| -rw-r--r-- | tools/stats_log_api_gen/Collation.cpp | 13 | ||||
| -rw-r--r-- | tools/stats_log_api_gen/Collation.h | 1 |
6 files changed, 175 insertions, 0 deletions
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index d7a926ffa28e..6065bbfc3f90 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -127,6 +127,7 @@ message Atom { WTFOccurred wtf_occurred = 80; LowMemReported low_mem_reported = 81; GenericAtom generic_atom = 82; + KeyValuePairsAtom key_value_pairs_atom = 83; } // Pulled events will start at field 10000. @@ -177,6 +178,20 @@ message AttributionNode { optional string tag = 2; } +message KeyValuePair { + optional int32 key = 1; + oneof value { + int64 value_int = 2; + string value_str = 3; + float value_float = 4; + } +} + +message KeyValuePairsAtom { + optional int32 uid = 1; + repeated KeyValuePair pairs = 2; +} + /* * ***************************************************************************** * Below are all of the individual atoms that are logged by Android via statsd. diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp index 04d34f3be2c0..73e6572db50f 100644 --- a/cmds/statsd/src/logd/LogEvent.cpp +++ b/cmds/statsd/src/logd/LogEvent.cpp @@ -18,6 +18,7 @@ #include "logd/LogEvent.h" #include "stats_log_util.h" +#include "statslog.h" namespace android { namespace os { @@ -51,6 +52,52 @@ LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedT } } +LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs, + int32_t uid, + const std::map<int32_t, int64_t>& int_map, + const std::map<int32_t, std::string>& string_map, + const std::map<int32_t, float>& float_map) { + mLogdTimestampNs = wallClockTimestampNs; + mElapsedTimestampNs = elapsedTimestampNs; + mTagId = android::util::KEY_VALUE_PAIRS_ATOM; + mLogUid = uid; + + int pos[] = {1, 1, 1}; + + mValues.push_back(FieldValue(Field(mTagId, pos, 0 /* depth */), Value(uid))); + pos[0]++; + for (const auto&itr : int_map) { + pos[2] = 1; + mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first))); + pos[2] = 2; + mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second))); + mValues.back().mField.decorateLastPos(2); + pos[1]++; + } + + for (const auto&itr : string_map) { + pos[2] = 1; + mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first))); + pos[2] = 3; + mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second))); + mValues.back().mField.decorateLastPos(2); + pos[1]++; + } + + for (const auto&itr : float_map) { + pos[2] = 1; + mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first))); + pos[2] = 4; + mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second))); + mValues.back().mField.decorateLastPos(2); + pos[1]++; + } + if (!mValues.empty()) { + mValues.back().mField.decorateLastPos(1); + mValues.at(mValues.size() - 2).mField.decorateLastPos(1); + } +} + LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) { mLogdTimestampNs = timestampNs; mTagId = tagId; diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h index 24d624d9d9be..9ed09dd12fbd 100644 --- a/cmds/statsd/src/logd/LogEvent.h +++ b/cmds/statsd/src/logd/LogEvent.h @@ -69,6 +69,15 @@ public: // For testing. The timestamp is used as both elapsed real time and logd timestamp. explicit LogEvent(int32_t tagId, int64_t timestampNs); + /** + * Constructs a KeyValuePairsAtom LogEvent from value maps. + */ + explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs, + int32_t uid, + const std::map<int32_t, int64_t>& int_map, + const std::map<int32_t, std::string>& string_map, + const std::map<int32_t, float>& float_map); + ~LogEvent(); /** diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp index 2fcde29fbbdb..acfa151c6f95 100644 --- a/cmds/statsd/tests/LogEvent_test.cpp +++ b/cmds/statsd/tests/LogEvent_test.cpp @@ -158,6 +158,96 @@ TEST(LogEventTest, TestLogParsing2) { EXPECT_EQ((float)1.1, item7.mValue.float_value); } +TEST(LogEventTest, TestKeyValuePairsAtomParsing) { + std::map<int32_t, int64_t> int_map; + std::map<int32_t, std::string> string_map; + std::map<int32_t, float> float_map; + + int_map[11] = 123L; + int_map[22] = 345L; + + string_map[1] = "test2"; + string_map[2] = "test1"; + + float_map[111] = 2.2f; + float_map[222] = 1.1f; + + LogEvent event1(83, 2000, 2001, 10001, int_map, string_map, float_map); + event1.init(); + + EXPECT_EQ(83, event1.GetTagId()); + EXPECT_EQ((int64_t)2000, event1.GetLogdTimestampNs()); + EXPECT_EQ((int64_t)2001, event1.GetElapsedTimestampNs()); + + const auto& items = event1.getValues(); + EXPECT_EQ((size_t)13, items.size()); + + const FieldValue& item0 = event1.getValues()[0]; + EXPECT_EQ(0x00010000, item0.mField.getField()); + EXPECT_EQ(Type::INT, item0.mValue.getType()); + EXPECT_EQ(10001, item0.mValue.int_value); + + const FieldValue& item1 = event1.getValues()[1]; + EXPECT_EQ(0x2020101, item1.mField.getField()); + EXPECT_EQ(Type::INT, item1.mValue.getType()); + EXPECT_EQ(11, item1.mValue.int_value); + + const FieldValue& item2 = event1.getValues()[2]; + EXPECT_EQ(0x2020182, item2.mField.getField()); + EXPECT_EQ(Type::LONG, item2.mValue.getType()); + EXPECT_EQ(123L, item2.mValue.long_value); + + const FieldValue& item3 = event1.getValues()[3]; + EXPECT_EQ(0x2020201, item3.mField.getField()); + EXPECT_EQ(Type::INT, item3.mValue.getType()); + EXPECT_EQ(22, item3.mValue.int_value); + + const FieldValue& item4 = event1.getValues()[4]; + EXPECT_EQ(0x2020282, item4.mField.getField()); + EXPECT_EQ(Type::LONG, item4.mValue.getType()); + EXPECT_EQ(345L, item4.mValue.long_value); + + const FieldValue& item5 = event1.getValues()[5]; + EXPECT_EQ(0x2020301, item5.mField.getField()); + EXPECT_EQ(Type::INT, item5.mValue.getType()); + EXPECT_EQ(1, item5.mValue.int_value); + + const FieldValue& item6 = event1.getValues()[6]; + EXPECT_EQ(0x2020383, item6.mField.getField()); + EXPECT_EQ(Type::STRING, item6.mValue.getType()); + EXPECT_EQ("test2", item6.mValue.str_value); + + const FieldValue& item7 = event1.getValues()[7]; + EXPECT_EQ(0x2020401, item7.mField.getField()); + EXPECT_EQ(Type::INT, item7.mValue.getType()); + EXPECT_EQ(2, item7.mValue.int_value); + + const FieldValue& item8 = event1.getValues()[8]; + EXPECT_EQ(0x2020483, item8.mField.getField()); + EXPECT_EQ(Type::STRING, item8.mValue.getType()); + EXPECT_EQ("test1", item8.mValue.str_value); + + const FieldValue& item9 = event1.getValues()[9]; + EXPECT_EQ(0x2020501, item9.mField.getField()); + EXPECT_EQ(Type::INT, item9.mValue.getType()); + EXPECT_EQ(111, item9.mValue.int_value); + + const FieldValue& item10 = event1.getValues()[10]; + EXPECT_EQ(0x2020584, item10.mField.getField()); + EXPECT_EQ(Type::FLOAT, item10.mValue.getType()); + EXPECT_EQ(2.2f, item10.mValue.float_value); + + const FieldValue& item11 = event1.getValues()[11]; + EXPECT_EQ(0x2028601, item11.mField.getField()); + EXPECT_EQ(Type::INT, item11.mValue.getType()); + EXPECT_EQ(222, item11.mValue.int_value); + + const FieldValue& item12 = event1.getValues()[12]; + EXPECT_EQ(0x2028684, item12.mField.getField()); + EXPECT_EQ(Type::FLOAT, item12.mValue.getType()); + EXPECT_EQ(1.1f, item12.mValue.float_value); +} + } // namespace statsd } // namespace os diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp index ebdcdfdd6c50..40ee490fc186 100644 --- a/tools/stats_log_api_gen/Collation.cpp +++ b/tools/stats_log_api_gen/Collation.cpp @@ -116,6 +116,9 @@ java_type(const FieldDescriptor* field) if (field->message_type()->full_name() == "android.os.statsd.AttributionNode") { return JAVA_TYPE_ATTRIBUTION_CHAIN; + } else if (field->message_type()->full_name() == + "android.os.statsd.KeyValuePair") { + return JAVA_TYPE_KEY_VALUE_PAIR; } else { return JAVA_TYPE_OBJECT; } @@ -181,6 +184,16 @@ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, expectedNumber++; } + // Skips the key value pair atom. + for (map<int, const FieldDescriptor *>::const_iterator it = fields.begin(); + it != fields.end(); it++) { + const FieldDescriptor *field = it->second; + java_type_t javaType = java_type(field); + if (javaType == JAVA_TYPE_KEY_VALUE_PAIR) { + return 0; + } + } + // Check that only allowed types are present. Remove any invalid ones. for (map<int, const FieldDescriptor *>::const_iterator it = fields.begin(); it != fields.end(); it++) { diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h index 5d2c30292c9c..ccdd1458f656 100644 --- a/tools/stats_log_api_gen/Collation.h +++ b/tools/stats_log_api_gen/Collation.h @@ -48,6 +48,7 @@ typedef enum { JAVA_TYPE_DOUBLE = 6, JAVA_TYPE_STRING = 7, JAVA_TYPE_ENUM = 8, + JAVA_TYPE_KEY_VALUE_PAIR = 9, JAVA_TYPE_OBJECT = -1, JAVA_TYPE_BYTE_ARRAY = -2, |