/* vim: set ts=2 et sw=2 cindent fo=qroca: */ package com.globant.katari.core.ping; import java.lang.management.ManagementFactory; import java.lang.management.MemoryPoolMXBean; import java.lang.management.MemoryType; import java.lang.management.MemoryUsage; // import org.apache.commons.io.FileUtils; /** Gives information about the current memory usage. */ public class PingMemory implements PingService { /** Gives information about the current memory usage. * * @return the status of the memory. */ public PingResult ping() { long heapSize = Runtime.getRuntime().totalMemory(); long max = Runtime.getRuntime().maxMemory(); StringBuilder message = new StringBuilder(); message.append("Heap Size = ").append(formatSize(heapSize)).append("\n"); message.append("Max Heap Size = ").append(formatSize(max)).append("\n"); for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) { String name = pool.getName(); MemoryType type = pool.getType(); MemoryUsage usage = pool.getUsage(); MemoryUsage peak = pool.getPeakUsage(); message.append("Heap named '").append(name); message.append("' (").append(type.toString()).append(") "); message.append("uses ").append(formatSize(usage.getUsed())); message.append(" of ").append(formatSize(usage.getMax())); message.append(". The max memory used so far is "); message.append(formatSize(peak.getUsed())).append(".\n"); } return new PingResult(true, message.toString()); } /** The number of bytes in a kilobyte. */ private static final int KB = 1024; /** The number of bytes in a megabyte. */ private static final int MB = KB * KB; /** The number of bytes in a gigabyte. */ private static final int GB = KB * MB; /** The divisor for the fraction of the memory size. */ private static final int FRACTION_DIVISOR = 100; /** Converts a filesize to a human readable format. * * Strings are formatted as 1024: 1KB, 1023: 1,023 B, and so on. * * @param size Size to be formatted. * * @return The formatted filesize, never null. */ private String formatSize(final long size) { long number, reminder; String result; if (size < KB) { result = insertSeparator(size) + " B"; } else if (size < MB) { number = size / KB; reminder = (size * FRACTION_DIVISOR / KB) % FRACTION_DIVISOR; result = String.format("%s.%02d KB", insertSeparator(number), reminder); } else if (size < GB) { number = size / MB; reminder = (size * FRACTION_DIVISOR / MB) % FRACTION_DIVISOR; result = String.format("%s.%02d MB", insertSeparator(number), reminder); } else { number = size / GB; reminder = (size * FRACTION_DIVISOR / GB) % FRACTION_DIVISOR; result = String.format("%s.%02d GB", insertSeparator(number), reminder); } // Display decimal points only if needed another alternative to this // approach is to check before calling str.Format, and have separate cases // depending on whether reminder == 0 or not. return result.replace(".00", ""); } /** The number of digits for the thousand separator. */ private static final int THOUSAND_DIGITS = 3; /** Converts a positive number to a string while inserting separators. * * @param number A positive number to add thousands separator for. * * @return The number with thousand separators as a String. */ private String insertSeparator(final long number) { StringBuilder result = new StringBuilder(); result.append(String.format("%d", number)); for (int i = result.length() - THOUSAND_DIGITS; i > 0; i -= THOUSAND_DIGITS) { result.insert(i, ","); } return result.toString(); } }