Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 85ed8387 authored by Chenjie Yu's avatar Chenjie Yu
Browse files

align metrics to 5min bundary

We use one alarm clock for all pulled atoms.
If metrics from different configs are not aligned,
the clock will be set to repeat at higher and higher
frequency, and consume a lot of battery.
Current implementation assumes a 5min minimum bucket
size. New metric start time is set to be aligned to
the start time of statsd in the next 5min.
So it will ignore events up to 5min.

align puller alarm to minute bundary

Test: unit test
Change-Id: I77ffa3c13de363c780b1000181b9a9b780dd0846
parent 14b1f3ed
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "android-base/stringprintf.h"
#include "guardrail/StatsdStats.h"
#include "metrics/CountMetricProducer.h"
#include "external/StatsPullerManager.h"
#include "stats_util.h"
#include "storage/StorageManager.h"

@@ -63,10 +64,15 @@ const int FIELD_ID_UID_MAP = 2;
StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap,
                                     const sp<AnomalyMonitor>& anomalyMonitor,
                                     const std::function<void(const ConfigKey&)>& sendBroadcast)
    : mUidMap(uidMap), mAnomalyMonitor(anomalyMonitor), mSendBroadcast(sendBroadcast) {
    : mUidMap(uidMap),
      mAnomalyMonitor(anomalyMonitor),
      mSendBroadcast(sendBroadcast),
      mTimeBaseSec(time(nullptr)) {
    // On each initialization of StatsLogProcessor, check stats-data directory to see if there is
    // any left over data to be read.
    StorageManager::sendBroadcast(STATS_DATA_DIR, mSendBroadcast);
    StatsPullerManager statsPullerManager;
    statsPullerManager.SetTimeBaseSec(mTimeBaseSec);
}

StatsLogProcessor::~StatsLogProcessor() {
@@ -108,7 +114,7 @@ void StatsLogProcessor::OnLogEvent(const LogEvent& msg) {

void StatsLogProcessor::OnConfigUpdated(const ConfigKey& key, const StatsdConfig& config) {
    ALOGD("Updated configuration for key %s", key.ToString().c_str());
    unique_ptr<MetricsManager> newMetricsManager = std::make_unique<MetricsManager>(key, config);
    unique_ptr<MetricsManager> newMetricsManager = std::make_unique<MetricsManager>(key, config, mTimeBaseSec);

    auto it = mMetricsManagers.find(key);
    if (it == mMetricsManagers.end() && mMetricsManagers.size() > StatsdStats::kMaxConfigCount) {
+2 −0
Original line number Diff line number Diff line
@@ -76,6 +76,8 @@ private:
    // to retrieve the stored data.
    std::function<void(const ConfigKey& key)> mSendBroadcast;

    const long mTimeBaseSec;

    FRIEND_TEST(StatsLogProcessorTest, TestRateLimitByteSize);
    FRIEND_TEST(StatsLogProcessorTest, TestRateLimitBroadcast);
    FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge);
+27 −19
Original line number Diff line number Diff line
@@ -26,7 +26,9 @@ class StatsPullerManager{
 public:
    virtual ~StatsPullerManager() {}

  virtual void RegisterReceiver(int tagId, wp<PullDataReceiver> receiver, long intervalMs) {
    virtual void RegisterReceiver(int tagId,
                                  wp <PullDataReceiver> receiver,
                                  long intervalMs) {
        mPullerManager.RegisterReceiver(tagId, receiver, intervalMs);
    };

@@ -43,12 +45,18 @@ class StatsPullerManager{
        mPullerManager.OnAlarmFired();
    }

  virtual bool Pull(const int tagId, vector<std::shared_ptr<LogEvent>>* data) {
    virtual bool
    Pull(const int tagId, vector<std::shared_ptr<LogEvent>>* data) {
        return mPullerManager.Pull(tagId, data);
    }

    virtual void SetTimeBaseSec(const long timeBaseSec) {
        mPullerManager.SetTimeBaseSec(timeBaseSec);
    }

 private:
  StatsPullerManagerImpl& mPullerManager = StatsPullerManagerImpl::GetInstance();
    StatsPullerManagerImpl
        & mPullerManager = StatsPullerManagerImpl::GetInstance();
};

}  // namespace statsd
+10 −10
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ namespace os {
namespace statsd {

StatsPullerManagerImpl::StatsPullerManagerImpl()
    : mCurrentPullingInterval(LONG_MAX), mPullStartTimeMs(get_pull_start_time_ms()) {
    : mCurrentPullingInterval(LONG_MAX) {
    shared_ptr<StatsPuller> statsCompanionServicePuller = make_shared<StatsCompanionServicePuller>();
    shared_ptr<StatsPuller> resourcePowerManagerPuller = make_shared<ResourcePowerManagerPuller>();
    shared_ptr<StatsPuller> cpuTimePerUidPuller = make_shared<CpuTimePerUidPuller>();
@@ -94,11 +94,6 @@ bool StatsPullerManagerImpl::PullerForMatcherExists(int tagId) const {
    return mPullers.find(tagId) != mPullers.end();
}

long StatsPullerManagerImpl::get_pull_start_time_ms() const {
    // TODO: limit and align pull intervals to 10min boundaries if this turns out to be a problem
    return time(nullptr) * 1000;
}

void StatsPullerManagerImpl::RegisterReceiver(int tagId, wp<PullDataReceiver> receiver,
                                              long intervalMs) {
    AutoMutex _l(mReceiversLock);
@@ -114,12 +109,17 @@ void StatsPullerManagerImpl::RegisterReceiver(int tagId, wp<PullDataReceiver> re
    receiverInfo.timeInfo.first = intervalMs;
    receivers.push_back(receiverInfo);

    // Round it to the nearest minutes. This is the limit of alarm manager.
    // In practice, we should limit it higher.
    long roundedIntervalMs = intervalMs/1000/60 * 1000 * 60;
    // There is only one alarm for all pulled events. So only set it to the smallest denom.
    if (intervalMs < mCurrentPullingInterval) {
    if (roundedIntervalMs < mCurrentPullingInterval) {
        VLOG("Updating pulling interval %ld", intervalMs);
        mCurrentPullingInterval = intervalMs;
        mCurrentPullingInterval = roundedIntervalMs;
        long currentTimeMs = time(nullptr) * 1000;
        long nextAlarmTimeMs = currentTimeMs + mCurrentPullingInterval - (currentTimeMs - mTimeBaseSec * 1000) % mCurrentPullingInterval;
        if (mStatsCompanionService != nullptr) {
            mStatsCompanionService->setPullingAlarms(mPullStartTimeMs, mCurrentPullingInterval);
            mStatsCompanionService->setPullingAlarms(nextAlarmTimeMs, mCurrentPullingInterval);
        } else {
            VLOG("Failed to update pulling interval");
        }
@@ -146,7 +146,7 @@ void StatsPullerManagerImpl::UnRegisterReceiver(int tagId, wp<PullDataReceiver>
void StatsPullerManagerImpl::OnAlarmFired() {
    AutoMutex _l(mReceiversLock);

    uint64_t currentTimeMs = time(nullptr) * 1000;
    uint64_t currentTimeMs = time(nullptr) /60 * 60 * 1000;

    vector<pair<int, vector<ReceiverInfo*>>> needToPull =
            vector<pair<int, vector<ReceiverInfo*>>>();
+4 −5
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ public:

    bool Pull(const int tagId, vector<std::shared_ptr<LogEvent>>* data);

    void SetTimeBaseSec(long timeBaseSec) {mTimeBaseSec = timeBaseSec;};

private:
    StatsPullerManagerImpl();

@@ -73,11 +75,8 @@ private:

    // for pulled metrics, it is important for the buckets to be aligned to multiple of smallest
    // bucket size. All pulled metrics start pulling based on this time, so that they can be
    // correctly attributed to the correct buckets. Pulled data attach a timestamp which is the
    // request time.
    const long mPullStartTimeMs;

    long get_pull_start_time_ms() const;
    // correctly attributed to the correct buckets.
    long mTimeBaseSec;

    LogEvent parse_pulled_data(String16 data);
};
Loading