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