diff --git a/src/main/java/com/etsy/statsd/profiler/profilers/MemoryProfiler.java b/src/main/java/com/etsy/statsd/profiler/profilers/MemoryProfiler.java index 2e3959e..e3d68eb 100644 --- a/src/main/java/com/etsy/statsd/profiler/profilers/MemoryProfiler.java +++ b/src/main/java/com/etsy/statsd/profiler/profilers/MemoryProfiler.java @@ -22,12 +22,14 @@ public class MemoryProfiler extends Profiler { private List gcMXBeans; private HashMap gcTimes = new HashMap<>(); private ClassLoadingMXBean classLoadingMXBean; + private List memoryPoolMXBeans; public MemoryProfiler(Reporter reporter, Arguments arguments) { super(reporter, arguments); memoryMXBean = ManagementFactory.getMemoryMXBean(); gcMXBeans = ManagementFactory.getGarbageCollectorMXBeans(); classLoadingMXBean = ManagementFactory.getClassLoadingMXBean(); + memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans(); for (GarbageCollectorMXBean b : gcMXBeans) gcTimes.put(b, new AtomicLong()); } @@ -67,8 +69,8 @@ private void recordStats() { MemoryUsage nonHeap = memoryMXBean.getNonHeapMemoryUsage(); recordGaugeValue("pending-finalization-count", finalizationPendingCount); - recordMemoryUsage("heap", heap); - recordMemoryUsage("nonheap", nonHeap); + recordMemoryUsage("heap.total", heap); + recordMemoryUsage("nonheap.total", nonHeap); for (GarbageCollectorMXBean gcMXBean : gcMXBeans) { recordGaugeValue("gc." + gcMXBean.getName() + ".count", gcMXBean.getCollectionCount()); @@ -90,6 +92,15 @@ private void recordStats() { recordGaugeValue("loaded-class-count", loadedClassCount); recordGaugeValue("total-loaded-class-count", totalLoadedClassCount); recordGaugeValue("unloaded-class-count", unloadedClassCount); + + for (MemoryPoolMXBean memoryPoolMXBean: memoryPoolMXBeans) { + String type = poolTypeToMetricName(memoryPoolMXBean.getType()); + String name = poolNameToMetricName(memoryPoolMXBean.getName()); + String prefix = type + '.' + name; + MemoryUsage usage = memoryPoolMXBean.getUsage(); + + recordMemoryUsage(prefix, usage); + } } /** @@ -104,4 +115,31 @@ private void recordMemoryUsage(String prefix, MemoryUsage memory) { recordGaugeValue(prefix + ".committed", memory.getCommitted()); recordGaugeValue(prefix + ".max", memory.getMax()); } + + /** + * Formats a MemoryType into a valid metric name + * + * @param memoryType a MemoryType + * @return a valid metric name + */ + private String poolTypeToMetricName(MemoryType memoryType) { + switch (memoryType) { + case HEAP: + return "heap"; + case NON_HEAP: + return "nonheap"; + default: + return "unknown"; + } + } + + /** + * Formats a pool name into a valid metric name + * + * @param poolName a pool name + * @return a valid metric name + */ + private String poolNameToMetricName(String poolName) { + return poolName.toLowerCase().replaceAll("\\s+", "-"); + } } diff --git a/visualization/influxdb-dashboard/public/scripts/render-client.js b/visualization/influxdb-dashboard/public/scripts/render-client.js index 6fcbcdb..30076d9 100644 --- a/visualization/influxdb-dashboard/public/scripts/render-client.js +++ b/visualization/influxdb-dashboard/public/scripts/render-client.js @@ -13,7 +13,7 @@ $(document).ready(function() { config = data; } }); - + var user = params.user; var job = params.job; var run = params.run; @@ -24,8 +24,8 @@ $(document).ready(function() { var prefix = base + '.' + user + '.' + job + '.' + run + '.' + stage + '.' + phase; var cpuPrefix = prefix + '.cpu.trace'; - var heapPrefix = prefix + '.heap'; - var nonHeapPrefix = prefix + '.nonheap'; + var heapPrefix = prefix + '.heap.total'; + var nonHeapPrefix = prefix + '.nonheap.total'; var finalizePrefix = prefix + '.pending-finalization-count'; var gcPrefix = prefix + '.gc'; @@ -34,7 +34,7 @@ $(document).ready(function() { var gcCountMetrics = [{metric:'PS MarkSweep.count', alias:'PS MarkSweep'},{metric:'PS Scavenge.count', alias:'PS Scavenge'}]; var gcTimeMetrics = [{metric:'PS MarkSweep.time', alias:'PS MarkSweep'},{metric:'PS Scavenge.time', alias:'PS Scavenge'}]; var gcRuntimeMetrics = [{metric:'PS MarkSweep.runtime', alias:'PS MarkSweep'},{metric:'PS Scavenge.runtime', alias:'PS Scavenge'}]; - + $("#toc ul").append('
  • Flame Graph
  • '); $('#toc').affix({ offset: { @@ -46,13 +46,13 @@ $(document).ready(function() { var nonHeapGet = $.get('/data/' + nonHeapPrefix); var finalizeGet = $.get('/data/' + finalizePrefix); var gcGet = $.get('/data/' + gcPrefix); - + $.when(heapGet, nonHeapGet, finalizeGet, gcGet).done(function() { var heapResults = heapGet['responseJSON']; var nonHeapResults = nonHeapGet['responseJSON']; var finalizeResults = finalizeGet['responseJSON']; var gcResults = gcGet['responseJSON']; - + ViewUtil.renderGraph(heapResults, 'Heap Usage', '#heap', memoryMetrics); ViewUtil.renderGraph(nonHeapResults, 'Non-Heap Usage', '#nonheap', memoryMetrics); ViewUtil.renderGraph(finalizeResults, 'Objects Pending Finalization', '#finalize', finalizeMetrics);