blob: 31f160d9994461708c64ef79bf02aeba41e0fbb3 [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;
Tej Singha0c89dd2019-01-25 16:39:18 -080073const int FIELD_ID_PULL_REGISTERED_COUNT = 16;
74const int FIELD_ID_PULL_UNREGISTERED_COUNT = 17;
Misha Wagner1eee2212019-01-22 11:47:11 +000075// for AtomMetricStats proto
76const int FIELD_ID_ATOM_METRIC_STATS = 17;
77const int FIELD_ID_METRIC_ID = 1;
78const int FIELD_ID_HARD_DIMENSION_LIMIT_REACHED = 2;
79const int FIELD_ID_LATE_LOG_EVENT_SKIPPED = 3;
80const int FIELD_ID_SKIPPED_FORWARD_BUCKETS = 4;
81const int FIELD_ID_BAD_VALUE_TYPE = 5;
82const int FIELD_ID_CONDITION_CHANGE_IN_NEXT_BUCKET = 6;
Olivier Gaillard9a5d3592019-02-05 15:12:39 +000083const int FIELD_ID_INVALIDATED_BUCKET = 7;
Olivier Gaillard320952b2019-02-06 13:57:24 +000084const int FIELD_ID_BUCKET_DROPPED = 8;
Olivier Gaillard3ba2e932019-02-08 14:25:35 +000085const int FIELD_ID_MIN_BUCKET_BOUNDARY_DELAY_NS = 9;
86const int FIELD_ID_MAX_BUCKET_BOUNDARY_DELAY_NS = 10;
Olivier Gaillarde63d9e02019-02-12 14:43:59 +000087const int FIELD_ID_BUCKET_UNKNOWN_CONDITION = 11;
Olivier Gaillardf248c0d2019-02-21 15:56:58 +000088const int FIELD_ID_BUCKET_COUNT = 12;
Yangster-mac9def8e32018-04-17 13:55:51 -070089
Yao Chen8a8d16c2018-02-08 14:50:40 -080090namespace {
Chenjie Yub038b702017-12-18 15:15:34 -080091
Yao Chen8a8d16c2018-02-08 14:50:40 -080092void writeDimensionToProtoHelper(const std::vector<FieldValue>& dims, size_t* index, int depth,
Yangster-mac9def8e32018-04-17 13:55:51 -070093 int prefix, std::set<string> *str_set,
94 ProtoOutputStream* protoOutput) {
Yao Chen8a8d16c2018-02-08 14:50:40 -080095 size_t count = dims.size();
96 while (*index < count) {
97 const auto& dim = dims[*index];
98 const int valueDepth = dim.mField.getDepth();
99 const int valuePrefix = dim.mField.getPrefix(depth);
100 const int fieldNum = dim.mField.getPosAtDepth(depth);
101 if (valueDepth > 2) {
102 ALOGE("Depth > 2 not supported");
103 return;
104 }
105
106 if (depth == valueDepth && valuePrefix == prefix) {
Yi Jin5ee07872018-03-05 18:18:27 -0800107 uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
Yao Chen8a8d16c2018-02-08 14:50:40 -0800108 DIMENSIONS_VALUE_TUPLE_VALUE);
109 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, fieldNum);
110 switch (dim.mValue.getType()) {
111 case INT:
112 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_VALUE_INT,
113 dim.mValue.int_value);
114 break;
115 case LONG:
116 protoOutput->write(FIELD_TYPE_INT64 | DIMENSIONS_VALUE_VALUE_LONG,
117 (long long)dim.mValue.long_value);
118 break;
119 case FLOAT:
120 protoOutput->write(FIELD_TYPE_FLOAT | DIMENSIONS_VALUE_VALUE_FLOAT,
121 dim.mValue.float_value);
122 break;
123 case STRING:
Yangster-mac9def8e32018-04-17 13:55:51 -0700124 if (str_set == nullptr) {
125 protoOutput->write(FIELD_TYPE_STRING | DIMENSIONS_VALUE_VALUE_STR,
126 dim.mValue.str_value);
127 } else {
128 str_set->insert(dim.mValue.str_value);
129 protoOutput->write(
130 FIELD_TYPE_UINT64 | DIMENSIONS_VALUE_VALUE_STR_HASH,
131 (long long)Hash64(dim.mValue.str_value));
132 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800133 break;
134 default:
135 break;
136 }
137 if (token != 0) {
138 protoOutput->end(token);
139 }
140 (*index)++;
141 } else if (valueDepth > depth && valuePrefix == prefix) {
142 // Writing the sub tree
Yi Jin5ee07872018-03-05 18:18:27 -0800143 uint64_t dimensionToken = protoOutput->start(
Yao Chen8a8d16c2018-02-08 14:50:40 -0800144 FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | DIMENSIONS_VALUE_TUPLE_VALUE);
145 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, fieldNum);
Yi Jin5ee07872018-03-05 18:18:27 -0800146 uint64_t tupleToken =
Yao Chen8a8d16c2018-02-08 14:50:40 -0800147 protoOutput->start(FIELD_TYPE_MESSAGE | DIMENSIONS_VALUE_VALUE_TUPLE);
148 writeDimensionToProtoHelper(dims, index, valueDepth, dim.mField.getPrefix(valueDepth),
Yangster-mac9def8e32018-04-17 13:55:51 -0700149 str_set, protoOutput);
150 protoOutput->end(tupleToken);
151 protoOutput->end(dimensionToken);
152 } else {
153 // Done with the prev sub tree
154 return;
155 }
156 }
157}
158
159void writeDimensionLeafToProtoHelper(const std::vector<FieldValue>& dims,
160 const int dimensionLeafField,
161 size_t* index, int depth,
162 int prefix, std::set<string> *str_set,
163 ProtoOutputStream* protoOutput) {
164 size_t count = dims.size();
165 while (*index < count) {
166 const auto& dim = dims[*index];
167 const int valueDepth = dim.mField.getDepth();
168 const int valuePrefix = dim.mField.getPrefix(depth);
169 if (valueDepth > 2) {
170 ALOGE("Depth > 2 not supported");
171 return;
172 }
173
174 if (depth == valueDepth && valuePrefix == prefix) {
175 uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
176 dimensionLeafField);
177 switch (dim.mValue.getType()) {
178 case INT:
179 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_VALUE_INT,
180 dim.mValue.int_value);
181 break;
182 case LONG:
183 protoOutput->write(FIELD_TYPE_INT64 | DIMENSIONS_VALUE_VALUE_LONG,
184 (long long)dim.mValue.long_value);
185 break;
186 case FLOAT:
187 protoOutput->write(FIELD_TYPE_FLOAT | DIMENSIONS_VALUE_VALUE_FLOAT,
188 dim.mValue.float_value);
189 break;
190 case STRING:
191 if (str_set == nullptr) {
192 protoOutput->write(FIELD_TYPE_STRING | DIMENSIONS_VALUE_VALUE_STR,
193 dim.mValue.str_value);
194 } else {
195 str_set->insert(dim.mValue.str_value);
196 protoOutput->write(
197 FIELD_TYPE_UINT64 | DIMENSIONS_VALUE_VALUE_STR_HASH,
198 (long long)Hash64(dim.mValue.str_value));
199 }
200 break;
201 default:
202 break;
203 }
204 if (token != 0) {
205 protoOutput->end(token);
206 }
207 (*index)++;
208 } else if (valueDepth > depth && valuePrefix == prefix) {
209 writeDimensionLeafToProtoHelper(dims, dimensionLeafField,
210 index, valueDepth, dim.mField.getPrefix(valueDepth),
211 str_set, protoOutput);
212 } else {
213 // Done with the prev sub tree
214 return;
215 }
216 }
217}
218
219void writeDimensionPathToProtoHelper(const std::vector<Matcher>& fieldMatchers,
220 size_t* index, int depth, int prefix,
221 ProtoOutputStream* protoOutput) {
222 size_t count = fieldMatchers.size();
223 while (*index < count) {
224 const Field& field = fieldMatchers[*index].mMatcher;
225 const int valueDepth = field.getDepth();
226 const int valuePrefix = field.getPrefix(depth);
227 const int fieldNum = field.getPosAtDepth(depth);
228 if (valueDepth > 2) {
229 ALOGE("Depth > 2 not supported");
230 return;
231 }
232
233 if (depth == valueDepth && valuePrefix == prefix) {
234 uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
235 DIMENSIONS_VALUE_TUPLE_VALUE);
236 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, fieldNum);
237 if (token != 0) {
238 protoOutput->end(token);
239 }
240 (*index)++;
241 } else if (valueDepth > depth && valuePrefix == prefix) {
242 // Writing the sub tree
243 uint64_t dimensionToken = protoOutput->start(
244 FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | DIMENSIONS_VALUE_TUPLE_VALUE);
245 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, fieldNum);
246 uint64_t tupleToken =
247 protoOutput->start(FIELD_TYPE_MESSAGE | DIMENSIONS_VALUE_VALUE_TUPLE);
248 writeDimensionPathToProtoHelper(fieldMatchers, index, valueDepth,
249 field.getPrefix(valueDepth), protoOutput);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800250 protoOutput->end(tupleToken);
251 protoOutput->end(dimensionToken);
252 } else {
253 // Done with the prev sub tree
254 return;
255 }
256 }
257}
258
259} // namespace
260
Yangster-mac9def8e32018-04-17 13:55:51 -0700261void writeDimensionToProto(const HashableDimensionKey& dimension, std::set<string> *str_set,
262 ProtoOutputStream* protoOutput) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800263 if (dimension.getValues().size() == 0) {
Yangster-mac93694462018-01-22 20:49:31 -0800264 return;
265 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800266 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD,
267 dimension.getValues()[0].mField.getTag());
Yi Jin5ee07872018-03-05 18:18:27 -0800268 uint64_t topToken = protoOutput->start(FIELD_TYPE_MESSAGE | DIMENSIONS_VALUE_VALUE_TUPLE);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800269 size_t index = 0;
Yangster-mac9def8e32018-04-17 13:55:51 -0700270 writeDimensionToProtoHelper(dimension.getValues(), &index, 0, 0, str_set, protoOutput);
271 protoOutput->end(topToken);
272}
273
274void writeDimensionLeafNodesToProto(const HashableDimensionKey& dimension,
275 const int dimensionLeafFieldId,
276 std::set<string> *str_set,
277 ProtoOutputStream* protoOutput) {
278 if (dimension.getValues().size() == 0) {
279 return;
280 }
281 size_t index = 0;
282 writeDimensionLeafToProtoHelper(dimension.getValues(), dimensionLeafFieldId,
283 &index, 0, 0, str_set, protoOutput);
284}
285
286void writeDimensionPathToProto(const std::vector<Matcher>& fieldMatchers,
287 ProtoOutputStream* protoOutput) {
288 if (fieldMatchers.size() == 0) {
289 return;
290 }
291 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD,
292 fieldMatchers[0].mMatcher.getTag());
293 uint64_t topToken = protoOutput->start(FIELD_TYPE_MESSAGE | DIMENSIONS_VALUE_VALUE_TUPLE);
294 size_t index = 0;
295 writeDimensionPathToProtoHelper(fieldMatchers, &index, 0, 0, protoOutput);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800296 protoOutput->end(topToken);
Yangster-mac20877162017-12-22 17:19:39 -0800297}
298
Yao Chen8a8d16c2018-02-08 14:50:40 -0800299// Supported Atoms format
300// XYZ_Atom {
301// repeated SubMsg field_1 = 1;
302// SubMsg2 field_2 = 2;
303// int32/float/string/int63 field_3 = 3;
304// }
305// logd's msg format, doesn't allow us to distinguish between the 2 cases below
306// Case (1):
307// Atom {
308// SubMsg {
309// int i = 1;
310// int j = 2;
311// }
312// repeated SubMsg
313// }
314//
315// and case (2):
316// Atom {
317// SubMsg {
318// repeated int i = 1;
319// repeated int j = 2;
320// }
321// optional SubMsg = 1;
322// }
323//
324//
Yao Chenbbdd67d2018-10-24 12:15:56 -0700325void writeFieldValueTreeToStreamHelper(int tagId, const std::vector<FieldValue>& dims,
326 size_t* index, int depth, int prefix,
327 ProtoOutputStream* protoOutput) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800328 size_t count = dims.size();
329 while (*index < count) {
330 const auto& dim = dims[*index];
331 const int valueDepth = dim.mField.getDepth();
332 const int valuePrefix = dim.mField.getPrefix(depth);
333 const int fieldNum = dim.mField.getPosAtDepth(depth);
334 if (valueDepth > 2) {
335 ALOGE("Depth > 2 not supported");
336 return;
Yangster-mac20877162017-12-22 17:19:39 -0800337 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800338
339 if (depth == valueDepth && valuePrefix == prefix) {
340 switch (dim.mValue.getType()) {
341 case INT:
342 protoOutput->write(FIELD_TYPE_INT32 | fieldNum, dim.mValue.int_value);
343 break;
344 case LONG:
345 protoOutput->write(FIELD_TYPE_INT64 | fieldNum,
346 (long long)dim.mValue.long_value);
347 break;
348 case FLOAT:
349 protoOutput->write(FIELD_TYPE_FLOAT | fieldNum, dim.mValue.float_value);
350 break;
Yao Chenbbdd67d2018-10-24 12:15:56 -0700351 case STRING: {
352 bool isBytesField = false;
353 // Bytes field is logged via string format in log_msg format. So here we check
354 // if this string field is a byte field.
355 std::map<int, std::vector<int>>::const_iterator itr;
356 if (depth == 0 && (itr = AtomsInfo::kBytesFieldAtoms.find(tagId)) !=
357 AtomsInfo::kBytesFieldAtoms.end()) {
358 const std::vector<int>& bytesFields = itr->second;
359 for (int bytesField : bytesFields) {
360 if (bytesField == fieldNum) {
361 // This is a bytes field
362 isBytesField = true;
363 break;
364 }
365 }
366 }
367 if (isBytesField) {
Yao Chen8e6f9982018-11-29 09:39:45 -0800368 if (dim.mValue.str_value.length() > 0) {
369 protoOutput->write(FIELD_TYPE_MESSAGE | fieldNum,
370 (const char*)dim.mValue.str_value.c_str(),
371 dim.mValue.str_value.length());
372 }
Yao Chenbbdd67d2018-10-24 12:15:56 -0700373 } else {
374 protoOutput->write(FIELD_TYPE_STRING | fieldNum, dim.mValue.str_value);
375 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800376 break;
Yao Chenbbdd67d2018-10-24 12:15:56 -0700377 }
Chenjie Yu12e5e672018-09-14 15:54:59 -0700378 case STORAGE:
379 protoOutput->write(FIELD_TYPE_MESSAGE | fieldNum,
380 (const char*)dim.mValue.storage_value.data(),
381 dim.mValue.storage_value.size());
382 break;
Yangster-macf5204922018-02-23 13:08:03 -0800383 default:
384 break;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800385 }
386 (*index)++;
387 } else if (valueDepth > depth && valuePrefix == prefix) {
388 // Writing the sub tree
Yi Jin5ee07872018-03-05 18:18:27 -0800389 uint64_t msg_token = 0ULL;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800390 if (valueDepth == depth + 2) {
391 msg_token =
392 protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | fieldNum);
393 } else if (valueDepth == depth + 1) {
394 msg_token = protoOutput->start(FIELD_TYPE_MESSAGE | fieldNum);
395 }
396 // Directly jump to the leaf value because the repeated position field is implied
397 // by the position of the sub msg in the parent field.
Yao Chenbbdd67d2018-10-24 12:15:56 -0700398 writeFieldValueTreeToStreamHelper(tagId, dims, index, valueDepth,
Yao Chen8a8d16c2018-02-08 14:50:40 -0800399 dim.mField.getPrefix(valueDepth), protoOutput);
400 if (msg_token != 0) {
401 protoOutput->end(msg_token);
402 }
403 } else {
404 // Done with the prev sub tree
405 return;
406 }
Yangster-mac20877162017-12-22 17:19:39 -0800407 }
408}
409
Yao Chen8a8d16c2018-02-08 14:50:40 -0800410void writeFieldValueTreeToStream(int tagId, const std::vector<FieldValue>& values,
Yangster-mac20877162017-12-22 17:19:39 -0800411 util::ProtoOutputStream* protoOutput) {
Yi Jin5ee07872018-03-05 18:18:27 -0800412 uint64_t atomToken = protoOutput->start(FIELD_TYPE_MESSAGE | tagId);
Yangster-mac20877162017-12-22 17:19:39 -0800413
Yao Chen8a8d16c2018-02-08 14:50:40 -0800414 size_t index = 0;
Yao Chenbbdd67d2018-10-24 12:15:56 -0700415 writeFieldValueTreeToStreamHelper(tagId, values, &index, 0, 0, protoOutput);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800416 protoOutput->end(atomToken);
Yangster-macb8144812018-01-04 10:56:23 -0800417}
Yangster-mac20877162017-12-22 17:19:39 -0800418
yro59cc24d2018-02-13 20:17:32 -0800419int64_t TimeUnitToBucketSizeInMillisGuardrailed(int uid, TimeUnit unit) {
420 int64_t bucketSizeMillis = TimeUnitToBucketSizeInMillis(unit);
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700421 if (bucketSizeMillis > 1000 && bucketSizeMillis < 5 * 60 * 1000LL && uid != AID_SHELL &&
422 uid != AID_ROOT) {
yro59cc24d2018-02-13 20:17:32 -0800423 bucketSizeMillis = 5 * 60 * 1000LL;
424 }
425 return bucketSizeMillis;
426}
427
Yangster-macb8144812018-01-04 10:56:23 -0800428int64_t TimeUnitToBucketSizeInMillis(TimeUnit unit) {
429 switch (unit) {
430 case ONE_MINUTE:
431 return 60 * 1000LL;
432 case FIVE_MINUTES:
433 return 5 * 60 * 1000LL;
434 case TEN_MINUTES:
435 return 10 * 60 * 1000LL;
436 case THIRTY_MINUTES:
437 return 30 * 60 * 1000LL;
438 case ONE_HOUR:
439 return 60 * 60 * 1000LL;
440 case THREE_HOURS:
441 return 3 * 60 * 60 * 1000LL;
442 case SIX_HOURS:
443 return 6 * 60 * 60 * 1000LL;
444 case TWELVE_HOURS:
445 return 12 * 60 * 60 * 1000LL;
446 case ONE_DAY:
447 return 24 * 60 * 60 * 1000LL;
448 case CTS:
449 return 1000;
450 case TIME_UNIT_UNSPECIFIED:
451 default:
452 return -1;
453 }
Yangster-mac20877162017-12-22 17:19:39 -0800454}
455
Chenjie Yub038b702017-12-18 15:15:34 -0800456void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>& pair,
457 util::ProtoOutputStream* protoOutput) {
Yi Jin5ee07872018-03-05 18:18:27 -0800458 uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_PULLED_ATOM_STATS |
Chenjie Yub038b702017-12-18 15:15:34 -0800459 FIELD_COUNT_REPEATED);
460 protoOutput->write(FIELD_TYPE_INT32 | FIELD_ID_PULL_ATOM_ID, (int32_t)pair.first);
461 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_TOTAL_PULL, (long long)pair.second.totalPull);
462 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_TOTAL_PULL_FROM_CACHE,
463 (long long)pair.second.totalPullFromCache);
464 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MIN_PULL_INTERVAL_SEC,
465 (long long)pair.second.minPullIntervalSec);
Chenjie Yu48ed1cc2018-10-31 17:36:38 -0700466 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_AVERAGE_PULL_TIME_NANOS,
467 (long long)pair.second.avgPullTimeNs);
468 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MAX_PULL_TIME_NANOS,
469 (long long)pair.second.maxPullTimeNs);
470 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_AVERAGE_PULL_DELAY_NANOS,
471 (long long)pair.second.avgPullDelayNs);
472 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MAX_PULL_DELAY_NANOS,
473 (long long)pair.second.maxPullDelayNs);
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700474 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_DATA_ERROR, (long long)pair.second.dataError);
Chenjie Yu0bd73db2018-12-16 07:37:04 -0800475 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_TIMEOUT,
476 (long long)pair.second.pullTimeout);
477 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_EXCEED_MAX_DELAY,
478 (long long)pair.second.pullExceedMaxDelay);
Misha Wagner1eee2212019-01-22 11:47:11 +0000479 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_FAILED,
480 (long long)pair.second.pullFailed);
481 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_STATS_COMPANION_FAILED,
482 (long long)pair.second.statsCompanionPullFailed);
483 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_STATS_COMPANION_BINDER_TRANSACTION_FAILED,
484 (long long)pair.second.statsCompanionPullBinderTransactionFailed);
485 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_EMPTY_DATA,
486 (long long)pair.second.emptyData);
Tej Singha0c89dd2019-01-25 16:39:18 -0800487 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_REGISTERED_COUNT,
488 (long long) pair.second.registeredCount);
489 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_UNREGISTERED_COUNT,
490 (long long) pair.second.unregisteredCount);
Misha Wagner1eee2212019-01-22 11:47:11 +0000491 protoOutput->end(token);
492}
493
Olivier Gaillardf48fb042019-02-13 11:03:20 +0000494void writeAtomMetricStatsToStream(const std::pair<int64_t, StatsdStats::AtomMetricStats> &pair,
Misha Wagner1eee2212019-01-22 11:47:11 +0000495 util::ProtoOutputStream *protoOutput) {
496 uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOM_METRIC_STATS |
497 FIELD_COUNT_REPEATED);
Olivier Gaillardf48fb042019-02-13 11:03:20 +0000498 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_ID, (long long)pair.first);
Misha Wagner1eee2212019-01-22 11:47:11 +0000499 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_HARD_DIMENSION_LIMIT_REACHED,
500 (long long)pair.second.hardDimensionLimitReached);
501 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_LATE_LOG_EVENT_SKIPPED,
502 (long long)pair.second.lateLogEventSkipped);
503 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_SKIPPED_FORWARD_BUCKETS,
504 (long long)pair.second.skippedForwardBuckets);
505 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BAD_VALUE_TYPE,
506 (long long)pair.second.badValueType);
507 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_CONDITION_CHANGE_IN_NEXT_BUCKET,
508 (long long)pair.second.conditionChangeInNextBucket);
Olivier Gaillard9a5d3592019-02-05 15:12:39 +0000509 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_INVALIDATED_BUCKET,
510 (long long)pair.second.invalidatedBucket);
Olivier Gaillard320952b2019-02-06 13:57:24 +0000511 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_DROPPED,
512 (long long)pair.second.bucketDropped);
Olivier Gaillard3ba2e932019-02-08 14:25:35 +0000513 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MIN_BUCKET_BOUNDARY_DELAY_NS,
514 (long long)pair.second.minBucketBoundaryDelayNs);
515 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MAX_BUCKET_BOUNDARY_DELAY_NS,
516 (long long)pair.second.maxBucketBoundaryDelayNs);
Olivier Gaillarde63d9e02019-02-12 14:43:59 +0000517 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_UNKNOWN_CONDITION,
518 (long long)pair.second.bucketUnknownCondition);
Olivier Gaillardf248c0d2019-02-21 15:56:58 +0000519 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_COUNT,
520 (long long)pair.second.bucketCount);
Chenjie Yub038b702017-12-18 15:15:34 -0800521 protoOutput->end(token);
522}
523
Yangster-mac330af582018-02-08 15:24:38 -0800524int64_t getElapsedRealtimeNs() {
525 return ::android::elapsedRealtimeNano();
526}
527
528int64_t getElapsedRealtimeSec() {
529 return ::android::elapsedRealtimeNano() / NS_PER_SEC;
530}
531
532int64_t getElapsedRealtimeMillis() {
533 return ::android::elapsedRealtime();
534}
535
536int64_t getWallClockNs() {
537 return time(nullptr) * NS_PER_SEC;
538}
539
540int64_t getWallClockSec() {
541 return time(nullptr);
542}
543
544int64_t getWallClockMillis() {
545 return time(nullptr) * MS_PER_SEC;
546}
547
Yangster-macd5c35622018-02-02 10:33:25 -0800548int64_t truncateTimestampNsToFiveMinutes(int64_t timestampNs) {
549 return timestampNs / NS_PER_SEC / (5 * 60) * NS_PER_SEC * (5 * 60);
550}
551
Yangster-mac9def8e32018-04-17 13:55:51 -0700552int64_t NanoToMillis(const int64_t nano) {
553 return nano / 1000000;
554}
555
556int64_t MillisToNano(const int64_t millis) {
557 return millis * 1000000;
558}
559
Yangster-mac20877162017-12-22 17:19:39 -0800560} // namespace statsd
561} // namespace os
yro59cc24d2018-02-13 20:17:32 -0800562} // namespace android