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

com.clickzetta.platform.metrics.NettyMemoryMetrics Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
package com.clickzetta.platform.metrics;

import com.codahale.metrics.Gauge;
import com.codahale.metrics.Metric;
import com.codahale.metrics.MetricRegistry;
import com.google.common.annotations.VisibleForTesting;
import io.netty.buffer.PoolArenaMetric;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.buffer.PooledByteBufAllocatorL;
import io.netty.buffer.PooledByteBufAllocatorMetric;
import org.apache.arrow.memory.NettyAllocationManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

public class NettyMemoryMetrics extends MetricBase {

  private static final Logger LOG = LoggerFactory.getLogger(NettyMemoryMetrics.class);

  @VisibleForTesting
  static final Set VERBOSE_METRICS = new HashSet<>();

  static {
    VERBOSE_METRICS.addAll(Arrays.asList(
        "numAllocations",
        "numTinyAllocations",
        "numSmallAllocations",
        "numNormalAllocations",
        "numHugeAllocations",
        "numDeallocations",
        "numTinyDeallocations",
        "numSmallDeallocations",
        "numNormalDeallocations",
        "numHugeDeallocations",
        "numActiveAllocations",
        "numActiveTinyAllocations",
        "numActiveSmallAllocations",
        "numActiveNormalAllocations",
        "numActiveHugeAllocations",
        "numActiveBytes"));
  }

  private final boolean verboseMetricsEnabled;

  private static volatile NettyMemoryMetrics INSTANCE = null;

  public static NettyMemoryMetrics getInstance(boolean verboseMetricsEnabled) {
    if (INSTANCE == null) {
      synchronized (NettyMemoryMetrics.class) {
        if (INSTANCE == null) {
          INSTANCE = new NettyMemoryMetrics(verboseMetricsEnabled);
        }
      }
    }
    return INSTANCE;
  }

  private NettyMemoryMetrics(boolean verboseMetricsEnabled) {
    super(new LinkedHashMap() {{
      put("namespace", "NettyMemory");
      put("server", "NettyMemory");
    }});
    this.verboseMetricsEnabled = verboseMetricsEnabled;
    registerMetrics();
  }

  private void registerMetrics() {
    PooledByteBufAllocatorMetric pooledAllocatorMetric = null;
    try {
      Field INNER_ALLOCATOR = NettyAllocationManager.class.getDeclaredField("INNER_ALLOCATOR");
      INNER_ALLOCATOR.setAccessible(true);
      PooledByteBufAllocatorL allocator = (PooledByteBufAllocatorL) INNER_ALLOCATOR.get(null);

      Class pooledByteBufAllocatorLClass = allocator.getClass();
      Field field = pooledByteBufAllocatorLClass.getDeclaredField("allocator");
      field.setAccessible(true);
      PooledByteBufAllocator pooledByteBufAllocator = (PooledByteBufAllocator) field.get(allocator);
      pooledAllocatorMetric = pooledByteBufAllocator.metric();
    } catch (Throwable t) {
      LOG.warn("ignore get PooledByteBufAllocatorMetric failed.", t);
    }

    if (pooledAllocatorMetric != null) {
      // Register general metrics.
      register("usedHeapMemory", new NettyHeapMemoryGauge(pooledAllocatorMetric));
      register("usedDirectMemory", new NettyDirectMemoryGauge(pooledAllocatorMetric));

      if (verboseMetricsEnabled) {
        int directArenaIndex = 0;
        for (PoolArenaMetric metric : pooledAllocatorMetric.directArenas()) {
          registerArenaMetric(metric, "directArena" + directArenaIndex);
          directArenaIndex++;
        }

        int heapArenaIndex = 0;
        for (PoolArenaMetric metric : pooledAllocatorMetric.heapArenas()) {
          registerArenaMetric(metric, "heapArena" + heapArenaIndex);
          heapArenaIndex++;
        }
      }
    }
  }

  private void registerArenaMetric(PoolArenaMetric arenaMetric, String arenaName) {
    for (String methodName : VERBOSE_METRICS) {
      Method m;
      try {
        m = PoolArenaMetric.class.getMethod(methodName);
      } catch (Exception e) {
        // Failed to find metric related method, ignore this metric.
        continue;
      }

      if (!Modifier.isPublic(m.getModifiers())) {
        // Ignore non-public methods.
        continue;
      }

      Class returnType = m.getReturnType();
      String metricName = MetricRegistry.name(arenaName, m.getName());
      if (returnType.equals(int.class)) {
        register(metricName, (Gauge) () -> {
          try {
            return (Integer) m.invoke(arenaMetric);
          } catch (Exception e) {
            return -1; // Swallow the exceptions.
          }
        });
      } else if (returnType.equals(long.class)) {
        register(metricName, (Gauge) () -> {
          try {
            return (Long) m.invoke(arenaMetric);
          } catch (Exception e) {
            return -1L; // Swallow the exceptions.
          }
        });
      }
    }
  }

  @Override
  protected  void recoveryFromMetrics(List metric) {
    throw new UnsupportedOperationException();
  }

  public static class NettyHeapMemoryGauge implements Gauge {
    private final PooledByteBufAllocatorMetric metric;

    public NettyHeapMemoryGauge(PooledByteBufAllocatorMetric metric) {
      this.metric = metric;
    }

    @Override
    public Long getValue() {
      return metric.usedHeapMemory();
    }
  }

  public static class NettyDirectMemoryGauge implements Gauge {
    private final PooledByteBufAllocatorMetric metric;

    public NettyDirectMemoryGauge(PooledByteBufAllocatorMetric metric) {
      this.metric = metric;
    }

    @Override
    public Long getValue() {
      return metric.usedDirectMemory();
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy