Skip to content

Commit

Permalink
DefaultRefreshable oversubscription logging is rate limited
Browse files Browse the repository at this point in the history
In cases where this logging occurs, it's likely to occur a _lot_.
It's not terribly helpful to log a warning+stack trace every time,
so we allow a maximum of ten per second per refreshable.
  • Loading branch information
carterkozak committed May 7, 2024
1 parent c8abce6 commit f87997e
Showing 1 changed file with 5 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.RateLimiter;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.palantir.logsafe.DoNotLog;
import com.palantir.logsafe.SafeArg;
Expand Down Expand Up @@ -55,6 +56,8 @@ final class DefaultRefreshable<@DoNotLog T> implements SettableRefreshable<T> {

private static final int WARN_THRESHOLD = 1000;

private final RateLimiter warningRateLimiter;

/** Subscribers are updated in deterministic order based on registration order. This prevents a class
* of bugs where a listener on a refreshable uses a refreshable mapped from itself, and guarantees the child
* mappings will be up-to-date before the listener is executed, as long as the input mapping occurred before
Expand Down Expand Up @@ -93,6 +96,7 @@ private DefaultRefreshable(T current, Optional<?> strongParentReference, RootSub
this.current = current;
this.strongParentReference = strongParentReference;
this.rootSubscriberTracker = tracker;
this.warningRateLimiter = RateLimiter.create(10);
ReadWriteLock lock = new ReentrantReadWriteLock();
writeLock = lock.writeLock();
readLock = lock.readLock();
Expand Down Expand Up @@ -225,7 +229,7 @@ public <R> Refreshable<R> map(Function<? super T, R> function) {
private void preSubscribeLogging() {
if (log.isWarnEnabled()) {
int subscribers = orderedSubscribers.size() + 1;
if (subscribers > WARN_THRESHOLD) {
if (subscribers > WARN_THRESHOLD && warningRateLimiter.tryAcquire()) {
log.warn(
"Refreshable {} has an excessive number of subscribers: {} and is likely leaking memory. "
+ "The current warning threshold is {}.",
Expand Down

0 comments on commit f87997e

Please sign in to comment.