all pullers have a default 1s cool down before next pull.
We can adjust these later.
Also add puller stats in StatsdStats
Test: unit test
Change-Id: I71894a24c41e059d841591312dbb852f54387b7d
src/config/ConfigKey.cpp \
src/config/ConfigListener.cpp \
src/config/ConfigManager.cpp \
+ src/external/StatsPuller.cpp \
src/external/StatsCompanionServicePuller.cpp \
src/external/ResourcePowerManagerPuller.cpp \
src/external/CpuTimePerUidPuller.cpp \
#include <fstream>
#include "external/CpuTimePerUidFreqPuller.h"
+#include "../guardrail/StatsdStats.h"
+#include "CpuTimePerUidFreqPuller.h"
+#include "guardrail/StatsdStats.h"
#include "logd/LogEvent.h"
#include "statslog.h"
* This provides the times a UID's processes spent executing at each different cpu frequency.
* The file contains a monotonically increasing count of time for a single boot.
*/
-bool CpuTimePerUidFreqPuller::Pull(const int tagId, vector<shared_ptr<LogEvent>>* data) {
- data->clear();
+CpuTimePerUidFreqPuller::CpuTimePerUidFreqPuller()
+ : StatsPuller(android::util::CPU_TIME_PER_UID_FREQ) {
+}
+
+bool CpuTimePerUidFreqPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
+ data->clear();
- ifstream fin;
- fin.open(sProcFile);
- if (!fin.good()) {
- VLOG("Failed to read pseudo file %s", sProcFile.c_str());
- return false;
- }
+ ifstream fin;
+ fin.open(sProcFile);
+ if (!fin.good()) {
+ VLOG("Failed to read pseudo file %s", sProcFile.c_str());
+ return false;
+ }
- uint64_t timestamp = time(nullptr) * NS_PER_SEC;
- char buf[kLineBufferSize];
- // first line prints the format and frequencies
- fin.getline(buf, kLineBufferSize);
- char * pch;
- while(!fin.eof()){
+ uint64_t timestamp = time(nullptr) * NS_PER_SEC;
+ char buf[kLineBufferSize];
+ // first line prints the format and frequencies
fin.getline(buf, kLineBufferSize);
- pch = strtok (buf, " :");
- if (pch == NULL) break;
- uint64_t uid = std::stoull(pch);
- pch = strtok(NULL, " ");
- uint64_t timeMs;
- int idx = 0;
- do {
- timeMs = std::stoull(pch);
- auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID_FREQ, timestamp);
- ptr->write(uid);
- ptr->write(idx);
- ptr->write(timeMs);
- ptr->init();
- data->push_back(ptr);
- VLOG("uid %lld, freq idx %d, sys time %lld", (long long)uid, idx, (long long)timeMs);
- idx ++;
- pch = strtok(NULL, " ");
- } while (pch != NULL);
- }
- return true;
+ char* pch;
+ while (!fin.eof()) {
+ fin.getline(buf, kLineBufferSize);
+ pch = strtok(buf, " :");
+ if (pch == NULL) break;
+ uint64_t uid = std::stoull(pch);
+ pch = strtok(NULL, " ");
+ uint64_t timeMs;
+ int idx = 0;
+ do {
+ timeMs = std::stoull(pch);
+ auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID_FREQ, timestamp);
+ ptr->write(uid);
+ ptr->write(idx);
+ ptr->write(timeMs);
+ ptr->init();
+ data->push_back(ptr);
+ VLOG("uid %lld, freq idx %d, sys time %lld", (long long)uid, idx, (long long)timeMs);
+ idx++;
+ pch = strtok(NULL, " ");
+ } while (pch != NULL);
+ }
+ return true;
}
} // namespace statsd
*/
class CpuTimePerUidFreqPuller : public StatsPuller {
public:
- bool Pull(const int tagId, vector<std::shared_ptr<LogEvent>>* data) override;
+ CpuTimePerUidFreqPuller();
+ bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
};
} // namespace statsd
#include <fstream>
#include "external/CpuTimePerUidPuller.h"
+#include "CpuTimePerUidPuller.h"
+#include "guardrail/StatsdStats.h"
#include "logd/LogEvent.h"
#include "statslog.h"
* This provides the time a UID's processes spent executing in user-space and kernel-space.
* The file contains a monotonically increasing count of time for a single boot.
*/
-bool CpuTimePerUidPuller::Pull(const int tagId, vector<shared_ptr<LogEvent>>* data) {
- data->clear();
+CpuTimePerUidPuller::CpuTimePerUidPuller() : StatsPuller(android::util::CPU_TIME_PER_UID) {
+}
+
+bool CpuTimePerUidPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
+ data->clear();
- ifstream fin;
- fin.open(sProcFile);
- if (!fin.good()) {
- VLOG("Failed to read pseudo file %s", sProcFile.c_str());
- return false;
- }
+ ifstream fin;
+ fin.open(sProcFile);
+ if (!fin.good()) {
+ VLOG("Failed to read pseudo file %s", sProcFile.c_str());
+ return false;
+ }
- uint64_t timestamp = time(nullptr) * NS_PER_SEC;
- char buf[kLineBufferSize];
- char * pch;
- while(!fin.eof()){
- fin.getline(buf, kLineBufferSize);
- pch = strtok(buf, " :");
- if (pch == NULL) break;
- uint64_t uid = std::stoull(pch);
- pch = strtok(buf, " ");
- uint64_t userTimeMs = std::stoull(pch);
- pch = strtok(buf, " ");
- uint64_t sysTimeMs = std::stoull(pch);
+ uint64_t timestamp = time(nullptr) * NS_PER_SEC;
+ char buf[kLineBufferSize];
+ char* pch;
+ while (!fin.eof()) {
+ fin.getline(buf, kLineBufferSize);
+ pch = strtok(buf, " :");
+ if (pch == NULL) break;
+ uint64_t uid = std::stoull(pch);
+ pch = strtok(buf, " ");
+ uint64_t userTimeMs = std::stoull(pch);
+ pch = strtok(buf, " ");
+ uint64_t sysTimeMs = std::stoull(pch);
- auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID, timestamp);
- ptr->write(uid);
- ptr->write(userTimeMs);
- ptr->write(sysTimeMs);
- ptr->init();
- data->push_back(ptr);
- VLOG("uid %lld, user time %lld, sys time %lld", (long long)uid, (long long)userTimeMs, (long long)sysTimeMs);
- }
- return true;
+ auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID, timestamp);
+ ptr->write(uid);
+ ptr->write(userTimeMs);
+ ptr->write(sysTimeMs);
+ ptr->init();
+ data->push_back(ptr);
+ VLOG("uid %lld, user time %lld, sys time %lld", (long long)uid, (long long)userTimeMs,
+ (long long)sysTimeMs);
+ }
+ return true;
}
} // namespace statsd
*/
class CpuTimePerUidPuller : public StatsPuller {
public:
- bool Pull(const int tagId, vector<std::shared_ptr<LogEvent>>* data) override;
+ CpuTimePerUidPuller();
+ bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
};
} // namespace statsd
#include "external/ResourcePowerManagerPuller.h"
#include "external/StatsPuller.h"
+#include "ResourcePowerManagerPuller.h"
#include "logd/LogEvent.h"
#include "statslog.h"
return gPowerHalV1_0 != nullptr;
}
-bool ResourcePowerManagerPuller::Pull(const int tagId, vector<shared_ptr<LogEvent>>* data) {
+ResourcePowerManagerPuller::ResourcePowerManagerPuller(int tagId) : StatsPuller(tagId) {
+}
+
+bool ResourcePowerManagerPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
std::lock_guard<std::mutex> lock(gPowerHalMutex);
if (!getPowerHal()) {
uint64_t timestamp = time(nullptr) * NS_PER_SEC;
data->clear();
- Return<void> ret = gPowerHalV1_0->getPlatformLowPowerStats(
- [&data, timestamp](hidl_vec<PowerStatePlatformSleepState> states, Status status) {
-
- if (status != Status::SUCCESS) return;
-
- for (size_t i = 0; i < states.size(); i++) {
- const PowerStatePlatformSleepState& state = states[i];
-
- auto statePtr = make_shared<LogEvent>(
- android::util::PLATFORM_SLEEP_STATE, timestamp);
- statePtr->write(state.name);
- statePtr->write(state.residencyInMsecSinceBoot);
- statePtr->write(state.totalTransitions);
- statePtr->write(state.supportedOnlyInSuspend);
- statePtr->init();
- data->push_back(statePtr);
- VLOG("powerstate: %s, %lld, %lld, %d", state.name.c_str(),
- (long long)state.residencyInMsecSinceBoot,
- (long long)state.totalTransitions, state.supportedOnlyInSuspend ? 1 : 0);
- for (auto voter : state.voters) {
- auto voterPtr =
- make_shared<LogEvent>(android::util::SLEEP_STATE_VOTER, timestamp);
- voterPtr->write(state.name);
- voterPtr->write(voter.name);
- voterPtr->write(voter.totalTimeInMsecVotedForSinceBoot);
- voterPtr->write(voter.totalNumberOfTimesVotedSinceBoot);
- voterPtr->init();
- data->push_back(voterPtr);
- VLOG("powerstatevoter: %s, %s, %lld, %lld", state.name.c_str(),
- voter.name.c_str(), (long long)voter.totalTimeInMsecVotedForSinceBoot,
- (long long)voter.totalNumberOfTimesVotedSinceBoot);
- }
- }
- });
- if (!ret.isOk()) {
- ALOGE("getLowPowerStats() failed: power HAL service not available");
- gPowerHalV1_0 = nullptr;
- return false;
- }
-
- // Trying to cast to IPower 1.1, this will succeed only for devices supporting 1.1
- sp<android::hardware::power::V1_1::IPower> gPowerHal_1_1 =
- android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0);
- if (gPowerHal_1_1 != nullptr) {
- ret = gPowerHal_1_1->getSubsystemLowPowerStats(
- [&data, timestamp](hidl_vec<PowerStateSubsystem> subsystems, Status status) {
+ Return<void> ret;
+ if (mTagId == android::util::PLATFORM_SLEEP_STATE ||
+ mTagId == android::util::SLEEP_STATE_VOTER) {
+ ret = gPowerHalV1_0->getPlatformLowPowerStats(
+ [&data, timestamp](hidl_vec<PowerStatePlatformSleepState> states, Status status) {
if (status != Status::SUCCESS) return;
- if (subsystems.size() > 0) {
- for (size_t i = 0; i < subsystems.size(); i++) {
- const PowerStateSubsystem& subsystem = subsystems[i];
- for (size_t j = 0; j < subsystem.states.size(); j++) {
- const PowerStateSubsystemSleepState& state = subsystem.states[j];
- auto subsystemStatePtr = make_shared<LogEvent>(
- android::util::SUBSYSTEM_SLEEP_STATE, timestamp);
- subsystemStatePtr->write(subsystem.name);
- subsystemStatePtr->write(state.name);
- subsystemStatePtr->write(state.residencyInMsecSinceBoot);
- subsystemStatePtr->write(state.totalTransitions);
- subsystemStatePtr->write(state.lastEntryTimestampMs);
- subsystemStatePtr->write(state.supportedOnlyInSuspend);
- subsystemStatePtr->init();
- data->push_back(subsystemStatePtr);
- VLOG("subsystemstate: %s, %s, %lld, %lld, %lld",
- subsystem.name.c_str(), state.name.c_str(),
- (long long)state.residencyInMsecSinceBoot,
- (long long)state.totalTransitions,
- (long long)state.lastEntryTimestampMs);
- }
+ for (size_t i = 0; i < states.size(); i++) {
+ const PowerStatePlatformSleepState& state = states[i];
+
+ auto statePtr = make_shared<LogEvent>(android::util::PLATFORM_SLEEP_STATE,
+ timestamp);
+ statePtr->write(state.name);
+ statePtr->write(state.residencyInMsecSinceBoot);
+ statePtr->write(state.totalTransitions);
+ statePtr->write(state.supportedOnlyInSuspend);
+ statePtr->init();
+ data->push_back(statePtr);
+ VLOG("powerstate: %s, %lld, %lld, %d", state.name.c_str(),
+ (long long)state.residencyInMsecSinceBoot,
+ (long long)state.totalTransitions,
+ state.supportedOnlyInSuspend ? 1 : 0);
+ for (auto voter : state.voters) {
+ auto voterPtr = make_shared<LogEvent>(android::util::SLEEP_STATE_VOTER,
+ timestamp);
+ voterPtr->write(state.name);
+ voterPtr->write(voter.name);
+ voterPtr->write(voter.totalTimeInMsecVotedForSinceBoot);
+ voterPtr->write(voter.totalNumberOfTimesVotedSinceBoot);
+ voterPtr->init();
+ data->push_back(voterPtr);
+ VLOG("powerstatevoter: %s, %s, %lld, %lld", state.name.c_str(),
+ voter.name.c_str(),
+ (long long)voter.totalTimeInMsecVotedForSinceBoot,
+ (long long)voter.totalNumberOfTimesVotedSinceBoot);
}
}
});
+ if (!ret.isOk()) {
+ ALOGE("getLowPowerStats() failed: power HAL service not available");
+ gPowerHalV1_0 = nullptr;
+ return false;
+ }
+ }
+
+ if (mTagId == android::util::SUBSYSTEM_SLEEP_STATE) {
+ // Trying to cast to IPower 1.1, this will succeed only for devices supporting 1.1
+ sp<android::hardware::power::V1_1::IPower> gPowerHal_1_1 =
+ android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0);
+ if (gPowerHal_1_1 != nullptr) {
+ ret = gPowerHal_1_1->getSubsystemLowPowerStats(
+ [&data, timestamp](hidl_vec<PowerStateSubsystem> subsystems, Status status) {
+ if (status != Status::SUCCESS) return;
+
+ if (subsystems.size() > 0) {
+ for (size_t i = 0; i < subsystems.size(); i++) {
+ const PowerStateSubsystem& subsystem = subsystems[i];
+ for (size_t j = 0; j < subsystem.states.size(); j++) {
+ const PowerStateSubsystemSleepState& state =
+ subsystem.states[j];
+ auto subsystemStatePtr = make_shared<LogEvent>(
+ android::util::SUBSYSTEM_SLEEP_STATE, timestamp);
+ subsystemStatePtr->write(subsystem.name);
+ subsystemStatePtr->write(state.name);
+ subsystemStatePtr->write(state.residencyInMsecSinceBoot);
+ subsystemStatePtr->write(state.totalTransitions);
+ subsystemStatePtr->write(state.lastEntryTimestampMs);
+ subsystemStatePtr->write(state.supportedOnlyInSuspend);
+ subsystemStatePtr->init();
+ data->push_back(subsystemStatePtr);
+ VLOG("subsystemstate: %s, %s, %lld, %lld, %lld",
+ subsystem.name.c_str(), state.name.c_str(),
+ (long long)state.residencyInMsecSinceBoot,
+ (long long)state.totalTransitions,
+ (long long)state.lastEntryTimestampMs);
+ }
+ }
+ }
+ });
+ }
}
return true;
}
*/
class ResourcePowerManagerPuller : public StatsPuller {
public:
- bool Pull(const int tagId, vector<std::shared_ptr<LogEvent>>* data) override;
+ ResourcePowerManagerPuller(int tagId);
+ bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
};
} // namespace statsd
#include <private/android_filesystem_config.h>
#include "StatsCompanionServicePuller.h"
#include "StatsService.h"
+#include "guardrail/StatsdStats.h"
using namespace android;
using namespace android::base;
// The reading and parsing are implemented in Java. It is not difficult to port over. But for now
// let StatsCompanionService handle that and send the data back.
-bool StatsCompanionServicePuller::Pull(const int tagId, vector<shared_ptr<LogEvent> >* data) {
+StatsCompanionServicePuller::StatsCompanionServicePuller(int tagId) : StatsPuller(tagId) {
+}
+
+bool StatsCompanionServicePuller::PullInternal(vector<shared_ptr<LogEvent> >* data) {
sp<IStatsCompanionService> statsCompanion = StatsService::getStatsCompanionService();
vector<StatsLogEventWrapper> returned_value;
if (statsCompanion != NULL) {
- Status status = statsCompanion->pullData(tagId, &returned_value);
+ Status status = statsCompanion->pullData(mTagId, &returned_value);
if (!status.isOk()) {
- ALOGW("error pulling for %d", tagId);
+ ALOGW("error pulling for %d", mTagId);
return false;
}
data->clear();
std::copy(it.bytes.begin(), it.bytes.end(), tmp.buf + kLogMsgHeaderSize);
data->push_back(make_shared<LogEvent>(tmp));
}
- ALOGD("StatsCompanionServicePuller::pull succeeded for %d", tagId);
+ ALOGD("StatsCompanionServicePuller::pull succeeded for %d", mTagId);
return true;
} else {
ALOGW("statsCompanion not found!");
class StatsCompanionServicePuller : public StatsPuller {
public:
- bool Pull(const int tagId, vector<std::shared_ptr<LogEvent> >* data) override;
+ StatsCompanionServicePuller(int tagId);
+ bool PullInternal(vector<std::shared_ptr<LogEvent> >* data) override;
};
} // namespace statsd
--- /dev/null
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define DEBUG false // STOPSHIP if true
+#include "Log.h"
+
+#include "StatsPuller.h"
+#include "guardrail/StatsdStats.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+using std::lock_guard;
+
+// ValueMetric has a minimum bucket size of 10min so that we don't pull too frequently
+StatsPuller::StatsPuller(const int tagId)
+ : mTagId(tagId) {
+ if (StatsdStats::kPullerCooldownMap.find(tagId) == StatsdStats::kPullerCooldownMap.end()) {
+ mCoolDownSec = StatsdStats::kDefaultPullerCooldown;
+ } else {
+ mCoolDownSec = StatsdStats::kPullerCooldownMap[tagId];
+ }
+ VLOG("Puller for tag %d created. Cooldown set to %ld", mTagId, mCoolDownSec);
+}
+
+bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) {
+ lock_guard<std::mutex> lock(mLock);
+ StatsdStats::getInstance().notePull(mTagId);
+ long curTime = time(nullptr);
+ if (curTime - mLastPullTimeSec < mCoolDownSec) {
+ (*data) = mCachedData;
+ StatsdStats::getInstance().notePullFromCache(mTagId);
+ return true;
+ }
+ if (mMinPullIntervalSec > curTime - mLastPullTimeSec) {
+ mMinPullIntervalSec = curTime - mLastPullTimeSec;
+ StatsdStats::getInstance().updateMinPullIntervalSec(mTagId, mMinPullIntervalSec);
+ }
+ mCachedData.clear();
+ mLastPullTimeSec = curTime;
+ bool ret = PullInternal(&mCachedData);
+ if (ret) {
+ (*data) = mCachedData;
+ }
+ return ret;
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
#include <android/os/StatsLogEventWrapper.h>
#include <utils/String16.h>
+#include <mutex>
#include <vector>
+
#include "logd/LogEvent.h"
+#include "guardrail/StatsdStats.h"
using android::os::StatsLogEventWrapper;
-using std::vector;
namespace android {
namespace os {
class StatsPuller {
public:
- virtual ~StatsPuller(){};
+ StatsPuller(const int tagId);
+
+ virtual ~StatsPuller() {}
+
+ bool Pull(std::vector<std::shared_ptr<LogEvent>>* data);
+
+protected:
+ // The atom tag id this puller pulls
+ const int mTagId;
+
+private:
+ mutable std::mutex mLock;
+ // Minimum time before this puller does actual pull again.
+ // If a pull request comes before cooldown, a cached version from purevious pull
+ // will be returned.
+ // The actual value should be determined by individual pullers.
+ long mCoolDownSec;
+ // For puller stats
+ long mMinPullIntervalSec = LONG_MAX;
+
+ virtual bool PullInternal(std::vector<std::shared_ptr<LogEvent>>* data) = 0;
+
+ // Cache of data from last pull. If next request comes before cool down finishes,
+ // cached data will be returned.
+ std::vector<std::shared_ptr<LogEvent>> mCachedData;
- virtual bool Pull(const int tagId, vector<std::shared_ptr<LogEvent>>* data) = 0;
+ long mLastPullTimeSec;
};
} // namespace statsd
StatsPullerManagerImpl::StatsPullerManagerImpl()
: mCurrentPullingInterval(LONG_MAX) {
- shared_ptr<StatsPuller> statsCompanionServicePuller = make_shared<StatsCompanionServicePuller>();
- shared_ptr<StatsPuller> resourcePowerManagerPuller = make_shared<ResourcePowerManagerPuller>();
- shared_ptr<StatsPuller> cpuTimePerUidPuller = make_shared<CpuTimePerUidPuller>();
- shared_ptr<StatsPuller> cpuTimePerUidFreqPuller = make_shared<CpuTimePerUidFreqPuller>();
-
mPullers.insert({android::util::KERNEL_WAKELOCK,
- statsCompanionServicePuller});
+ make_shared<StatsCompanionServicePuller>(android::util::KERNEL_WAKELOCK)});
mPullers.insert({android::util::WIFI_BYTES_TRANSFER,
- statsCompanionServicePuller});
- mPullers.insert({android::util::MOBILE_BYTES_TRANSFER,
- statsCompanionServicePuller});
+ make_shared<StatsCompanionServicePuller>(android::util::WIFI_BYTES_TRANSFER)});
+ mPullers.insert(
+ {android::util::MOBILE_BYTES_TRANSFER,
+ make_shared<StatsCompanionServicePuller>(android::util::MOBILE_BYTES_TRANSFER)});
mPullers.insert({android::util::WIFI_BYTES_TRANSFER_BY_FG_BG,
- statsCompanionServicePuller});
+ make_shared<StatsCompanionServicePuller>(
+ android::util::WIFI_BYTES_TRANSFER_BY_FG_BG)});
mPullers.insert({android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG,
- statsCompanionServicePuller});
+ make_shared<StatsCompanionServicePuller>(
+ android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG)});
mPullers.insert({android::util::PLATFORM_SLEEP_STATE,
- resourcePowerManagerPuller});
+ make_shared<ResourcePowerManagerPuller>(android::util::PLATFORM_SLEEP_STATE)});
mPullers.insert({android::util::SLEEP_STATE_VOTER,
- resourcePowerManagerPuller});
- mPullers.insert({android::util::SUBSYSTEM_SLEEP_STATE,
- resourcePowerManagerPuller});
- mPullers.insert({android::util::CPU_TIME_PER_UID, cpuTimePerUidPuller});
- mPullers.insert({android::util::CPU_TIME_PER_UID_FREQ, cpuTimePerUidFreqPuller});
+ make_shared<ResourcePowerManagerPuller>(android::util::SLEEP_STATE_VOTER)});
+ mPullers.insert(
+ {android::util::SUBSYSTEM_SLEEP_STATE,
+ make_shared<ResourcePowerManagerPuller>(android::util::SUBSYSTEM_SLEEP_STATE)});
+ mPullers.insert({android::util::CPU_TIME_PER_FREQ, make_shared<StatsCompanionServicePuller>(android::util::CPU_TIME_PER_FREQ)});
+ mPullers.insert({android::util::CPU_TIME_PER_UID, make_shared<CpuTimePerUidPuller>()});
+ mPullers.insert({android::util::CPU_TIME_PER_UID_FREQ, make_shared<CpuTimePerUidFreqPuller>()});
mStatsCompanionService = StatsService::getStatsCompanionService();
}
if (DEBUG) ALOGD("Initiating pulling %d", tagId);
if (mPullers.find(tagId) != mPullers.end()) {
- bool ret = mPullers.find(tagId)->second->Pull(tagId, data);
+ bool ret = mPullers.find(tagId)->second->Pull(data);
ALOGD("pulled %d items", (int)data->size());
return ret;
} else {
#include "StatsdStats.h"
#include <android/util/ProtoOutputStream.h>
+#include "../stats_log_util.h"
#include "statslog.h"
namespace android {
const int FIELD_ID_ANOMALY_ALARMS_REGISTERED = 1;
+std::map<int, long> StatsdStats::kPullerCooldownMap = {
+ {android::util::KERNEL_WAKELOCK, 1},
+ {android::util::WIFI_BYTES_TRANSFER, 1},
+ {android::util::MOBILE_BYTES_TRANSFER, 1},
+ {android::util::WIFI_BYTES_TRANSFER_BY_FG_BG, 1},
+ {android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG, 1},
+ {android::util::PLATFORM_SLEEP_STATE, 1},
+ {android::util::SLEEP_STATE_VOTER, 1},
+ {android::util::SUBSYSTEM_SLEEP_STATE, 1},
+ {android::util::CPU_TIME_PER_FREQ, 1},
+ {android::util::CPU_TIME_PER_UID, 1},
+ {android::util::CPU_TIME_PER_UID_FREQ, 1},
+};
+
// TODO: add stats for pulled atoms.
StatsdStats::StatsdStats() {
mPushedAtomStats.resize(android::util::kMaxPushedAtomId + 1);
mAnomalyAlarmRegisteredStats++;
}
+void StatsdStats::updateMinPullIntervalSec(int pullAtomId, long intervalSec) {
+ lock_guard<std::mutex> lock(mLock);
+ mPulledAtomStats[pullAtomId].minPullIntervalSec = intervalSec;
+}
+
+void StatsdStats::notePull(int pullAtomId) {
+ lock_guard<std::mutex> lock(mLock);
+ mPulledAtomStats[pullAtomId].totalPull++;
+}
+
+void StatsdStats::notePullFromCache(int pullAtomId) {
+ lock_guard<std::mutex> lock(mLock);
+ mPulledAtomStats[pullAtomId].totalPullFromCache++;
+}
+
void StatsdStats::noteAtomLogged(int atomId, int32_t timeSec) {
lock_guard<std::mutex> lock(mLock);
configStats.clear_alert_stats();
}
- VLOG("********Atom stats***********");
+ VLOG("********Pushed Atom stats***********");
const size_t atomCounts = mPushedAtomStats.size();
for (size_t i = 2; i < atomCounts; i++) {
if (mPushedAtomStats[i] > 0) {
}
}
+ VLOG("********Pulled Atom stats***********");
+ for (const auto& pair : mPulledAtomStats) {
+ android::os::statsd::writePullerStatsToStream(pair, &proto);
+ VLOG("Atom %d->%ld, %ld, %ld\n", (int) pair.first, (long) pair.second.totalPull, (long) pair.second.totalPullFromCache, (long) pair.second.minPullIntervalSec);
+ }
+
if (mAnomalyAlarmRegisteredStats > 0) {
VLOG("********AnomalyAlarmStats stats***********");
long long token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_ANOMALY_ALARM_STATS);
#include "config/ConfigKey.h"
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
+#include "statslog.h"
#include <gtest/gtest_prod.h>
#include <log/log_time.h>
/* Min period between two checks of byte size per config key in nanoseconds. */
static const unsigned long long kMinByteSizeCheckPeriodNs = 10 * NS_PER_SEC;
+ // Default minimum interval between pulls for an atom. Pullers can return cached values if
+ // another pull request happens within this interval.
+ static std::map<int, long> kPullerCooldownMap;
+
+ // Default cooldown time for a puller
+ static const long kDefaultPullerCooldown = 1;
+
/**
* Report a new config has been received and report the static stats about the config.
*
void setUidMapChanges(int changes);
void setCurrentUidMapMemory(int bytes);
+ // Update minimum interval between pulls for an pulled atom
+ void updateMinPullIntervalSec(int pullAtomId, long intervalSec);
+
+ // Notify pull request for an atom
+ void notePull(int pullAtomId);
+
+ // Notify pull request for an atom served from cached data
+ void notePullFromCache(int pullAtomId);
+
/**
* Reset the historical stats. Including all stats in icebox, and the tracked stats about
* metrics, matchers, and atoms. The active configs will be kept and StatsdStats will continue
*/
void dumpStats(std::vector<uint8_t>* buffer, bool reset);
+ typedef struct {
+ long totalPull;
+ long totalPullFromCache;
+ long minPullIntervalSec;
+ } PulledAtomStats;
+
private:
StatsdStats();
// This is a vector, not a map because it will be accessed A LOT -- for each stats log.
std::vector<int> mPushedAtomStats;
+ std::map<int, PulledAtomStats> mPulledAtomStats;
+
// Stores the number of times statsd modified the anomaly alarm registered with
// StatsCompanionService.
int mAnomalyAlarmRegisteredStats = 0;
}
}
+ mCurrentSlicedBucketForAnomaly = std::make_shared<DimToValMap>();
mCurrentSlicedBucket = std::make_shared<DimToGaugeFieldsMap>();
// Adjusts the bucket start time
optional int32 alarms_registered = 1;
}
optional AnomalyAlarmStats anomaly_alarm_stats = 9;
+
+ message PulledAtomStats {
+ optional int32 atom_id = 1;
+ optional int64 total_pull = 2;
+ optional int64 total_pull_from_cache = 3;
+ optional int64 min_pull_interval_sec = 4;
+ }
+ repeated PulledAtomStats pulled_atom_stats = 10;
}
\ No newline at end of file
// for MessageValue Proto
const int FIELD_ID_FIELD_VALUE_IN_MESSAGE_VALUE_PROTO = 1;
+// for PulledAtomStats proto
+const int FIELD_ID_PULLED_ATOM_STATS = 10;
+const int FIELD_ID_PULL_ATOM_ID = 1;
+const int FIELD_ID_TOTAL_PULL = 2;
+const int FIELD_ID_TOTAL_PULL_FROM_CACHE = 3;
+const int FIELD_ID_MIN_PULL_INTERVAL_SEC = 4;
+
void writeDimensionsValueProtoToStream(const DimensionsValue& dimensionsValue,
ProtoOutputStream* protoOutput) {
protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, dimensionsValue.field());
}
}
+void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>& pair,
+ util::ProtoOutputStream* protoOutput) {
+ long long token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_PULLED_ATOM_STATS |
+ FIELD_COUNT_REPEATED);
+ protoOutput->write(FIELD_TYPE_INT32 | FIELD_ID_PULL_ATOM_ID, (int32_t)pair.first);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_TOTAL_PULL, (long long)pair.second.totalPull);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_TOTAL_PULL_FROM_CACHE,
+ (long long)pair.second.totalPullFromCache);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MIN_PULL_INTERVAL_SEC,
+ (long long)pair.second.minPullIntervalSec);
+ protoOutput->end(token);
+}
+
} // namespace statsd
} // namespace os
} // namespace android
\ No newline at end of file
#pragma once
#include <android/util/ProtoOutputStream.h>
-#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
-#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
#include "field_util.h"
+#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "guardrail/StatsdStats.h"
namespace android {
namespace os {
namespace statsd {
// Helper function to write DimensionsValue proto to ProtoOutputStream.
-void writeDimensionsValueProtoToStream(
- const DimensionsValue& fieldValue, util::ProtoOutputStream* protoOutput);
+void writeDimensionsValueProtoToStream(const DimensionsValue& fieldValue,
+ util::ProtoOutputStream* protoOutput);
// Helper function to write Field proto to ProtoOutputStream.
-void writeFieldProtoToStream(
- const Field& field, util::ProtoOutputStream* protoOutput);
+void writeFieldProtoToStream(const Field& field, util::ProtoOutputStream* protoOutput);
// Helper function to construct the field value tree and write to ProtoOutputStream
-void writeFieldValueTreeToStream(const FieldValueMap &fieldValueMap,
- util::ProtoOutputStream* protoOutput);
+void writeFieldValueTreeToStream(const FieldValueMap& fieldValueMap,
+ util::ProtoOutputStream* protoOutput);
// Convert the TimeUnit enum to the bucket size in millis.
int64_t TimeUnitToBucketSizeInMillis(TimeUnit unit);
+// Helper function to write PulledAtomStats to ProtoOutputStream
+void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>& pair,
+ util::ProtoOutputStream* protoOutput);
} // namespace statsd
} // namespace os
} // namespace android
\ No newline at end of file