1 /*
2 * Copyright (C) 2025 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
17 #define STATSD_DEBUG false // STOPSHIP if true
18
19 #include "Log.h"
20
21 #include "LoggingRate.h"
22
23 #include <algorithm>
24
25 using namespace std;
26
27 namespace android {
28 namespace os {
29 namespace statsd {
30
LoggingRate(int maxStatsNum,int64_t logFrequencyWindowNs)31 LoggingRate::LoggingRate(int maxStatsNum, int64_t logFrequencyWindowNs)
32 : mMaxRateInfoSize(maxStatsNum), mLogFrequencyWindowNs(logFrequencyWindowNs) {
33 }
34
noteLogEvent(uint32_t atomId,int64_t eventTimestampNs)35 void LoggingRate::noteLogEvent(uint32_t atomId, int64_t eventTimestampNs) {
36 auto rateInfoIt = mRateInfo.find(atomId);
37
38 if (rateInfoIt != mRateInfo.end()) {
39 RateInfo& rateInfo = rateInfoIt->second;
40 if (eventTimestampNs - rateInfo.intervalStartNs >= mLogFrequencyWindowNs) {
41 rateInfo.intervalStartNs = eventTimestampNs;
42 rateInfo.rate = 1;
43 } else {
44 // update rateInfo
45 rateInfo.rate++;
46 #ifdef STATSD_DEBUG
47 if (rateInfo.maxRate < rateInfo.rate) {
48 VLOG("For Atom %d new maxRate is %d", atomId, rateInfo.rate);
49 }
50 #endif
51 rateInfo.maxRate = max(rateInfo.maxRate, rateInfo.rate);
52 }
53 } else if (mRateInfo.size() < mMaxRateInfoSize) {
54 // atomId not found, add it to the map with initial frequency
55 mRateInfo[atomId] = {eventTimestampNs, 1, 1};
56 }
57 }
58
getMaxRate(uint32_t atomId) const59 int32_t LoggingRate::getMaxRate(uint32_t atomId) const {
60 const auto rateInfoIt = mRateInfo.find(atomId);
61 if (rateInfoIt != mRateInfo.end()) {
62 return rateInfoIt->second.maxRate;
63 }
64 return 0;
65 }
66
getMaxRates(size_t topN) const67 std::vector<LoggingRate::PeakRatePerAtomId> LoggingRate::getMaxRates(size_t topN) const {
68 std::vector<PeakRatePerAtomId> result;
69 result.reserve(mRateInfo.size());
70
71 for (auto& [atomId, rateInfo] : mRateInfo) {
72 result.emplace_back(atomId, rateInfo.maxRate);
73 }
74
75 std::sort(result.begin(), result.end(),
76 [](const PeakRatePerAtomId& a, const PeakRatePerAtomId& b) {
77 return a.second > b.second;
78 });
79
80 if (topN < result.size()) {
81 result.erase(result.begin() + topN, result.end());
82 }
83
84 return result;
85 }
86
reset()87 void LoggingRate::reset() {
88 mRateInfo.clear();
89 }
90
91 } // namespace statsd
92 } // namespace os
93 } // namespace android
94