blob: f9f1b387279a0fa57780c78f2145e4e997c70dfd [file] [log] [blame]
Joe Onoratoc4dfae52017-10-17 23:38:21 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Tej Singh484524a2018-02-01 15:10:05 -080017#define DEBUG false // STOPSHIP if true
Joe Onoratoc4dfae52017-10-17 23:38:21 -070018#include "logd/LogEvent.h"
19
Yangster-mac20877162017-12-22 17:19:39 -080020#include "stats_log_util.h"
Yangster-mac48b3d622018-08-18 12:38:11 -070021#include "statslog.h"
Joe Onoratoc4dfae52017-10-17 23:38:21 -070022
23namespace android {
24namespace os {
25namespace statsd {
26
yro24809bd2017-10-31 23:06:53 -070027using namespace android::util;
Yao Chen9c1debe2018-02-19 14:39:19 -080028using android::util::ProtoOutputStream;
David Chen1481fe12017-10-16 13:16:34 -070029using std::string;
Yao Chen9c1debe2018-02-19 14:39:19 -080030using std::vector;
Joe Onoratoc4dfae52017-10-17 23:38:21 -070031
Yao Chen80235402017-11-13 20:42:25 -080032LogEvent::LogEvent(log_msg& msg) {
Chenjie Yu3ca36832018-01-22 15:10:54 -080033 mContext =
Yao Chen80235402017-11-13 20:42:25 -080034 create_android_log_parser(msg.msg() + sizeof(uint32_t), msg.len() - sizeof(uint32_t));
Yangster-mac330af582018-02-08 15:24:38 -080035 mLogdTimestampNs = msg.entry_v1.sec * NS_PER_SEC + msg.entry_v1.nsec;
Yao Chend10f7b12017-12-18 12:53:50 -080036 mLogUid = msg.entry_v4.uid;
Chenjie Yu3ca36832018-01-22 15:10:54 -080037 init(mContext);
38 if (mContext) {
Yao Chen48d75182018-01-23 09:40:48 -080039 // android_log_destroy will set mContext to NULL
Chenjie Yu3ca36832018-01-22 15:10:54 -080040 android_log_destroy(&mContext);
Yangster-mac20877162017-12-22 17:19:39 -080041 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -070042}
43
Chenjie Yu12e5e672018-09-14 15:54:59 -070044LogEvent::LogEvent(const StatsLogEventWrapper& statsLogEventWrapper) {
45 mTagId = statsLogEventWrapper.getTagId();
46 mLogdTimestampNs = statsLogEventWrapper.getWallClockTimeNs();
47 mElapsedTimestampNs = statsLogEventWrapper.getElapsedRealTimeNs();
48 mLogUid = 0;
49 for (int i = 0; i < (int)statsLogEventWrapper.getElements().size(); i++) {
50 Field field(statsLogEventWrapper.getTagId(), getSimpleField(i + 1));
51 switch (statsLogEventWrapper.getElements()[i].type) {
52 case android::os::StatsLogValue::STATS_LOG_VALUE_TYPE::INT:
53 mValues.push_back(
54 FieldValue(field, Value(statsLogEventWrapper.getElements()[i].int_value)));
55 break;
56 case android::os::StatsLogValue::STATS_LOG_VALUE_TYPE::LONG:
57 mValues.push_back(
58 FieldValue(field, Value(statsLogEventWrapper.getElements()[i].long_value)));
59 break;
60 case android::os::StatsLogValue::STATS_LOG_VALUE_TYPE::FLOAT:
61 mValues.push_back(FieldValue(
62 field, Value(statsLogEventWrapper.getElements()[i].float_value)));
63 break;
64 case android::os::StatsLogValue::STATS_LOG_VALUE_TYPE::DOUBLE:
65 mValues.push_back(FieldValue(
66 field, Value(statsLogEventWrapper.getElements()[i].double_value)));
67 break;
68 case android::os::StatsLogValue::STATS_LOG_VALUE_TYPE::STRING:
69 mValues.push_back(
70 FieldValue(field, Value(statsLogEventWrapper.getElements()[i].str_value)));
71 break;
72 case android::os::StatsLogValue::STATS_LOG_VALUE_TYPE::STORAGE:
73 mValues.push_back(FieldValue(
74 field, Value(statsLogEventWrapper.getElements()[i].storage_value)));
75 break;
76 default:
77 break;
78 }
79 }
80}
81
Yangster-mac330af582018-02-08 15:24:38 -080082LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs) {
83 mLogdTimestampNs = wallClockTimestampNs;
Yao Chen80235402017-11-13 20:42:25 -080084 mTagId = tagId;
Yangster-mac20877162017-12-22 17:19:39 -080085 mLogUid = 0;
Yao Chen80235402017-11-13 20:42:25 -080086 mContext = create_android_logger(1937006964); // the event tag shared by all stats logs
87 if (mContext) {
Yangster-mac330af582018-02-08 15:24:38 -080088 android_log_write_int64(mContext, elapsedTimestampNs);
89 android_log_write_int32(mContext, tagId);
90 }
91}
92
Yangster-mac48b3d622018-08-18 12:38:11 -070093LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
94 int32_t uid,
95 const std::map<int32_t, int64_t>& int_map,
96 const std::map<int32_t, std::string>& string_map,
97 const std::map<int32_t, float>& float_map) {
98 mLogdTimestampNs = wallClockTimestampNs;
99 mElapsedTimestampNs = elapsedTimestampNs;
100 mTagId = android::util::KEY_VALUE_PAIRS_ATOM;
101 mLogUid = uid;
102
103 int pos[] = {1, 1, 1};
104
105 mValues.push_back(FieldValue(Field(mTagId, pos, 0 /* depth */), Value(uid)));
106 pos[0]++;
107 for (const auto&itr : int_map) {
108 pos[2] = 1;
109 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
110 pos[2] = 2;
111 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
112 mValues.back().mField.decorateLastPos(2);
113 pos[1]++;
114 }
115
116 for (const auto&itr : string_map) {
117 pos[2] = 1;
118 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
119 pos[2] = 3;
120 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
121 mValues.back().mField.decorateLastPos(2);
122 pos[1]++;
123 }
124
125 for (const auto&itr : float_map) {
126 pos[2] = 1;
127 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
128 pos[2] = 4;
129 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
130 mValues.back().mField.decorateLastPos(2);
131 pos[1]++;
132 }
133 if (!mValues.empty()) {
134 mValues.back().mField.decorateLastPos(1);
135 mValues.at(mValues.size() - 2).mField.decorateLastPos(1);
136 }
137}
138
Yangster-mac330af582018-02-08 15:24:38 -0800139LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) {
140 mLogdTimestampNs = timestampNs;
141 mTagId = tagId;
142 mLogUid = 0;
143 mContext = create_android_logger(1937006964); // the event tag shared by all stats logs
144 if (mContext) {
145 android_log_write_int64(mContext, timestampNs);
Yao Chen80235402017-11-13 20:42:25 -0800146 android_log_write_int32(mContext, tagId);
147 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700148}
149
David Chen1481fe12017-10-16 13:16:34 -0700150void LogEvent::init() {
Yao Chen80235402017-11-13 20:42:25 -0800151 if (mContext) {
152 const char* buffer;
153 size_t len = android_log_write_list_buffer(mContext, &buffer);
154 // turns to reader mode
Chenjie Yuc1fe6f42018-02-01 23:14:18 -0800155 android_log_context contextForRead = create_android_log_parser(buffer, len);
156 if (contextForRead) {
157 init(contextForRead);
158 // destroy the context to save memory.
Yao Chen48d75182018-01-23 09:40:48 -0800159 // android_log_destroy will set mContext to NULL
Chenjie Yuc1fe6f42018-02-01 23:14:18 -0800160 android_log_destroy(&contextForRead);
Yao Chen48d75182018-01-23 09:40:48 -0800161 }
Chenjie Yuc1fe6f42018-02-01 23:14:18 -0800162 android_log_destroy(&mContext);
Yangster-mac20877162017-12-22 17:19:39 -0800163 }
164}
165
166LogEvent::~LogEvent() {
167 if (mContext) {
Yao Chen48d75182018-01-23 09:40:48 -0800168 // This is for the case when LogEvent is created using the test interface
169 // but init() isn't called.
Yangster-mac20877162017-12-22 17:19:39 -0800170 android_log_destroy(&mContext);
Yao Chen80235402017-11-13 20:42:25 -0800171 }
172}
173
174bool LogEvent::write(int32_t value) {
175 if (mContext) {
176 return android_log_write_int32(mContext, value) >= 0;
177 }
178 return false;
179}
180
181bool LogEvent::write(uint32_t value) {
182 if (mContext) {
183 return android_log_write_int32(mContext, value) >= 0;
184 }
185 return false;
186}
187
Chenjie Yud9dfda72017-12-11 17:41:20 -0800188bool LogEvent::write(int64_t value) {
189 if (mContext) {
190 return android_log_write_int64(mContext, value) >= 0;
191 }
192 return false;
193}
194
Yao Chen80235402017-11-13 20:42:25 -0800195bool LogEvent::write(uint64_t value) {
196 if (mContext) {
197 return android_log_write_int64(mContext, value) >= 0;
198 }
199 return false;
200}
201
202bool LogEvent::write(const string& value) {
203 if (mContext) {
204 return android_log_write_string8_len(mContext, value.c_str(), value.length()) >= 0;
205 }
206 return false;
207}
208
209bool LogEvent::write(float value) {
210 if (mContext) {
211 return android_log_write_float32(mContext, value) >= 0;
212 }
213 return false;
214}
215
Yangster-mace124e422018-08-16 10:30:28 -0700216
217
218bool LogEvent::writeKeyValuePairs(const std::map<int32_t, int64_t>& int_map,
219 const std::map<int32_t, std::string>& string_map,
220 const std::map<int32_t, float>& float_map) {
221 if (mContext) {
222 if (android_log_write_list_begin(mContext) < 0) {
223 return false;
224 }
225 for (const auto& itr : int_map) {
226 if (android_log_write_list_begin(mContext) < 0) {
227 return false;
228 }
229 write(itr.first);
230 write(itr.second);
231 if (android_log_write_list_end(mContext) < 0) {
232 return false;
233 }
234 }
235
236 for (const auto& itr : string_map) {
237 if (android_log_write_list_begin(mContext) < 0) {
238 return false;
239 }
240 write(itr.first);
241 write(itr.second.c_str());
242 if (android_log_write_list_end(mContext) < 0) {
243 return false;
244 }
245 }
246
247 for (const auto& itr : float_map) {
248 if (android_log_write_list_begin(mContext) < 0) {
249 return false;
250 }
251 write(itr.first);
252 write(itr.second);
253 if (android_log_write_list_end(mContext) < 0) {
254 return false;
255 }
256 }
257
258 if (android_log_write_list_end(mContext) < 0) {
259 return false;
260 }
261 return true;
262 }
263 return false;
264}
265
Yao Chen9c1debe2018-02-19 14:39:19 -0800266bool LogEvent::write(const std::vector<AttributionNodeInternal>& nodes) {
Yao Chen80235402017-11-13 20:42:25 -0800267 if (mContext) {
Yangster-mac20877162017-12-22 17:19:39 -0800268 if (android_log_write_list_begin(mContext) < 0) {
269 return false;
270 }
271 for (size_t i = 0; i < nodes.size(); ++i) {
272 if (!write(nodes[i])) {
273 return false;
274 }
275 }
276 if (android_log_write_list_end(mContext) < 0) {
277 return false;
278 }
279 return true;
280 }
281 return false;
282}
283
Yao Chen9c1debe2018-02-19 14:39:19 -0800284bool LogEvent::write(const AttributionNodeInternal& node) {
Yangster-mac20877162017-12-22 17:19:39 -0800285 if (mContext) {
286 if (android_log_write_list_begin(mContext) < 0) {
287 return false;
288 }
289 if (android_log_write_int32(mContext, node.uid()) < 0) {
290 return false;
291 }
292 if (android_log_write_string8(mContext, node.tag().c_str()) < 0) {
293 return false;
294 }
Yangster-mac20877162017-12-22 17:19:39 -0800295 if (android_log_write_list_end(mContext) < 0) {
296 return false;
297 }
298 return true;
299 }
300 return false;
301}
302
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700303/**
304 * The elements of each log event are stored as a vector of android_log_list_elements.
305 * The goal is to do as little preprocessing as possible, because we read a tiny fraction
306 * of the elements that are written to the log.
Yao Chen8a8d16c2018-02-08 14:50:40 -0800307 *
308 * The idea here is to read through the log items once, we get as much information we need for
309 * matching as possible. Because this log will be matched against lots of matchers.
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700310 */
Yao Chen80235402017-11-13 20:42:25 -0800311void LogEvent::init(android_log_context context) {
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700312 android_log_list_element elem;
Yao Chen80235402017-11-13 20:42:25 -0800313 int i = 0;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800314 int depth = -1;
315 int pos[] = {1, 1, 1};
Yangster-mace124e422018-08-16 10:30:28 -0700316 bool isKeyValuePairAtom = false;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700317 do {
Yao Chen80235402017-11-13 20:42:25 -0800318 elem = android_log_read_next(context);
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700319 switch ((int)elem.type) {
320 case EVENT_TYPE_INT:
Yangster-mac330af582018-02-08 15:24:38 -0800321 // elem at [0] is EVENT_TYPE_LIST, [1] is the timestamp, [2] is tag id.
322 if (i == 2) {
Yao Chen80235402017-11-13 20:42:25 -0800323 mTagId = elem.data.int32;
Yangster-mace124e422018-08-16 10:30:28 -0700324 isKeyValuePairAtom = (mTagId == android::util::KEY_VALUE_PAIRS_ATOM);
Yangster-mac20877162017-12-22 17:19:39 -0800325 } else {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800326 if (depth < 0 || depth > 2) {
Yangster-mac20877162017-12-22 17:19:39 -0800327 return;
328 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800329
330 mValues.push_back(
331 FieldValue(Field(mTagId, pos, depth), Value((int32_t)elem.data.int32)));
332
333 pos[depth]++;
Yangster-mac20877162017-12-22 17:19:39 -0800334 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700335 break;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800336 case EVENT_TYPE_FLOAT: {
337 if (depth < 0 || depth > 2) {
338 ALOGE("Depth > 2. Not supported!");
339 return;
340 }
341
Yangster-mace124e422018-08-16 10:30:28 -0700342 // Handles the oneof field in KeyValuePair atom.
343 if (isKeyValuePairAtom && depth == 2) {
344 pos[depth] = 4;
345 }
346
Yao Chen8a8d16c2018-02-08 14:50:40 -0800347 mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(elem.data.float32)));
348
349 pos[depth]++;
350
351 } break;
352 case EVENT_TYPE_STRING: {
353 if (depth < 0 || depth > 2) {
354 ALOGE("Depth > 2. Not supported!");
355 return;
356 }
357
Yangster-mace124e422018-08-16 10:30:28 -0700358 // Handles the oneof field in KeyValuePair atom.
359 if (isKeyValuePairAtom && depth == 2) {
360 pos[depth] = 3;
361 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800362 mValues.push_back(FieldValue(Field(mTagId, pos, depth),
363 Value(string(elem.data.string, elem.len))));
364
365 pos[depth]++;
366
367 } break;
368 case EVENT_TYPE_LONG: {
Yangster-mac330af582018-02-08 15:24:38 -0800369 if (i == 1) {
370 mElapsedTimestampNs = elem.data.int64;
371 } else {
372 if (depth < 0 || depth > 2) {
373 ALOGE("Depth > 2. Not supported!");
374 return;
375 }
Yangster-mace124e422018-08-16 10:30:28 -0700376 // Handles the oneof field in KeyValuePair atom.
377 if (isKeyValuePairAtom && depth == 2) {
378 pos[depth] = 2;
379 }
Yangster-mac330af582018-02-08 15:24:38 -0800380 mValues.push_back(
381 FieldValue(Field(mTagId, pos, depth), Value((int64_t)elem.data.int64)));
382
383 pos[depth]++;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800384 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800385 } break;
386 case EVENT_TYPE_LIST:
387 depth++;
388 if (depth > 2) {
389 ALOGE("Depth > 2. Not supported!");
390 return;
391 }
392 pos[depth] = 1;
393
394 break;
395 case EVENT_TYPE_LIST_STOP: {
396 int prevDepth = depth;
397 depth--;
398 if (depth >= 0 && depth < 2) {
399 // Now go back to decorate the previous items that are last at prevDepth.
400 // So that we can later easily match them with Position=Last matchers.
401 pos[prevDepth]--;
402 int path = getEncodedField(pos, prevDepth, false);
Yao Chendb43afc2018-02-13 09:37:27 -0800403 for (auto it = mValues.rbegin(); it != mValues.rend(); ++it) {
404 if (it->mField.getDepth() >= prevDepth &&
405 it->mField.getPath(prevDepth) == path) {
406 it->mField.decorateLastPos(prevDepth);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800407 } else {
408 // Safe to break, because the items are in DFS order.
409 break;
410 }
Yangster-mac20877162017-12-22 17:19:39 -0800411 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800412 pos[depth]++;
Yangster-mac20877162017-12-22 17:19:39 -0800413 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700414 break;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800415 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700416 case EVENT_TYPE_UNKNOWN:
417 break;
418 default:
419 break;
420 }
Yao Chen80235402017-11-13 20:42:25 -0800421 i++;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700422 } while ((elem.type != EVENT_TYPE_UNKNOWN) && !elem.complete);
423}
424
425int64_t LogEvent::GetLong(size_t key, status_t* err) const {
Yao Chen5bfffb52018-06-21 16:58:51 -0700426 // TODO(b/110561208): encapsulate the magical operations in Field struct as static functions
Yao Chen8a8d16c2018-02-08 14:50:40 -0800427 int field = getSimpleField(key);
428 for (const auto& value : mValues) {
429 if (value.mField.getField() == field) {
Yao Chenab92a1f2018-02-13 15:17:55 -0800430 if (value.mValue.getType() == LONG) {
431 return value.mValue.long_value;
432 } else if (value.mValue.getType() == INT) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800433 return value.mValue.int_value;
434 } else {
435 *err = BAD_TYPE;
436 return 0;
437 }
438 }
439 if ((size_t)value.mField.getPosAtDepth(0) > key) {
440 break;
Yangster-mac20877162017-12-22 17:19:39 -0800441 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700442 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800443
444 *err = BAD_INDEX;
445 return 0;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700446}
447
Chenjie Yu80f91122018-01-31 20:24:50 -0800448int LogEvent::GetInt(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800449 int field = getSimpleField(key);
450 for (const auto& value : mValues) {
451 if (value.mField.getField() == field) {
452 if (value.mValue.getType() == INT) {
453 return value.mValue.int_value;
454 } else {
455 *err = BAD_TYPE;
456 return 0;
457 }
458 }
459 if ((size_t)value.mField.getPosAtDepth(0) > key) {
460 break;
461 }
462 }
463
Chenjie Yu80f91122018-01-31 20:24:50 -0800464 *err = BAD_INDEX;
465 return 0;
Chenjie Yu80f91122018-01-31 20:24:50 -0800466}
467
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700468const char* LogEvent::GetString(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800469 int field = getSimpleField(key);
470 for (const auto& value : mValues) {
471 if (value.mField.getField() == field) {
472 if (value.mValue.getType() == STRING) {
473 return value.mValue.str_value.c_str();
474 } else {
475 *err = BAD_TYPE;
476 return 0;
477 }
478 }
479 if ((size_t)value.mField.getPosAtDepth(0) > key) {
480 break;
Yangster-mac20877162017-12-22 17:19:39 -0800481 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700482 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800483
484 *err = BAD_INDEX;
485 return NULL;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700486}
487
488bool LogEvent::GetBool(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800489 int field = getSimpleField(key);
490 for (const auto& value : mValues) {
491 if (value.mField.getField() == field) {
492 if (value.mValue.getType() == INT) {
493 return value.mValue.int_value != 0;
494 } else if (value.mValue.getType() == LONG) {
495 return value.mValue.long_value != 0;
496 } else {
497 *err = BAD_TYPE;
498 return false;
499 }
500 }
501 if ((size_t)value.mField.getPosAtDepth(0) > key) {
502 break;
Yangster-mac20877162017-12-22 17:19:39 -0800503 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700504 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800505
506 *err = BAD_INDEX;
507 return false;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700508}
509
510float LogEvent::GetFloat(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800511 int field = getSimpleField(key);
512 for (const auto& value : mValues) {
513 if (value.mField.getField() == field) {
514 if (value.mValue.getType() == FLOAT) {
515 return value.mValue.float_value;
516 } else {
517 *err = BAD_TYPE;
518 return 0.0;
519 }
520 }
521 if ((size_t)value.mField.getPosAtDepth(0) > key) {
522 break;
Yangster-mac20877162017-12-22 17:19:39 -0800523 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700524 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700525
Yao Chen8a8d16c2018-02-08 14:50:40 -0800526 *err = BAD_INDEX;
527 return 0.0;
Yangster-macd40053e2018-01-09 16:29:22 -0800528}
529
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700530string LogEvent::ToString() const {
Yao Chen20e9e622018-02-28 11:18:51 -0800531 string result;
532 result += StringPrintf("{ %lld %lld (%d)", (long long)mLogdTimestampNs,
533 (long long)mElapsedTimestampNs, mTagId);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800534 for (const auto& value : mValues) {
Yao Chen20e9e622018-02-28 11:18:51 -0800535 result +=
536 StringPrintf("%#x", value.mField.getField()) + "->" + value.mValue.toString() + " ";
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700537 }
Yao Chen20e9e622018-02-28 11:18:51 -0800538 result += " }";
539 return result;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700540}
541
Yangster-mac20877162017-12-22 17:19:39 -0800542void LogEvent::ToProto(ProtoOutputStream& protoOutput) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800543 writeFieldValueTreeToStream(mTagId, getValues(), &protoOutput);
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700544}
545
546} // namespace statsd
547} // namespace os
548} // namespace android