StatsdStats.cpp revision 203bbbf942e8675338b88ab67d49481d2bfcf904
1/*
2 * Copyright 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#define DEBUG false  // STOPSHIP if true
17#include "Log.h"
18
19#include "StatsdStats.h"
20
21#include <android/util/ProtoOutputStream.h>
22#include "../stats_log_util.h"
23#include "statslog.h"
24#include "storage/StorageManager.h"
25
26namespace android {
27namespace os {
28namespace statsd {
29
30using android::util::FIELD_COUNT_REPEATED;
31using android::util::FIELD_TYPE_BOOL;
32using 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;
37using android::util::ProtoOutputStream;
38using std::lock_guard;
39using std::map;
40using std::shared_ptr;
41using std::string;
42using std::vector;
43
44const int FIELD_ID_BEGIN_TIME = 1;
45const int FIELD_ID_END_TIME = 2;
46const int FIELD_ID_CONFIG_STATS = 3;
47const int FIELD_ID_ATOM_STATS = 7;
48const int FIELD_ID_UIDMAP_STATS = 8;
49const int FIELD_ID_ANOMALY_ALARM_STATS = 9;
50// const int FIELD_ID_PULLED_ATOM_STATS = 10; // The proto is written in stats_log_util.cpp
51const int FIELD_ID_LOGGER_ERROR_STATS = 11;
52const int FIELD_ID_PERIODIC_ALARM_STATS = 12;
53const int FIELD_ID_SKIPPED_LOG_EVENT_STATS = 13;
54
55const int FIELD_ID_ATOM_STATS_TAG = 1;
56const int FIELD_ID_ATOM_STATS_COUNT = 2;
57
58const int FIELD_ID_ANOMALY_ALARMS_REGISTERED = 1;
59const int FIELD_ID_PERIODIC_ALARMS_REGISTERED = 1;
60
61const int FIELD_ID_LOGGER_STATS_TIME = 1;
62const int FIELD_ID_LOGGER_STATS_ERROR_CODE = 2;
63
64const int FIELD_ID_SKIPPED_LOG_EVENT_STATS_TAG = 1;
65const int FIELD_ID_SKIPPED_LOG_EVENT_STATS_TIMESTAMP = 2;
66
67const int FIELD_ID_CONFIG_STATS_UID = 1;
68const int FIELD_ID_CONFIG_STATS_ID = 2;
69const int FIELD_ID_CONFIG_STATS_CREATION = 3;
70const int FIELD_ID_CONFIG_STATS_RESET = 19;
71const int FIELD_ID_CONFIG_STATS_DELETION = 4;
72const int FIELD_ID_CONFIG_STATS_METRIC_COUNT = 5;
73const int FIELD_ID_CONFIG_STATS_CONDITION_COUNT = 6;
74const int FIELD_ID_CONFIG_STATS_MATCHER_COUNT = 7;
75const int FIELD_ID_CONFIG_STATS_ALERT_COUNT = 8;
76const int FIELD_ID_CONFIG_STATS_VALID = 9;
77const int FIELD_ID_CONFIG_STATS_BROADCAST = 10;
78const int FIELD_ID_CONFIG_STATS_DATA_DROP = 11;
79const int FIELD_ID_CONFIG_STATS_DUMP_REPORT = 12;
80const int FIELD_ID_CONFIG_STATS_MATCHER_STATS = 13;
81const int FIELD_ID_CONFIG_STATS_CONDITION_STATS = 14;
82const int FIELD_ID_CONFIG_STATS_METRIC_STATS = 15;
83const int FIELD_ID_CONFIG_STATS_ALERT_STATS = 16;
84const int FIELD_ID_CONFIG_STATS_METRIC_DIMENSION_IN_CONDITION_STATS = 17;
85const int FIELD_ID_CONFIG_STATS_ANNOTATION = 18;
86const int FIELD_ID_CONFIG_STATS_ANNOTATION_INT64 = 1;
87const int FIELD_ID_CONFIG_STATS_ANNOTATION_INT32 = 2;
88
89const int FIELD_ID_MATCHER_STATS_ID = 1;
90const int FIELD_ID_MATCHER_STATS_COUNT = 2;
91const int FIELD_ID_CONDITION_STATS_ID = 1;
92const int FIELD_ID_CONDITION_STATS_COUNT = 2;
93const int FIELD_ID_METRIC_STATS_ID = 1;
94const int FIELD_ID_METRIC_STATS_COUNT = 2;
95const int FIELD_ID_ALERT_STATS_ID = 1;
96const int FIELD_ID_ALERT_STATS_COUNT = 2;
97
98const int FIELD_ID_UID_MAP_CHANGES = 1;
99const int FIELD_ID_UID_MAP_BYTES_USED = 2;
100const int FIELD_ID_UID_MAP_DROPPED_CHANGES = 3;
101const int FIELD_ID_UID_MAP_DELETED_APPS = 4;
102
103const std::map<int, std::pair<size_t, size_t>> StatsdStats::kAtomDimensionKeySizeLimitMap = {
104        {android::util::CPU_TIME_PER_UID_FREQ, {6000, 10000}},
105};
106
107// TODO: add stats for pulled atoms.
108StatsdStats::StatsdStats() {
109    mPushedAtomStats.resize(android::util::kMaxPushedAtomId + 1);
110    mStartTimeSec = getWallClockSec();
111}
112
113StatsdStats& StatsdStats::getInstance() {
114    static StatsdStats statsInstance;
115    return statsInstance;
116}
117
118void StatsdStats::addToIceBoxLocked(shared_ptr<ConfigStats>& stats) {
119    // The size of mIceBox grows strictly by one at a time. It won't be > kMaxIceBoxSize.
120    if (mIceBox.size() == kMaxIceBoxSize) {
121        mIceBox.pop_front();
122    }
123    mIceBox.push_back(stats);
124}
125
126void StatsdStats::noteConfigReceived(
127        const ConfigKey& key, int metricsCount, int conditionsCount, int matchersCount,
128        int alertsCount, const std::list<std::pair<const int64_t, const int32_t>>& annotations,
129        bool isValid) {
130    lock_guard<std::mutex> lock(mLock);
131    int32_t nowTimeSec = getWallClockSec();
132
133    // If there is an existing config for the same key, icebox the old config.
134    noteConfigRemovedInternalLocked(key);
135
136    shared_ptr<ConfigStats> configStats = std::make_shared<ConfigStats>();
137    configStats->uid = key.GetUid();
138    configStats->id = key.GetId();
139    configStats->creation_time_sec = nowTimeSec;
140    configStats->metric_count = metricsCount;
141    configStats->condition_count = conditionsCount;
142    configStats->matcher_count = matchersCount;
143    configStats->alert_count = alertsCount;
144    configStats->is_valid = isValid;
145    for (auto& v : annotations) {
146        configStats->annotations.emplace_back(v);
147    }
148
149    if (isValid) {
150        mConfigStats[key] = configStats;
151    } else {
152        configStats->deletion_time_sec = nowTimeSec;
153        addToIceBoxLocked(configStats);
154    }
155}
156
157void StatsdStats::noteConfigRemovedInternalLocked(const ConfigKey& key) {
158    auto it = mConfigStats.find(key);
159    if (it != mConfigStats.end()) {
160        int32_t nowTimeSec = getWallClockSec();
161        it->second->deletion_time_sec = nowTimeSec;
162        addToIceBoxLocked(it->second);
163        mConfigStats.erase(it);
164    }
165}
166
167void StatsdStats::noteConfigRemoved(const ConfigKey& key) {
168    lock_guard<std::mutex> lock(mLock);
169    noteConfigRemovedInternalLocked(key);
170}
171
172void StatsdStats::noteConfigResetInternalLocked(const ConfigKey& key) {
173    auto it = mConfigStats.find(key);
174    if (it != mConfigStats.end()) {
175        it->second->reset_time_sec = getWallClockSec();
176    }
177}
178
179void StatsdStats::noteConfigReset(const ConfigKey& key) {
180    lock_guard<std::mutex> lock(mLock);
181    noteConfigResetInternalLocked(key);
182}
183
184void StatsdStats::noteBroadcastSent(const ConfigKey& key) {
185    noteBroadcastSent(key, getWallClockSec());
186}
187
188void StatsdStats::noteBroadcastSent(const ConfigKey& key, int32_t timeSec) {
189    lock_guard<std::mutex> lock(mLock);
190    auto it = mConfigStats.find(key);
191    if (it == mConfigStats.end()) {
192        ALOGE("Config key %s not found!", key.ToString().c_str());
193        return;
194    }
195    if (it->second->broadcast_sent_time_sec.size() == kMaxTimestampCount) {
196        it->second->broadcast_sent_time_sec.pop_front();
197    }
198    it->second->broadcast_sent_time_sec.push_back(timeSec);
199}
200
201void StatsdStats::noteDataDropped(const ConfigKey& key) {
202    noteDataDropped(key, getWallClockSec());
203}
204
205void StatsdStats::noteDataDropped(const ConfigKey& key, int32_t timeSec) {
206    lock_guard<std::mutex> lock(mLock);
207    auto it = mConfigStats.find(key);
208    if (it == mConfigStats.end()) {
209        ALOGE("Config key %s not found!", key.ToString().c_str());
210        return;
211    }
212    if (it->second->data_drop_time_sec.size() == kMaxTimestampCount) {
213        it->second->data_drop_time_sec.pop_front();
214    }
215    it->second->data_drop_time_sec.push_back(timeSec);
216}
217
218void StatsdStats::noteMetricsReportSent(const ConfigKey& key) {
219    noteMetricsReportSent(key, getWallClockSec());
220}
221
222void StatsdStats::noteMetricsReportSent(const ConfigKey& key, int32_t timeSec) {
223    lock_guard<std::mutex> lock(mLock);
224    auto it = mConfigStats.find(key);
225    if (it == mConfigStats.end()) {
226        ALOGE("Config key %s not found!", key.ToString().c_str());
227        return;
228    }
229    if (it->second->dump_report_time_sec.size() == kMaxTimestampCount) {
230        it->second->dump_report_time_sec.pop_front();
231    }
232    it->second->dump_report_time_sec.push_back(timeSec);
233}
234
235void StatsdStats::noteUidMapDropped(int deltas) {
236    lock_guard<std::mutex> lock(mLock);
237    mUidMapStats.dropped_changes += mUidMapStats.dropped_changes + deltas;
238}
239
240void StatsdStats::noteUidMapAppDeletionDropped() {
241    lock_guard<std::mutex> lock(mLock);
242    mUidMapStats.deleted_apps++;
243}
244
245void StatsdStats::setUidMapChanges(int changes) {
246    lock_guard<std::mutex> lock(mLock);
247    mUidMapStats.changes = changes;
248}
249
250void StatsdStats::setCurrentUidMapMemory(int bytes) {
251    lock_guard<std::mutex> lock(mLock);
252    mUidMapStats.bytes_used = bytes;
253}
254
255void StatsdStats::noteConditionDimensionSize(const ConfigKey& key, const int64_t& id, int size) {
256    lock_guard<std::mutex> lock(mLock);
257    // if name doesn't exist before, it will create the key with count 0.
258    auto statsIt = mConfigStats.find(key);
259    if (statsIt == mConfigStats.end()) {
260        return;
261    }
262
263    auto& conditionSizeMap = statsIt->second->condition_stats;
264    if (size > conditionSizeMap[id]) {
265        conditionSizeMap[id] = size;
266    }
267}
268
269void StatsdStats::noteMetricDimensionSize(const ConfigKey& key, const int64_t& id, int size) {
270    lock_guard<std::mutex> lock(mLock);
271    // if name doesn't exist before, it will create the key with count 0.
272    auto statsIt = mConfigStats.find(key);
273    if (statsIt == mConfigStats.end()) {
274        return;
275    }
276    auto& metricsDimensionMap = statsIt->second->metric_stats;
277    if (size > metricsDimensionMap[id]) {
278        metricsDimensionMap[id] = size;
279    }
280}
281
282void StatsdStats::noteMetricDimensionInConditionSize(
283        const ConfigKey& key, const int64_t& id, int size) {
284    lock_guard<std::mutex> lock(mLock);
285    // if name doesn't exist before, it will create the key with count 0.
286    auto statsIt = mConfigStats.find(key);
287    if (statsIt == mConfigStats.end()) {
288        return;
289    }
290    auto& metricsDimensionMap = statsIt->second->metric_dimension_in_condition_stats;
291    if (size > metricsDimensionMap[id]) {
292        metricsDimensionMap[id] = size;
293    }
294}
295
296void StatsdStats::noteMatcherMatched(const ConfigKey& key, const int64_t& id) {
297    lock_guard<std::mutex> lock(mLock);
298
299    auto statsIt = mConfigStats.find(key);
300    if (statsIt == mConfigStats.end()) {
301        return;
302    }
303    statsIt->second->matcher_stats[id]++;
304}
305
306void StatsdStats::noteAnomalyDeclared(const ConfigKey& key, const int64_t& id) {
307    lock_guard<std::mutex> lock(mLock);
308    auto statsIt = mConfigStats.find(key);
309    if (statsIt == mConfigStats.end()) {
310        return;
311    }
312    statsIt->second->alert_stats[id]++;
313}
314
315void StatsdStats::noteRegisteredAnomalyAlarmChanged() {
316    lock_guard<std::mutex> lock(mLock);
317    mAnomalyAlarmRegisteredStats++;
318}
319
320void StatsdStats::noteRegisteredPeriodicAlarmChanged() {
321    lock_guard<std::mutex> lock(mLock);
322    mPeriodicAlarmRegisteredStats++;
323}
324
325void StatsdStats::updateMinPullIntervalSec(int pullAtomId, long intervalSec) {
326    lock_guard<std::mutex> lock(mLock);
327    mPulledAtomStats[pullAtomId].minPullIntervalSec = intervalSec;
328}
329
330void StatsdStats::notePull(int pullAtomId) {
331    lock_guard<std::mutex> lock(mLock);
332    mPulledAtomStats[pullAtomId].totalPull++;
333}
334
335void StatsdStats::notePullFromCache(int pullAtomId) {
336    lock_guard<std::mutex> lock(mLock);
337    mPulledAtomStats[pullAtomId].totalPullFromCache++;
338}
339
340void StatsdStats::noteAtomLogged(int atomId, int32_t timeSec) {
341    lock_guard<std::mutex> lock(mLock);
342
343    if (atomId > android::util::kMaxPushedAtomId) {
344        ALOGW("not interested in atom %d", atomId);
345        return;
346    }
347
348    mPushedAtomStats[atomId]++;
349}
350
351void StatsdStats::noteLogEventSkipped(int tag, int64_t timestamp) {
352    lock_guard<std::mutex> lock(mLock);
353    // grows strictly one at a time. so it won't > kMaxSkippedLogEvents
354    if (mSkippedLogEvents.size() == kMaxSkippedLogEvents) {
355        mSkippedLogEvents.pop_front();
356    }
357    mSkippedLogEvents.push_back(std::make_pair(tag, timestamp));
358}
359
360void StatsdStats::noteLoggerError(int error) {
361    lock_guard<std::mutex> lock(mLock);
362    // grows strictly one at a time. so it won't > kMaxLoggerErrors
363    if (mLoggerErrors.size() == kMaxLoggerErrors) {
364        mLoggerErrors.pop_front();
365    }
366    mLoggerErrors.push_back(std::make_pair(getWallClockSec(), error));
367}
368
369void StatsdStats::reset() {
370    lock_guard<std::mutex> lock(mLock);
371    resetInternalLocked();
372}
373
374void StatsdStats::resetInternalLocked() {
375    // Reset the historical data, but keep the active ConfigStats
376    mStartTimeSec = getWallClockSec();
377    mIceBox.clear();
378    std::fill(mPushedAtomStats.begin(), mPushedAtomStats.end(), 0);
379    mAnomalyAlarmRegisteredStats = 0;
380    mPeriodicAlarmRegisteredStats = 0;
381    mLoggerErrors.clear();
382    mSkippedLogEvents.clear();
383    for (auto& config : mConfigStats) {
384        config.second->broadcast_sent_time_sec.clear();
385        config.second->data_drop_time_sec.clear();
386        config.second->dump_report_time_sec.clear();
387        config.second->annotations.clear();
388        config.second->matcher_stats.clear();
389        config.second->condition_stats.clear();
390        config.second->metric_stats.clear();
391        config.second->metric_dimension_in_condition_stats.clear();
392        config.second->alert_stats.clear();
393    }
394}
395
396void StatsdStats::dumpStats(FILE* out) const {
397    lock_guard<std::mutex> lock(mLock);
398    time_t t = mStartTimeSec;
399    struct tm* tm = localtime(&t);
400    char timeBuffer[80];
401    strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %I:%M%p\n", tm);
402    fprintf(out, "Stats collection start second: %s\n", timeBuffer);
403    fprintf(out, "%lu Config in icebox: \n", (unsigned long)mIceBox.size());
404    for (const auto& configStats : mIceBox) {
405        fprintf(out,
406                "Config {%d_%lld}: creation=%d, deletion=%d, reset=%d, #metric=%d, #condition=%d, "
407                "#matcher=%d, #alert=%d,  valid=%d\n",
408                configStats->uid, (long long)configStats->id, configStats->creation_time_sec,
409                configStats->deletion_time_sec, configStats->reset_time_sec,
410                configStats->metric_count,
411                configStats->condition_count, configStats->matcher_count, configStats->alert_count,
412                configStats->is_valid);
413
414        for (const auto& broadcastTime : configStats->broadcast_sent_time_sec) {
415            fprintf(out, "\tbroadcast time: %d\n", broadcastTime);
416        }
417
418        for (const auto& dataDropTime : configStats->data_drop_time_sec) {
419            fprintf(out, "\tdata drop time: %d\n", dataDropTime);
420        }
421    }
422    fprintf(out, "%lu Active Configs\n", (unsigned long)mConfigStats.size());
423    for (auto& pair : mConfigStats) {
424        auto& configStats = pair.second;
425        fprintf(out,
426                "Config {%d-%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, "
427                "#matcher=%d, #alert=%d,  valid=%d\n",
428                configStats->uid, (long long)configStats->id, configStats->creation_time_sec,
429                configStats->deletion_time_sec, configStats->metric_count,
430                configStats->condition_count, configStats->matcher_count, configStats->alert_count,
431                configStats->is_valid);
432        for (const auto& annotation : configStats->annotations) {
433            fprintf(out, "\tannotation: %lld, %d\n", (long long)annotation.first,
434                    annotation.second);
435        }
436
437        for (const auto& broadcastTime : configStats->broadcast_sent_time_sec) {
438            fprintf(out, "\tbroadcast time: %d\n", broadcastTime);
439        }
440
441        for (const auto& dataDropTime : configStats->data_drop_time_sec) {
442            fprintf(out, "\tdata drop time: %d\n", dataDropTime);
443        }
444
445        for (const auto& dumpTime : configStats->dump_report_time_sec) {
446            fprintf(out, "\tdump report time: %d\n", dumpTime);
447        }
448
449        for (const auto& stats : pair.second->matcher_stats) {
450            fprintf(out, "matcher %lld matched %d times\n", (long long)stats.first, stats.second);
451        }
452
453        for (const auto& stats : pair.second->condition_stats) {
454            fprintf(out, "condition %lld max output tuple size %d\n", (long long)stats.first,
455                    stats.second);
456        }
457
458        for (const auto& stats : pair.second->condition_stats) {
459            fprintf(out, "metrics %lld max output tuple size %d\n", (long long)stats.first,
460                    stats.second);
461        }
462
463        for (const auto& stats : pair.second->alert_stats) {
464            fprintf(out, "alert %lld declared %d times\n", (long long)stats.first, stats.second);
465        }
466    }
467    fprintf(out, "********Disk Usage stats***********\n");
468    StorageManager::printStats(out);
469    fprintf(out, "********Pushed Atom stats***********\n");
470    const size_t atomCounts = mPushedAtomStats.size();
471    for (size_t i = 2; i < atomCounts; i++) {
472        if (mPushedAtomStats[i] > 0) {
473            fprintf(out, "Atom %lu->%d\n", (unsigned long)i, mPushedAtomStats[i]);
474        }
475    }
476
477    fprintf(out, "********Pulled Atom stats***********\n");
478    for (const auto& pair : mPulledAtomStats) {
479        fprintf(out, "Atom %d->%ld, %ld, %ld\n", (int)pair.first, (long)pair.second.totalPull,
480                (long)pair.second.totalPullFromCache, (long)pair.second.minPullIntervalSec);
481    }
482
483    if (mAnomalyAlarmRegisteredStats > 0) {
484        fprintf(out, "********AnomalyAlarmStats stats***********\n");
485        fprintf(out, "Anomaly alarm registrations: %d\n", mAnomalyAlarmRegisteredStats);
486    }
487
488    if (mPeriodicAlarmRegisteredStats > 0) {
489        fprintf(out, "********SubscriberAlarmStats stats***********\n");
490        fprintf(out, "Subscriber alarm registrations: %d\n", mPeriodicAlarmRegisteredStats);
491    }
492
493    fprintf(out, "UID map stats: bytes=%d, changes=%d, deleted=%d, changes lost=%d\n",
494            mUidMapStats.bytes_used, mUidMapStats.changes, mUidMapStats.deleted_apps,
495            mUidMapStats.dropped_changes);
496
497    for (const auto& error : mLoggerErrors) {
498        time_t error_time = error.first;
499        struct tm* error_tm = localtime(&error_time);
500        char buffer[80];
501        strftime(buffer, sizeof(buffer), "%Y-%m-%d %I:%M%p\n", error_tm);
502        fprintf(out, "Logger error %d at %s\n", error.second, buffer);
503    }
504    for (const auto& skipped : mSkippedLogEvents) {
505        fprintf(out, "Log event (%d) skipped at %lld\n", skipped.first, (long long)skipped.second);
506    }
507}
508
509void addConfigStatsToProto(const ConfigStats& configStats, ProtoOutputStream* proto) {
510    uint64_t token =
511            proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_CONFIG_STATS);
512    proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_UID, configStats.uid);
513    proto->write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_STATS_ID, (long long)configStats.id);
514    proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_CREATION, configStats.creation_time_sec);
515    if (configStats.reset_time_sec != 0) {
516        proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_RESET, configStats.reset_time_sec);
517    }
518    if (configStats.deletion_time_sec != 0) {
519        proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DELETION,
520                     configStats.deletion_time_sec);
521    }
522    proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_METRIC_COUNT, configStats.metric_count);
523    proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_CONDITION_COUNT,
524                 configStats.condition_count);
525    proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_MATCHER_COUNT, configStats.matcher_count);
526    proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_ALERT_COUNT, configStats.alert_count);
527    proto->write(FIELD_TYPE_BOOL | FIELD_ID_CONFIG_STATS_VALID, configStats.is_valid);
528
529    for (const auto& broadcast : configStats.broadcast_sent_time_sec) {
530        proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_BROADCAST | FIELD_COUNT_REPEATED,
531                     broadcast);
532    }
533
534    for (const auto& drop : configStats.data_drop_time_sec) {
535        proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DATA_DROP | FIELD_COUNT_REPEATED,
536                     drop);
537    }
538
539    for (const auto& dump : configStats.dump_report_time_sec) {
540        proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DUMP_REPORT | FIELD_COUNT_REPEATED,
541                     dump);
542    }
543
544    for (const auto& annotation : configStats.annotations) {
545        uint64_t token = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
546                                      FIELD_ID_CONFIG_STATS_ANNOTATION);
547        proto->write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_STATS_ANNOTATION_INT64,
548                     (long long)annotation.first);
549        proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_ANNOTATION_INT32, annotation.second);
550        proto->end(token);
551    }
552
553    for (const auto& pair : configStats.matcher_stats) {
554        uint64_t tmpToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
555                                          FIELD_ID_CONFIG_STATS_MATCHER_STATS);
556        proto->write(FIELD_TYPE_INT64 | FIELD_ID_MATCHER_STATS_ID, (long long)pair.first);
557        proto->write(FIELD_TYPE_INT32 | FIELD_ID_MATCHER_STATS_COUNT, pair.second);
558        proto->end(tmpToken);
559    }
560
561    for (const auto& pair : configStats.condition_stats) {
562        uint64_t tmpToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
563                                          FIELD_ID_CONFIG_STATS_CONDITION_STATS);
564        proto->write(FIELD_TYPE_INT64 | FIELD_ID_CONDITION_STATS_ID, (long long)pair.first);
565        proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONDITION_STATS_COUNT, pair.second);
566        proto->end(tmpToken);
567    }
568
569    for (const auto& pair : configStats.metric_stats) {
570        uint64_t tmpToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
571                                          FIELD_ID_CONFIG_STATS_METRIC_STATS);
572        proto->write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_STATS_ID, (long long)pair.first);
573        proto->write(FIELD_TYPE_INT32 | FIELD_ID_METRIC_STATS_COUNT, pair.second);
574        proto->end(tmpToken);
575    }
576    for (const auto& pair : configStats.metric_dimension_in_condition_stats) {
577        uint64_t tmpToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
578                                         FIELD_ID_CONFIG_STATS_METRIC_DIMENSION_IN_CONDITION_STATS);
579        proto->write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_STATS_ID, (long long)pair.first);
580        proto->write(FIELD_TYPE_INT32 | FIELD_ID_METRIC_STATS_COUNT, pair.second);
581        proto->end(tmpToken);
582    }
583
584    for (const auto& pair : configStats.alert_stats) {
585        uint64_t tmpToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
586                                          FIELD_ID_CONFIG_STATS_ALERT_STATS);
587        proto->write(FIELD_TYPE_INT64 | FIELD_ID_ALERT_STATS_ID, (long long)pair.first);
588        proto->write(FIELD_TYPE_INT32 | FIELD_ID_ALERT_STATS_COUNT, pair.second);
589        proto->end(tmpToken);
590    }
591
592    proto->end(token);
593}
594
595void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) {
596    lock_guard<std::mutex> lock(mLock);
597
598    ProtoOutputStream proto;
599    proto.write(FIELD_TYPE_INT32 | FIELD_ID_BEGIN_TIME, mStartTimeSec);
600    proto.write(FIELD_TYPE_INT32 | FIELD_ID_END_TIME, (int32_t)getWallClockSec());
601
602    for (const auto& configStats : mIceBox) {
603        addConfigStatsToProto(*configStats, &proto);
604    }
605
606    for (auto& pair : mConfigStats) {
607        addConfigStatsToProto(*(pair.second), &proto);
608    }
609
610    const size_t atomCounts = mPushedAtomStats.size();
611    for (size_t i = 2; i < atomCounts; i++) {
612        if (mPushedAtomStats[i] > 0) {
613            uint64_t token =
614                    proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOM_STATS | FIELD_COUNT_REPEATED);
615            proto.write(FIELD_TYPE_INT32 | FIELD_ID_ATOM_STATS_TAG, (int32_t)i);
616            proto.write(FIELD_TYPE_INT32 | FIELD_ID_ATOM_STATS_COUNT, mPushedAtomStats[i]);
617            proto.end(token);
618        }
619    }
620
621    for (const auto& pair : mPulledAtomStats) {
622        android::os::statsd::writePullerStatsToStream(pair, &proto);
623    }
624
625    if (mAnomalyAlarmRegisteredStats > 0) {
626        uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_ANOMALY_ALARM_STATS);
627        proto.write(FIELD_TYPE_INT32 | FIELD_ID_ANOMALY_ALARMS_REGISTERED,
628                    mAnomalyAlarmRegisteredStats);
629        proto.end(token);
630    }
631
632    if (mPeriodicAlarmRegisteredStats > 0) {
633        uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_PERIODIC_ALARM_STATS);
634        proto.write(FIELD_TYPE_INT32 | FIELD_ID_PERIODIC_ALARMS_REGISTERED,
635                    mPeriodicAlarmRegisteredStats);
636        proto.end(token);
637    }
638
639    uint64_t uidMapToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_UIDMAP_STATS);
640    proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID_MAP_CHANGES, mUidMapStats.changes);
641    proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID_MAP_BYTES_USED, mUidMapStats.bytes_used);
642    proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID_MAP_DROPPED_CHANGES, mUidMapStats.dropped_changes);
643    proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID_MAP_DELETED_APPS, mUidMapStats.deleted_apps);
644    proto.end(uidMapToken);
645
646    for (const auto& error : mLoggerErrors) {
647        uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_LOGGER_ERROR_STATS |
648                                      FIELD_COUNT_REPEATED);
649        proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOGGER_STATS_TIME, error.first);
650        proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOGGER_STATS_ERROR_CODE, error.second);
651        proto.end(token);
652    }
653
654    for (const auto& skipped : mSkippedLogEvents) {
655        uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_SKIPPED_LOG_EVENT_STATS |
656                                      FIELD_COUNT_REPEATED);
657        proto.write(FIELD_TYPE_INT32 | FIELD_ID_SKIPPED_LOG_EVENT_STATS_TAG, skipped.first);
658        proto.write(FIELD_TYPE_INT64 | FIELD_ID_SKIPPED_LOG_EVENT_STATS_TIMESTAMP,
659                    (long long)skipped.second);
660        proto.end(token);
661    }
662
663    output->clear();
664    size_t bufferSize = proto.size();
665    output->resize(bufferSize);
666
667    size_t pos = 0;
668    auto it = proto.data();
669    while (it.readBuffer() != NULL) {
670        size_t toRead = it.currentToRead();
671        std::memcpy(&((*output)[pos]), it.readBuffer(), toRead);
672        pos += toRead;
673        it.rp()->move(toRead);
674    }
675
676    if (reset) {
677        resetInternalLocked();
678    }
679
680    VLOG("reset=%d, returned proto size %lu", reset, (unsigned long)bufferSize);
681}
682
683}  // namespace statsd
684}  // namespace os
685}  // namespace android
686