All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wavefront.agent.ProxyMemoryGuard Maven / Gradle / Ivy

There is a newer version: 4.36
Show newest version
package com.wavefront.agent;

import static com.wavefront.common.Utils.lazySupplier;

import com.google.common.base.Preconditions;
import com.wavefront.common.TaggedMetricName;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Counter;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryNotificationInfo;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryType;
import java.util.function.Supplier;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
import javax.management.NotificationEmitter;

/**
 * Logic around OoM protection logic that drains memory buffers on MEMORY_THRESHOLD_EXCEEDED
 * notifications, extracted from AbstractAgent.
 *
 * @author [email protected]
 */
public class ProxyMemoryGuard {
  private static final Logger logger = Logger.getLogger(ProxyMemoryGuard.class.getCanonicalName());

  private final Supplier drainBuffersCount =
      lazySupplier(
          () ->
              Metrics.newCounter(
                  new TaggedMetricName("buffer", "flush-count", "reason", "heapUsageThreshold")));

  /**
   * Set up the memory guard.
   *
   * @param flushTask runnable to invoke when in-memory buffers need to be drained to disk
   * @param threshold memory usage threshold that is considered critical, 0 < threshold <= 1.
   */
  public ProxyMemoryGuard(@Nonnull final Runnable flushTask, double threshold) {
    Preconditions.checkArgument(threshold > 0, "ProxyMemoryGuard threshold must be > 0!");
    Preconditions.checkArgument(threshold <= 1, "ProxyMemoryGuard threshold must be <= 1!");
    MemoryPoolMXBean tenuredGenPool = getTenuredGenPool();
    if (tenuredGenPool == null) return;
    tenuredGenPool.setUsageThreshold((long) (tenuredGenPool.getUsage().getMax() * threshold));

    NotificationEmitter emitter = (NotificationEmitter) ManagementFactory.getMemoryMXBean();
    emitter.addNotificationListener(
        (notification, obj) -> {
          if (notification.getType().equals(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED)) {
            logger.warning("Heap usage threshold exceeded - draining buffers to disk!");
            drainBuffersCount.get().inc();
            flushTask.run();
            logger.info("Draining buffers to disk: finished");
          }
        },
        null,
        null);
  }

  private MemoryPoolMXBean getTenuredGenPool() {
    for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {
      if (pool.getType() == MemoryType.HEAP && pool.isUsageThresholdSupported()) {
        return pool;
      }
    }
    return null;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy