1 // Copyright 2023 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.net.telemetry; 6 7 import android.os.SystemClock; 8 9 /** 10 * This allows us to do ratelimiting based on the time difference between the last log action and 11 * the current log action. This class allows us to specify the number of samples/second we want for 12 * each request. 13 */ 14 public final class RateLimiter { 15 private static final long ONE_SECOND_MILLIS = 1000L; 16 17 private final Object mLock = new Object(); 18 // The last tracked time 19 private final int mSamplesPerSeconds; 20 private int mSamplesLoggedDuringSecond; 21 private long mLastPermitMillis = Long.MIN_VALUE; 22 RateLimiter(int samplesPerSeconds)23 public RateLimiter(int samplesPerSeconds) { 24 if (samplesPerSeconds <= 0) { 25 throw new IllegalArgumentException("Expect sample rate to be > 0 sample(s) per second"); 26 } 27 28 this.mSamplesPerSeconds = samplesPerSeconds; 29 } 30 31 // Check if rate limiting should happen based on a time passed or sample rate. tryAcquire()32 public boolean tryAcquire() { 33 synchronized (mLock) { 34 long currentMillis = SystemClock.elapsedRealtime(); 35 36 if (mLastPermitMillis + ONE_SECOND_MILLIS <= currentMillis) { 37 // reset samplesLoggedDuringSecond and stopwatch once a second has passed 38 mSamplesLoggedDuringSecond = 1; 39 mLastPermitMillis = currentMillis; 40 return true; 41 } else if (mSamplesLoggedDuringSecond < mSamplesPerSeconds) { 42 mSamplesLoggedDuringSecond++; 43 return true; 44 } 45 return false; 46 } 47 } 48 } 49