
org.rajivprab.sava.logging.LogDispatcher Maven / Gradle / Ivy
package org.rajivprab.sava.logging;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Log Interface
* Will handle logging, but will also send emails/texts/calls where needed
*
* Created by rprabhakar on 7/25/15.
*/
public class LogDispatcher {
// Trace: Only for the most gratuitous log of any and all activity
// Debug: Information that's generally not needed, except when debugging issues
// Info: Issues that dev-ops/UX teams might want to know. Eg, Anything that should produce 4xx http-response
// Notify: Same as Info, but also generate notifications. Example: All-is-well status checks
// Warn: Suspicious behavior that needs to be investigated. Eg: Tampered tokens. Stormpath timeouts.
// Error: Issues that have exposed errors in our code. Eg, Anything that produces 5xx response due to our fault
// Fatal: Show stopper issues that need to be fixed at 2am in the morning. Eg: Stormpath invalid-API-key errors
public enum Severity {
TRACE, DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL
}
public interface Dispatcher {
void dispatch(Severity severity, Object message, Throwable throwable);
}
public static synchronized void setDispatcher(Dispatcher override) {
dispatcher = override;
}
public static void setEmptyDispatcher() {
setDispatcher(new DummyDispatcher());
}
public static void report(Object header, Severity severity, Object message) {
report(header.getClass(), severity, message);
}
public static void report(Class header, Severity severity, Object message) {
report(header.getName(), severity, message);
}
public static void report(String header, Severity severity, Object message) {
report(header, severity, message, null);
}
public static void report(Object header, Severity severity, Throwable throwable) {
report(header.getClass(), severity, throwable.getMessage(), throwable);
}
public static void report(Class header, Severity severity, Throwable throwable) {
report(header.getName(), severity, throwable.getMessage(), throwable);
}
public static void report(Object header, Severity severity, Object message, Throwable throwable) {
report(header.getClass(), severity, message, throwable);
}
public static void report(Class header, Severity severity, Object message, Throwable throwable) {
report(header.getName(), severity, message, throwable);
}
public static void report(String header, Severity severity, Object message, Throwable throwable) {
Log log = LogFactory.getLog(header);
switch (severity) {
case TRACE:
log.trace(message, throwable);
break;
case DEBUG:
log.debug(message, throwable);
break;
case INFO:
case NOTIFY:
log.info(message, throwable);
break;
case WARN:
log.warn(message, throwable);
break;
case ERROR:
log.error(message, throwable);
break;
case FATAL:
log.fatal(message, throwable);
break;
default:
throw new IllegalStateException("Found unexpected severity: " + severity);
}
dispatcher.dispatch(severity, message, throwable);
}
// TODO static variable is not marked as volatile, and methods that read this are not synchronized either
// Done for performance reasons, but is not thread-safe, strictly speaking. Reasonable?
private static Dispatcher dispatcher = new WarningDispatcher();
private static class WarningDispatcher implements Dispatcher {
// Default behavior for Dispatcher: Do Nothing. Log a warning telling users to define their own implementation
private static final Log LOG = LogFactory.getLog(LogDispatcher.class);
public void dispatch(Severity severity, Object message, Throwable throwable) {
if (severity.compareTo(Severity.INFO) > 0) {
LOG.warn("Using default Dispatcher that ignores all calls. " +
"Recommend setting your own or calling LogDispatcher.setEmptyDispatcher()");
}
}
}
private static class DummyDispatcher implements Dispatcher {
@Override
public void dispatch(Severity severity, Object message, Throwable throwable) {}
}
}