blob: 9c9985ed271c29c56d97c29102185861d3b8e6f7 [file] [log] [blame]
Yangster-mac20877162017-12-22 17:19:39 -08001/*
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
Yangster-mac9def8e32018-04-17 13:55:51 -070017#include "hash.h"
Yangster-mac20877162017-12-22 17:19:39 -080018#include "stats_log_util.h"
19
Yao Chen8a8d16c2018-02-08 14:50:40 -080020#include <logd/LogEvent.h>
yro59cc24d2018-02-13 20:17:32 -080021#include <private/android_filesystem_config.h>
Yao Chen8a8d16c2018-02-08 14:50:40 -080022#include <utils/Log.h>
Yangster-mac20877162017-12-22 17:19:39 -080023#include <set>
24#include <stack>
Yangster-mac330af582018-02-08 15:24:38 -080025#include <utils/Log.h>
26#include <utils/SystemClock.h>
Yangster-mac20877162017-12-22 17:19:39 -080027
Yao Chenbbdd67d2018-10-24 12:15:56 -070028using android::util::AtomsInfo;
Yangster-mac20877162017-12-22 17:19:39 -080029using android::util::FIELD_COUNT_REPEATED;
30using android::util::FIELD_TYPE_BOOL;
Yao Chenbbdd67d2018-10-24 12:15:56 -070031using android::util::FIELD_TYPE_FIXED64;
Yangster-mac20877162017-12-22 17:19:39 -080032using android::util::FIELD_TYPE_FLOAT;
33using android::util::FIELD_TYPE_INT32;
34using android::util::FIELD_TYPE_INT64;
35using android::util::FIELD_TYPE_MESSAGE;
36using android::util::FIELD_TYPE_STRING;
Yao Chenbbdd67d2018-10-24 12:15:56 -070037using android::util::FIELD_TYPE_UINT64;
Yangster-mac20877162017-12-22 17:19:39 -080038using android::util::ProtoOutputStream;
39
40namespace android {
41namespace os {
42namespace statsd {
43
44// for DimensionsValue Proto
45const int DIMENSIONS_VALUE_FIELD = 1;
46const int DIMENSIONS_VALUE_VALUE_STR = 2;
47const int DIMENSIONS_VALUE_VALUE_INT = 3;
48const int DIMENSIONS_VALUE_VALUE_LONG = 4;
Yao Chen4c959cb2018-02-13 13:27:48 -080049// const int DIMENSIONS_VALUE_VALUE_BOOL = 5; // logd doesn't have bool data type.
Yangster-mac20877162017-12-22 17:19:39 -080050const int DIMENSIONS_VALUE_VALUE_FLOAT = 6;
51const int DIMENSIONS_VALUE_VALUE_TUPLE = 7;
Yangster-mac9def8e32018-04-17 13:55:51 -070052const int DIMENSIONS_VALUE_VALUE_STR_HASH = 8;
Yangster-mac20877162017-12-22 17:19:39 -080053
Yao Chen8a8d16c2018-02-08 14:50:40 -080054const int DIMENSIONS_VALUE_TUPLE_VALUE = 1;
55
Chenjie Yub038b702017-12-18 15:15:34 -080056// for PulledAtomStats proto
57const int FIELD_ID_PULLED_ATOM_STATS = 10;
58const int FIELD_ID_PULL_ATOM_ID = 1;
59const int FIELD_ID_TOTAL_PULL = 2;
60const int FIELD_ID_TOTAL_PULL_FROM_CACHE = 3;
61const int FIELD_ID_MIN_PULL_INTERVAL_SEC = 4;
Chenjie Yu48ed1cc2018-10-31 17:36:38 -070062const int FIELD_ID_AVERAGE_PULL_TIME_NANOS = 5;
63const int FIELD_ID_MAX_PULL_TIME_NANOS = 6;
64const int FIELD_ID_AVERAGE_PULL_DELAY_NANOS = 7;
65const int FIELD_ID_MAX_PULL_DELAY_NANOS = 8;
Chenjie Yuc715b9e2018-10-19 07:52:12 -070066const int FIELD_ID_DATA_ERROR = 9;
Chenjie Yu0bd73db2018-12-16 07:37:04 -080067const int FIELD_ID_PULL_TIMEOUT = 10;
68const int FIELD_ID_PULL_EXCEED_MAX_DELAY = 11;
Misha Wagner1eee2212019-01-22 11:47:11 +000069const int FIELD_ID_PULL_FAILED = 12;
70const int FIELD_ID_STATS_COMPANION_FAILED = 13;
71const int FIELD_ID_STATS_COMPANION_BINDER_TRANSACTION_FAILED = 14;
72const int FIELD_ID_EMPTY_DATA = 15;
73// for AtomMetricStats proto
74const int FIELD_ID_ATOM_METRIC_STATS = 17;
75const int FIELD_ID_METRIC_ID = 1;
76const int FIELD_ID_HARD_DIMENSION_LIMIT_REACHED = 2;
77const int FIELD_ID_LATE_LOG_EVENT_SKIPPED = 3;
78const int FIELD_ID_SKIPPED_FORWARD_BUCKETS = 4;
79const int FIELD_ID_BAD_VALUE_TYPE = 5;
80const int FIELD_ID_CONDITION_CHANGE_IN_NEXT_BUCKET = 6;
Yangster-mac9def8e32018-04-17 13:55:51 -070081
Yao Chen8a8d16c2018-02-08 14:50:40 -080082namespace {
Chenjie Yub038b702017-12-18 15:15:34 -080083
Yao Chen8a8d16c2018-02-08 14:50:40 -080084void writeDimensionToProtoHelper(const std::vector<FieldValue>& dims, size_t* index, int depth,
Yangster-mac9def8e32018-04-17 13:55:51 -070085 int prefix, std::set<string> *str_set,
86 ProtoOutputStream* protoOutput) {
Yao Chen8a8d16c2018-02-08 14:50:40 -080087 size_t count = dims.size();
88 while (*index < count) {
89 const auto& dim = dims[*index];
90 const int valueDepth = dim.mField.getDepth();
91 const int valuePrefix = dim.mField.getPrefix(depth);
92 const int fieldNum = dim.mField.getPosAtDepth(depth);
93 if (valueDepth > 2) {
94 ALOGE("Depth > 2 not supported");
95 return;
96 }
97
98 if (depth == valueDepth && valuePrefix == prefix) {
Yi Jin5ee07872018-03-05 18:18:27 -080099 uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
Yao Chen8a8d16c2018-02-08 14:50:40 -0800100 DIMENSIONS_VALUE_TUPLE_VALUE);
101 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, fieldNum);
102 switch (dim.mValue.getType()) {
103 case INT:
104 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_VALUE_INT,
105 dim.mValue.int_value);
106 break;
107 case LONG:
108 protoOutput->write(FIELD_TYPE_INT64 | DIMENSIONS_VALUE_VALUE_LONG,
109 (long long)dim.mValue.long_value);
110 break;
111 case FLOAT:
112 protoOutput->write(FIELD_TYPE_FLOAT | DIMENSIONS_VALUE_VALUE_FLOAT,
113 dim.mValue.float_value);
114 break;
115 case STRING:
Yangster-mac9def8e32018-04-17 13:55:51 -0700116 if (str_set == nullptr) {
117 protoOutput->write(FIELD_TYPE_STRING | DIMENSIONS_VALUE_VALUE_STR,
118 dim.mValue.str_value);
119 } else {
120 str_set->insert(dim.mValue.str_value);
121 protoOutput->write(
122 FIELD_TYPE_UINT64 | DIMENSIONS_VALUE_VALUE_STR_HASH,
123 (long long)Hash64(dim.mValue.str_value));
124 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800125 break;
126 default:
127 break;
128 }
129 if (token != 0) {
130 protoOutput->end(token);
131 }
132 (*index)++;
133 } else if (valueDepth > depth && valuePrefix == prefix) {
134 // Writing the sub tree
Yi Jin5ee07872018-03-05 18:18:27 -0800135 uint64_t dimensionToken = protoOutput->start(
Yao Chen8a8d16c2018-02-08 14:50:40 -0800136 FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | DIMENSIONS_VALUE_TUPLE_VALUE);
137 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, fieldNum);
Yi Jin5ee07872018-03-05 18:18:27 -0800138 uint64_t tupleToken =
Yao Chen8a8d16c2018-02-08 14:50:40 -0800139 protoOutput->start(FIELD_TYPE_MESSAGE | DIMENSIONS_VALUE_VALUE_TUPLE);
140 writeDimensionToProtoHelper(dims, index, valueDepth, dim.mField.getPrefix(valueDepth),
Yangster-mac9def8e32018-04-17 13:55:51 -0700141 str_set, protoOutput);
142 protoOutput->end(tupleToken);
143 protoOutput->end(dimensionToken);
144 } else {
145 // Done with the prev sub tree
146 return;
147 }
148 }
149}
150
151void writeDimensionLeafToProtoHelper(const std::vector<FieldValue>& dims,
152 const int dimensionLeafField,
153 size_t* index, int depth,
154 int prefix, std::set<string> *str_set,
155 ProtoOutputStream* protoOutput) {
156 size_t count = dims.size();
157 while (*index < count) {
158 const auto& dim = dims[*index];
159 const int valueDepth = dim.mField.getDepth();
160 const int valuePrefix = dim.mField.getPrefix(depth);
161 if (valueDepth > 2) {
162 ALOGE("Depth > 2 not supported");
163 return;
164 }
165
166 if (depth == valueDepth && valuePrefix == prefix) {
167 uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
168 dimensionLeafField);
169 switch (dim.mValue.getType()) {
170 case INT:
171 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_VALUE_INT,
172 dim.mValue.int_value);
173 break;
174 case LONG:
175 protoOutput->write(FIELD_TYPE_INT64 | DIMENSIONS_VALUE_VALUE_LONG,
176 (long long)dim.mValue.long_value);
177 break;
178 case FLOAT:
179 protoOutput->write(FIELD_TYPE_FLOAT | DIMENSIONS_VALUE_VALUE_FLOAT,
180 dim.mValue.float_value);
181 break;
182 case STRING:
183 if (str_set == nullptr) {
184 protoOutput->write(FIELD_TYPE_STRING | DIMENSIONS_VALUE_VALUE_STR,
185 dim.mValue.str_value);
186 } else {
187 str_set->insert(dim.mValue.str_value);
188 protoOutput->write(
189 FIELD_TYPE_UINT64 | DIMENSIONS_VALUE_VALUE_STR_HASH,
190 (long long)Hash64(dim.mValue.str_value));
191 }
192 break;
193 default:
194 break;
195 }
196 if (token != 0) {
197 protoOutput->end(token);
198 }
199 (*index)++;
200 } else if (valueDepth > depth && valuePrefix == prefix) {
201 writeDimensionLeafToProtoHelper(dims, dimensionLeafField,
202 index, valueDepth, dim.mField.getPrefix(valueDepth),
203 str_set, protoOutput);
204 } else {
205 // Done with the prev sub tree
206 return;
207 }
208 }
209}
210
211void writeDimensionPathToProtoHelper(const std::vector<Matcher>& fieldMatchers,
212 size_t* index, int depth, int prefix,
213 ProtoOutputStream* protoOutput) {
214 size_t count = fieldMatchers.size();
215 while (*index < count) {
216 const Field& field = fieldMatchers[*index].mMatcher;
217 const int valueDepth = field.getDepth();
218 const int valuePrefix = field.getPrefix(depth);
219 const int fieldNum = field.getPosAtDepth(depth);
220 if (valueDepth > 2) {
221 ALOGE("Depth > 2 not supported");
222 return;
223 }
224
225 if (depth == valueDepth && valuePrefix == prefix) {
226 uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
227 DIMENSIONS_VALUE_TUPLE_VALUE);
228 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, fieldNum);
229 if (token != 0) {
230 protoOutput->end(token);
231 }
232 (*index)++;
233 } else if (valueDepth > depth && valuePrefix == prefix) {
234 // Writing the sub tree
235 uint64_t dimensionToken = protoOutput->start(
236 FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | DIMENSIONS_VALUE_TUPLE_VALUE);
237 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, fieldNum);
238 uint64_t tupleToken =
239 protoOutput->start(FIELD_TYPE_MESSAGE | DIMENSIONS_VALUE_VALUE_TUPLE);
240 writeDimensionPathToProtoHelper(fieldMatchers, index, valueDepth,
241 field.getPrefix(valueDepth), protoOutput);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800242 protoOutput->end(tupleToken);
243 protoOutput->end(dimensionToken);
244 } else {
245 // Done with the prev sub tree
246 return;
247 }
248 }
249}
250
251} // namespace
252
Yangster-mac9def8e32018-04-17 13:55:51 -0700253void writeDimensionToProto(const HashableDimensionKey& dimension, std::set<string> *str_set,
254 ProtoOutputStream* protoOutput) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800255 if (dimension.getValues().size() == 0) {
Yangster-mac93694462018-01-22 20:49:31 -0800256 return;
257 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800258 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD,
259 dimension.getValues()[0].mField.getTag());
Yi Jin5ee07872018-03-05 18:18:27 -0800260 uint64_t topToken = protoOutput->start(FIELD_TYPE_MESSAGE | DIMENSIONS_VALUE_VALUE_TUPLE);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800261 size_t index = 0;
Yangster-mac9def8e32018-04-17 13:55:51 -0700262 writeDimensionToProtoHelper(dimension.getValues(), &index, 0, 0, str_set, protoOutput);
263 protoOutput->end(topToken);
264}
265
266void writeDimensionLeafNodesToProto(const HashableDimensionKey& dimension,
267 const int dimensionLeafFieldId,
268 std::set<string> *str_set,
269 ProtoOutputStream* protoOutput) {
270 if (dimension.getValues().size() == 0) {
271 return;
272 }
273 size_t index = 0;
274 writeDimensionLeafToProtoHelper(dimension.getValues(), dimensionLeafFieldId,
275 &index, 0, 0, str_set, protoOutput);
276}
277
278void writeDimensionPathToProto(const std::vector<Matcher>& fieldMatchers,
279 ProtoOutputStream* protoOutput) {
280 if (fieldMatchers.size() == 0) {
281 return;
282 }
283 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD,
284 fieldMatchers[0].mMatcher.getTag());
285 uint64_t topToken = protoOutput->start(FIELD_TYPE_MESSAGE | DIMENSIONS_VALUE_VALUE_TUPLE);
286 size_t index = 0;
287 writeDimensionPathToProtoHelper(fieldMatchers, &index, 0, 0, protoOutput);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800288 protoOutput->end(topToken);
Yangster-mac20877162017-12-22 17:19:39 -0800289}
290
Yao Chen8a8d16c2018-02-08 14:50:40 -0800291// Supported Atoms format
292// XYZ_Atom {
293// repeated SubMsg field_1 = 1;
294// SubMsg2 field_2 = 2;
295// int32/float/string/int63 field_3 = 3;
296// }
297// logd's msg format, doesn't allow us to distinguish between the 2 cases below
298// Case (1):
299// Atom {
300// SubMsg {
301// int i = 1;
302// int j = 2;
303// }
304// repeated SubMsg
305// }
306//
307// and case (2):
308// Atom {
309// SubMsg {
310// repeated int i = 1;
311// repeated int j = 2;
312// }
313// optional SubMsg = 1;
314// }
315//
316//
Yao Chenbbdd67d2018-10-24 12:15:56 -0700317void writeFieldValueTreeToStreamHelper(int tagId, const std::vector<FieldValue>& dims,
318 size_t* index, int depth, int prefix,
319 ProtoOutputStream* protoOutput) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800320 size_t count = dims.size();
321 while (*index < count) {
322 const auto& dim = dims[*index];
323 const int valueDepth = dim.mField.getDepth();
324 const int valuePrefix = dim.mField.getPrefix(depth);
325 const int fieldNum = dim.mField.getPosAtDepth(depth);
326 if (valueDepth > 2) {
327 ALOGE("Depth > 2 not supported");
328 return;
Yangster-mac20877162017-12-22 17:19:39 -0800329 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800330
331 if (depth == valueDepth && valuePrefix == prefix) {
332 switch (dim.mValue.getType()) {
333 case INT:
334 protoOutput->write(FIELD_TYPE_INT32 | fieldNum, dim.mValue.int_value);
335 break;
336 case LONG:
337 protoOutput->write(FIELD_TYPE_INT64 | fieldNum,
338 (long long)dim.mValue.long_value);
339 break;
340 case FLOAT:
341 protoOutput->write(FIELD_TYPE_FLOAT | fieldNum, dim.mValue.float_value);
342 break;
Yao Chenbbdd67d2018-10-24 12:15:56 -0700343 case STRING: {
344 bool isBytesField = false;
345 // Bytes field is logged via string format in log_msg format. So here we check
346 // if this string field is a byte field.
347 std::map<int, std::vector<int>>::const_iterator itr;
348 if (depth == 0 && (itr = AtomsInfo::kBytesFieldAtoms.find(tagId)) !=
349 AtomsInfo::kBytesFieldAtoms.end()) {
350 const std::vector<int>& bytesFields = itr->second;
351 for (int bytesField : bytesFields) {
352 if (bytesField == fieldNum) {
353 // This is a bytes field
354 isBytesField = true;
355 break;
356 }
357 }
358 }
359 if (isBytesField) {
Yao Chen8e6f9982018-11-29 09:39:45 -0800360 if (dim.mValue.str_value.length() > 0) {
361 protoOutput->write(FIELD_TYPE_MESSAGE | fieldNum,
362 (const char*)dim.mValue.str_value.c_str(),
363 dim.mValue.str_value.length());
364 }
Yao Chenbbdd67d2018-10-24 12:15:56 -0700365 } else {
366 protoOutput->write(FIELD_TYPE_STRING | fieldNum, dim.mValue.str_value);
367 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800368 break;
Yao Chenbbdd67d2018-10-24 12:15:56 -0700369 }
Chenjie Yu12e5e672018-09-14 15:54:59 -0700370 case STORAGE:
371 protoOutput->write(FIELD_TYPE_MESSAGE | fieldNum,
372 (const char*)dim.mValue.storage_value.data(),
373 dim.mValue.storage_value.size());
374 break;
Yangster-macf5204922018-02-23 13:08:03 -0800375 default:
376 break;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800377 }
378 (*index)++;
379 } else if (valueDepth > depth && valuePrefix == prefix) {
380 // Writing the sub tree
Yi Jin5ee07872018-03-05 18:18:27 -0800381 uint64_t msg_token = 0ULL;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800382 if (valueDepth == depth + 2) {
383 msg_token =
384 protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | fieldNum);
385 } else if (valueDepth == depth + 1) {
386 msg_token = protoOutput->start(FIELD_TYPE_MESSAGE | fieldNum);
387 }
388 // Directly jump to the leaf value because the repeated position field is implied
389 // by the position of the sub msg in the parent field.
Yao Chenbbdd67d2018-10-24 12:15:56 -0700390 writeFieldValueTreeToStreamHelper(tagId, dims, index, valueDepth,
Yao Chen8a8d16c2018-02-08 14:50:40 -0800391 dim.mField.getPrefix(valueDepth), protoOutput);
392 if (msg_token != 0) {
393 protoOutput->end(msg_token);
394 }
395 } else {
396 // Done with the prev sub tree
397 return;
398 }
Yangster-mac20877162017-12-22 17:19:39 -0800399 }
400}
401
Yao Chen8a8d16c2018-02-08 14:50:40 -0800402void writeFieldValueTreeToStream(int tagId, const std::vector<FieldValue>& values,
Yangster-mac20877162017-12-22 17:19:39 -0800403 util::ProtoOutputStream* protoOutput) {
Yi Jin5ee07872018-03-05 18:18:27 -0800404 uint64_t atomToken = protoOutput->start(FIELD_TYPE_MESSAGE | tagId);
Yangster-mac20877162017-12-22 17:19:39 -0800405
Yao Chen8a8d16c2018-02-08 14:50:40 -0800406 size_t index = 0;
Yao Chenbbdd67d2018-10-24 12:15:56 -0700407 writeFieldValueTreeToStreamHelper(tagId, values, &index, 0, 0, protoOutput);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800408 protoOutput->end(atomToken);
Yangster-macb8144812018-01-04 10:56:23 -0800409}
Yangster-mac20877162017-12-22 17:19:39 -0800410
yro59cc24d2018-02-13 20:17:32 -0800411int64_t TimeUnitToBucketSizeInMillisGuardrailed(int uid, TimeUnit unit) {
412 int64_t bucketSizeMillis = TimeUnitToBucketSizeInMillis(unit);
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700413 if (bucketSizeMillis > 1000 && bucketSizeMillis < 5 * 60 * 1000LL && uid != AID_SHELL &&
414 uid != AID_ROOT) {
yro59cc24d2018-02-13 20:17:32 -0800415 bucketSizeMillis = 5 * 60 * 1000LL;
416 }
417 return bucketSizeMillis;
418}
419
Yangster-macb8144812018-01-04 10:56:23 -0800420int64_t TimeUnitToBucketSizeInMillis(TimeUnit unit) {
421 switch (unit) {
422 case ONE_MINUTE:
423 return 60 * 1000LL;
424 case FIVE_MINUTES:
425 return 5 * 60 * 1000LL;
426 case TEN_MINUTES:
427 return 10 * 60 * 1000LL;
428 case THIRTY_MINUTES:
429 return 30 * 60 * 1000LL;
430 case ONE_HOUR:
431 return 60 * 60 * 1000LL;
432 case THREE_HOURS:
433 return 3 * 60 * 60 * 1000LL;
434 case SIX_HOURS:
435 return 6 * 60 * 60 * 1000LL;
436 case TWELVE_HOURS:
437 return 12 * 60 * 60 * 1000LL;
438 case ONE_DAY:
439 return 24 * 60 * 60 * 1000LL;
440 case CTS:
441 return 1000;
442 case TIME_UNIT_UNSPECIFIED:
443 default:
444 return -1;
445 }
Yangster-mac20877162017-12-22 17:19:39 -0800446}
447
Chenjie Yub038b702017-12-18 15:15:34 -0800448void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>& pair,
449 util::ProtoOutputStream* protoOutput) {
Yi Jin5ee07872018-03-05 18:18:27 -0800450 uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_PULLED_ATOM_STATS |
Chenjie Yub038b702017-12-18 15:15:34 -0800451 FIELD_COUNT_REPEATED);
452 protoOutput->write(FIELD_TYPE_INT32 | FIELD_ID_PULL_ATOM_ID, (int32_t)pair.first);
453 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_TOTAL_PULL, (long long)pair.second.totalPull);
454 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_TOTAL_PULL_FROM_CACHE,
455 (long long)pair.second.totalPullFromCache);
456 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MIN_PULL_INTERVAL_SEC,
457 (long long)pair.second.minPullIntervalSec);
Chenjie Yu48ed1cc2018-10-31 17:36:38 -0700458 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_AVERAGE_PULL_TIME_NANOS,
459 (long long)pair.second.avgPullTimeNs);
460 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MAX_PULL_TIME_NANOS,
461 (long long)pair.second.maxPullTimeNs);
462 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_AVERAGE_PULL_DELAY_NANOS,
463 (long long)pair.second.avgPullDelayNs);
464 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MAX_PULL_DELAY_NANOS,
465 (long long)pair.second.maxPullDelayNs);
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700466 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_DATA_ERROR, (long long)pair.second.dataError);
Chenjie Yu0bd73db2018-12-16 07:37:04 -0800467 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_TIMEOUT,
468 (long long)pair.second.pullTimeout);
469 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_EXCEED_MAX_DELAY,
470 (long long)pair.second.pullExceedMaxDelay);
Misha Wagner1eee2212019-01-22 11:47:11 +0000471 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_FAILED,
472 (long long)pair.second.pullFailed);
473 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_STATS_COMPANION_FAILED,
474 (long long)pair.second.statsCompanionPullFailed);
475 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_STATS_COMPANION_BINDER_TRANSACTION_FAILED,
476 (long long)pair.second.statsCompanionPullBinderTransactionFailed);
477 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_EMPTY_DATA,
478 (long long)pair.second.emptyData);
479 protoOutput->end(token);
480}
481
482void writeAtomMetricStatsToStream(const std::pair<int, StatsdStats::AtomMetricStats> &pair,
483 util::ProtoOutputStream *protoOutput) {
484 uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOM_METRIC_STATS |
485 FIELD_COUNT_REPEATED);
486 protoOutput->write(FIELD_TYPE_INT32 | FIELD_ID_METRIC_ID, (int32_t)pair.first);
487 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_HARD_DIMENSION_LIMIT_REACHED,
488 (long long)pair.second.hardDimensionLimitReached);
489 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_LATE_LOG_EVENT_SKIPPED,
490 (long long)pair.second.lateLogEventSkipped);
491 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_SKIPPED_FORWARD_BUCKETS,
492 (long long)pair.second.skippedForwardBuckets);
493 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BAD_VALUE_TYPE,
494 (long long)pair.second.badValueType);
495 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_CONDITION_CHANGE_IN_NEXT_BUCKET,
496 (long long)pair.second.conditionChangeInNextBucket);
Chenjie Yub038b702017-12-18 15:15:34 -0800497 protoOutput->end(token);
498}
499
Yangster-mac330af582018-02-08 15:24:38 -0800500int64_t getElapsedRealtimeNs() {
501 return ::android::elapsedRealtimeNano();
502}
503
504int64_t getElapsedRealtimeSec() {
505 return ::android::elapsedRealtimeNano() / NS_PER_SEC;
506}
507
508int64_t getElapsedRealtimeMillis() {
509 return ::android::elapsedRealtime();
510}
511
512int64_t getWallClockNs() {
513 return time(nullptr) * NS_PER_SEC;
514}
515
516int64_t getWallClockSec() {
517 return time(nullptr);
518}
519
520int64_t getWallClockMillis() {
521 return time(nullptr) * MS_PER_SEC;
522}
523
Yangster-macd5c35622018-02-02 10:33:25 -0800524int64_t truncateTimestampNsToFiveMinutes(int64_t timestampNs) {
525 return timestampNs / NS_PER_SEC / (5 * 60) * NS_PER_SEC * (5 * 60);
526}
527
Yangster-mac9def8e32018-04-17 13:55:51 -0700528int64_t NanoToMillis(const int64_t nano) {
529 return nano / 1000000;
530}
531
532int64_t MillisToNano(const int64_t millis) {
533 return millis * 1000000;
534}
535
Yangster-mac20877162017-12-22 17:19:39 -0800536} // namespace statsd
537} // namespace os
yro59cc24d2018-02-13 20:17:32 -0800538} // namespace android