Interface of writing key value pair atom to socket and parsing from statsd.
Test: statsd unit test
BUG: b/114231161
Change-Id: I3543900934b5e8e0677bf1e7cc454d61064a2475
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 73e6572..cf04ee3 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -175,6 +175,56 @@
return false;
}
+
+
+bool LogEvent::writeKeyValuePairs(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) {
+ if (mContext) {
+ if (android_log_write_list_begin(mContext) < 0) {
+ return false;
+ }
+ for (const auto& itr : int_map) {
+ if (android_log_write_list_begin(mContext) < 0) {
+ return false;
+ }
+ write(itr.first);
+ write(itr.second);
+ if (android_log_write_list_end(mContext) < 0) {
+ return false;
+ }
+ }
+
+ for (const auto& itr : string_map) {
+ if (android_log_write_list_begin(mContext) < 0) {
+ return false;
+ }
+ write(itr.first);
+ write(itr.second.c_str());
+ if (android_log_write_list_end(mContext) < 0) {
+ return false;
+ }
+ }
+
+ for (const auto& itr : float_map) {
+ if (android_log_write_list_begin(mContext) < 0) {
+ return false;
+ }
+ write(itr.first);
+ write(itr.second);
+ if (android_log_write_list_end(mContext) < 0) {
+ return false;
+ }
+ }
+
+ if (android_log_write_list_end(mContext) < 0) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
bool LogEvent::write(const std::vector<AttributionNodeInternal>& nodes) {
if (mContext) {
if (android_log_write_list_begin(mContext) < 0) {
@@ -225,6 +275,7 @@
int i = 0;
int depth = -1;
int pos[] = {1, 1, 1};
+ bool isKeyValuePairAtom = false;
do {
elem = android_log_read_next(context);
switch ((int)elem.type) {
@@ -232,6 +283,7 @@
// elem at [0] is EVENT_TYPE_LIST, [1] is the timestamp, [2] is tag id.
if (i == 2) {
mTagId = elem.data.int32;
+ isKeyValuePairAtom = (mTagId == android::util::KEY_VALUE_PAIRS_ATOM);
} else {
if (depth < 0 || depth > 2) {
return;
@@ -249,6 +301,11 @@
return;
}
+ // Handles the oneof field in KeyValuePair atom.
+ if (isKeyValuePairAtom && depth == 2) {
+ pos[depth] = 4;
+ }
+
mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(elem.data.float32)));
pos[depth]++;
@@ -260,6 +317,10 @@
return;
}
+ // Handles the oneof field in KeyValuePair atom.
+ if (isKeyValuePairAtom && depth == 2) {
+ pos[depth] = 3;
+ }
mValues.push_back(FieldValue(Field(mTagId, pos, depth),
Value(string(elem.data.string, elem.len))));
@@ -274,6 +335,10 @@
ALOGE("Depth > 2. Not supported!");
return;
}
+ // Handles the oneof field in KeyValuePair atom.
+ if (isKeyValuePairAtom && depth == 2) {
+ pos[depth] = 2;
+ }
mValues.push_back(
FieldValue(Field(mTagId, pos, depth), Value((int64_t)elem.data.int64)));
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 9ed09dd..2ee6bdf 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -119,6 +119,9 @@
bool write(float value);
bool write(const std::vector<AttributionNodeInternal>& nodes);
bool write(const AttributionNodeInternal& node);
+ bool writeKeyValuePairs(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);
/**
* Return a string representation of this event.
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index acfa151..6e3b04c 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -89,6 +89,89 @@
EXPECT_EQ((float)1.1, item7.mValue.float_value);
}
+TEST(LogEventTest, TestKeyValuePairsAtomParsing) {
+ LogEvent event1(83, 2000);
+ 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;
+
+ EXPECT_TRUE(event1.writeKeyValuePairs(int_map, string_map, float_map));
+ event1.init();
+
+ EXPECT_EQ(83, event1.GetTagId());
+ const auto& items = event1.getValues();
+ EXPECT_EQ((size_t)12, items.size());
+
+ const FieldValue& item0 = event1.getValues()[0];
+ EXPECT_EQ(0x2010101, item0.mField.getField());
+ EXPECT_EQ(Type::INT, item0.mValue.getType());
+ EXPECT_EQ(11, item0.mValue.int_value);
+
+ const FieldValue& item1 = event1.getValues()[1];
+ EXPECT_EQ(0x2010182, item1.mField.getField());
+ EXPECT_EQ(Type::LONG, item1.mValue.getType());
+ EXPECT_EQ(123L, item1.mValue.long_value);
+
+ const FieldValue& item2 = event1.getValues()[2];
+ EXPECT_EQ(0x2010201, item2.mField.getField());
+ EXPECT_EQ(Type::INT, item2.mValue.getType());
+ EXPECT_EQ(22, item2.mValue.int_value);
+
+ const FieldValue& item3 = event1.getValues()[3];
+ EXPECT_EQ(0x2010282, item3.mField.getField());
+ EXPECT_EQ(Type::LONG, item3.mValue.getType());
+ EXPECT_EQ(345L, item3.mValue.long_value);
+
+ const FieldValue& item4 = event1.getValues()[4];
+ EXPECT_EQ(0x2010301, item4.mField.getField());
+ EXPECT_EQ(Type::INT, item4.mValue.getType());
+ EXPECT_EQ(1, item4.mValue.int_value);
+
+ const FieldValue& item5 = event1.getValues()[5];
+ EXPECT_EQ(0x2010383, item5.mField.getField());
+ EXPECT_EQ(Type::STRING, item5.mValue.getType());
+ EXPECT_EQ("test2", item5.mValue.str_value);
+
+ const FieldValue& item6 = event1.getValues()[6];
+ EXPECT_EQ(0x2010401, item6.mField.getField());
+ EXPECT_EQ(Type::INT, item6.mValue.getType());
+ EXPECT_EQ(2, item6.mValue.int_value);
+
+ const FieldValue& item7 = event1.getValues()[7];
+ EXPECT_EQ(0x2010483, item7.mField.getField());
+ EXPECT_EQ(Type::STRING, item7.mValue.getType());
+ EXPECT_EQ("test1", item7.mValue.str_value);
+
+ const FieldValue& item8 = event1.getValues()[8];
+ EXPECT_EQ(0x2010501, item8.mField.getField());
+ EXPECT_EQ(Type::INT, item8.mValue.getType());
+ EXPECT_EQ(111, item8.mValue.int_value);
+
+ const FieldValue& item9 = event1.getValues()[9];
+ EXPECT_EQ(0x2010584, item9.mField.getField());
+ EXPECT_EQ(Type::FLOAT, item9.mValue.getType());
+ EXPECT_EQ(2.2f, item9.mValue.float_value);
+
+ const FieldValue& item10 = event1.getValues()[10];
+ EXPECT_EQ(0x2018601, item10.mField.getField());
+ EXPECT_EQ(Type::INT, item10.mValue.getType());
+ EXPECT_EQ(222, item10.mValue.int_value);
+
+ const FieldValue& item11 = event1.getValues()[11];
+ EXPECT_EQ(0x2018684, item11.mField.getField());
+ EXPECT_EQ(Type::FLOAT, item11.mValue.getType());
+ EXPECT_EQ(1.1f, item11.mValue.float_value);
+}
+
TEST(LogEventTest, TestLogParsing2) {
LogEvent event1(1, 2000);
@@ -158,7 +241,7 @@
EXPECT_EQ((float)1.1, item7.mValue.float_value);
}
-TEST(LogEventTest, TestKeyValuePairsAtomParsing) {
+TEST(LogEventTest, TestKeyValuePairsEvent) {
std::map<int32_t, int64_t> int_map;
std::map<int32_t, std::string> string_map;
std::map<int32_t, float> float_map;