package info.freelibrary.djatoka.util;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nu.xom.Attribute;
import nu.xom.Document;
import nu.xom.Element;
import nu.xom.Serializer;
public class HealthServlet extends HttpServlet {
private static final long serialVersionUID = -1456866062313365312L;
private static final Logger LOGGER = LoggerFactory.getLogger(HealthServlet.class);
@Override
protected void doGet(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletException,
IOException {
boolean detailedOutput = aRequest.getParameter("detailed") != null;
ServletOutputStream out = aResponse.getOutputStream();
Element root = new Element("response");
Document response = new Document(root);
Element health = new Element("health");
Serializer serializer = new Serializer(out);
Runtime runtime = Runtime.getRuntime();
long freeMemory = runtime.freeMemory();
long totalMemory = runtime.totalMemory();
long usedMemory = totalMemory - freeMemory;
double percentage = (double) usedMemory / totalMemory;
String memUsage = String.format("%.2g", percentage);
int memory;
serializer.setIndent(2);
root.appendChild(health);
memory = (int) (Double.parseDouble(memUsage) * 100);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Memory usage at {}%", memory);
}
// These numbers are just a guess... need some real world tests
// also, add other things like deadlocked threads, etc?
if (memory < 85) {
health.appendChild("ok");
} else {
if (LOGGER.isWarnEnabled()) {
LOGGER.warn("Memory usage at {}%", memory);
}
if (memory > 95) {
health.appendChild("dying");
} else {
health.appendChild("sick");
}
}
if (detailedOutput) {
root.appendChild(getMemoryStats(memory, freeMemory, totalMemory));
root.appendChild(getProcessorStats());
root.appendChild(getThreadStats());
}
serializer.write(response);
out.close();
}
private Element getThreadStats() {
Element threads = new Element("threads");
ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
int threadCount = mxBean.getThreadCount();
long[] deadlocked = mxBean.findDeadlockedThreads();
long startedCount = mxBean.getTotalStartedThreadCount();
int deadCount = deadlocked != null ? deadlocked.length : 0;
int peakCount = mxBean.getPeakThreadCount();
long totalCount = mxBean.getTotalStartedThreadCount();
Element threadCountElem = new Element("threadCount");
Element deadlockedCountElem = new Element("deadlockedCount");
Element peakCountElem = new Element("peakCount");
Element totalCountElem = new Element("totalCount");
Element startedCountElem = new Element("totalStartedCount");
threadCountElem.appendChild(String.valueOf(threadCount));
deadlockedCountElem.appendChild(String.valueOf(deadCount));
peakCountElem.appendChild(String.valueOf(peakCount));
totalCountElem.appendChild(String.valueOf(totalCount));
startedCountElem.appendChild(String.valueOf(startedCount));
threads.appendChild(threadCountElem);
threads.appendChild(deadlockedCountElem);
threads.appendChild(peakCountElem);
threads.appendChild(totalCountElem);
threads.appendChild(startedCountElem);
return threads;
}
private Element getProcessorStats() {
Runtime runtime = Runtime.getRuntime();
String processors = Integer.toString(runtime.availableProcessors());
Element processorsElem = new Element("processors");
processorsElem.appendChild(processors);
return processorsElem;
}
private Element getMemoryStats(int aMemPct, long aFreeMem, long aTotalMem) {
long maxMemory = Runtime.getRuntime().totalMemory();
Element freeMemElem = new Element("freeMem");
Element totalMemElem = new Element("totalMem");
Element maxMemElem = new Element("maxMem");
Element memoryElem = new Element("memory");
Attribute memPctAtt = new Attribute("pctUsed", String.valueOf(aMemPct));
int mb = 1024 * 1024;
String freeMB = Long.toString(aFreeMem / mb);
String totalMB = Long.toString(aTotalMem / mb);
String maxMB = Long.toString(maxMemory / mb);
freeMemElem.appendChild(Long.toString(aFreeMem));
freeMemElem.addAttribute(new Attribute("mb", freeMB));
totalMemElem.appendChild(Long.toString(aTotalMem));
totalMemElem.addAttribute(new Attribute("mb", totalMB));
maxMemElem.appendChild(Long.toString(maxMemory));
maxMemElem.addAttribute(new Attribute("mb", maxMB));
memoryElem.appendChild(freeMemElem);
memoryElem.appendChild(totalMemElem);
memoryElem.appendChild(maxMemElem);
memoryElem.addAttribute(memPctAtt);
return memoryElem;
}
}