1 /* 2 * Copyright (C) 2024 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 #pragma once 18 19 #include <stdint.h> 20 21 #include <thread> 22 #include <unordered_map> 23 24 #include "utils.h" 25 26 class RealTimeClock { 27 public: getTimeNs()28 static int64_t getTimeNs() { 29 return get_elapsed_realtime_ns(); 30 } 31 }; 32 33 template <typename Clock> 34 class LoggingRateLimiter { 35 public: LoggingRateLimiter(int32_t logFrequencyThreshold,int32_t logFrequencyWindowMs)36 LoggingRateLimiter(int32_t logFrequencyThreshold, int32_t logFrequencyWindowMs) 37 : mLogFrequencyThreshold(logFrequencyThreshold), 38 mLogFrequencyWindowNs(logFrequencyWindowMs * 1000000) { 39 } 40 canLogAtom(uint32_t atomId)41 bool canLogAtom(uint32_t atomId) { 42 const int64_t nowNs = Clock::getTimeNs(); 43 44 std::unique_lock<std::mutex> lock(mMutex); 45 46 // update current logging frequency 47 auto atomFrequencyIt = mLogFrequencies.find(atomId); 48 49 if (atomFrequencyIt != mLogFrequencies.end()) { 50 Frequency& frequency = atomFrequencyIt->second; 51 if (nowNs - frequency.intervalStartNs >= mLogFrequencyWindowNs) { 52 frequency.intervalStartNs = nowNs; 53 frequency.logsCount = 1; 54 return true; 55 } else { 56 // update frequency 57 frequency.logsCount++; 58 } 59 return isLoggingUnderThreshold(frequency.logsCount); 60 } 61 // atomId not found, add it to the map with initial frequency 62 mLogFrequencies[atomId] = {nowNs, 1}; 63 return true; 64 } 65 66 private: isLoggingUnderThreshold(int32_t logsCount)67 bool isLoggingUnderThreshold(int32_t logsCount) const { 68 return logsCount <= mLogFrequencyThreshold; 69 } 70 71 std::mutex mMutex; 72 73 const int32_t mLogFrequencyThreshold; 74 const int64_t mLogFrequencyWindowNs; 75 76 struct Frequency { 77 int64_t intervalStartNs; 78 int32_t logsCount; 79 }; 80 81 // Key is atom id. 82 std::unordered_map<uint32_t, Frequency> mLogFrequencies; 83 }; 84