Skip to content

Instantly share code, notes, and snippets.

@jkuipers
Created January 14, 2022 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkuipers/1e0bfaf7dcb2c4002864be7813343272 to your computer and use it in GitHub Desktop.
Save jkuipers/1e0bfaf7dcb2c4002864be7813343272 to your computer and use it in GitHub Desktop.
Micrometer.io heap statistics for OpenJ9 VMs
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.BaseUnits;
import io.micrometer.core.instrument.binder.MeterBinder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
/**
* Provides the used heap memory as a percentage so that we can scale based on that metric.
* Uses OpenJ9-specific class, therefore the code uses reflection so that this will also
* compile using an OpenJDK.
*
* @see <a href="https://www.eclipse.org/openj9/docs/api/jdk11/openj9.jvm/com/ibm/jvm/Stats.html">JavaDoc for Stats</a>
*/
public class OpenJ9MemoryMetrics implements MeterBinder {
private Object stats;
private Method getStats;
private Method getUsedHeap;
private long maxHeap;
private Logger logger = LoggerFactory.getLogger(getClass());
public OpenJ9MemoryMetrics() {
try {
Class statsClass = Class.forName("com.ibm.jvm.Stats");
this.stats = statsClass.getDeclaredConstructor().newInstance();
this.getStats = statsClass.getMethod("getStats");
this.getUsedHeap = statsClass.getMethod("getUsedHeap");
ReflectionUtils.invokeMethod(getStats, stats);
this.maxHeap = (long) ReflectionUtils.invokeMethod(statsClass.getMethod("getMaxHeap"), stats);
} catch (Exception e) {
logger.error("Failed to initialize OpenJ9MemoryMetrics", e);
}
}
@Override
public void bindTo(MeterRegistry registry) {
if (this.maxHeap != 0L) {
try {
Gauge.builder("jvm.memory.heap-used-percentage", stats, stats -> {
ReflectionUtils.invokeMethod(getStats, stats);
long usedHeap = (long) ReflectionUtils.invokeMethod(getUsedHeap, stats);
return ((double) usedHeap) / maxHeap;
})
.description("Percentage of heap used by the JVM in the range [0..1], based on used divided by max as reported by OpenJ9's Stats class")
.baseUnit(BaseUnits.PERCENT)
.register(registry);
} catch (Exception e) {
logger.error("Could not create heap percentage gauge", e);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment