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