package play.modules.logger;
import play.PlayPlugin;
import play.exceptions.ActionNotFoundException;
import play.exceptions.JavaExecutionException;
import play.exceptions.UnexpectedException;
import javax.persistence.PersistenceException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import static java.lang.Integer.compare;
import static java.lang.String.format;
import static java.util.Collections.sort;
import static org.apache.commons.lang.StringUtils.split;
public class ExceptionsMonitoringPlugin extends PlayPlugin {
private static final ConcurrentHashMap<String, AtomicInteger> exceptions = new ConcurrentHashMap<>();
public static void register(String source, Throwable e) {
if (e instanceof ActionNotFoundException) return;
if (e instanceof UnexpectedException ||
e instanceof InvocationTargetException ||
e instanceof JavaExecutionException ||
e instanceof PersistenceException) {
if (e.getCause() != null) e = e.getCause();
}
String key = "[" + source + "] " + key(e);
AtomicInteger value = exceptions.get(key);
if (value == null) exceptions.put(key, value = new AtomicInteger());
value.incrementAndGet();
}
static String key(Throwable e) {
return split(e.toString(), '\n')[0]
.replaceAll("@[0-9a-f]{4,}", "@*")
.replaceAll("\\{\\{.*\\}\\}", "*")
.replaceAll("[\\d*]{3,}", "*");
}
@Override public String getStatus() {
StringWriter sw = new StringWriter();
try (PrintWriter out = new PrintWriter(sw)) {
out.println("Exception statistics:");
out.println("~~~~~~~~~~~~~~~~~~~~~~");
ArrayList<Map.Entry<String, AtomicInteger>> sorted = new ArrayList<>(exceptions.entrySet());
sort(sorted, (o1, o2) -> compare(o2.getValue().get(), o1.getValue().get()));
for (Map.Entry<String, AtomicInteger> entry : sorted) {
out.println(format("%4d : %s", entry.getValue().get(), entry.getKey()));
}
}
return sw.toString();
}
public static Map<String, AtomicInteger> getExceptions() {
return exceptions;
}
public static void resetExceptions() {
exceptions.clear();
}
}