MicroLogger.java
package org.microspace.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
/**
* Provide varargs functionality for org.apache.log4j.Logger,
* so that lightweight logging is possible and toString
* is called only when the object is logged.
*
* @author Gaspar Sinai at microspace.org
* @version 2011-01-29
*/
public class MicroLogger {
private Logger log;
private static UniqueIdSeed seed = new UniqueIdSeed();
public MicroLogger (Logger log) {
this.log = log;
if(seed == null){
seed = new UniqueIdSeed();
}
// This lets you specify %X{PID}
MDC.put("PID", "" + seed.getProcessId());
}
public MicroLogger (Class<?> clazz) {
this(LoggerFactory.getLogger(clazz));
}
public Logger getLogger () {
return log;
}
public void trace(String msg, Object... args) {
if (log == null || msg == null || !log.isTraceEnabled()) {
return;
}
log.trace(parse(msg, args));
}
public void debug(String msg, Object... args) {
if (log == null || msg == null || !log.isDebugEnabled()) {
return;
}
log.debug(parse(msg, args));
}
public void info(String msg, Object... args) {
if (log == null || msg == null || !log.isInfoEnabled()) {
return;
}
log.info(parse(msg, args));
}
public void warn(String msg, Throwable e, Object... args) {
if (log == null || msg == null || !log.isWarnEnabled()) {
return;
}
if (e != null) {
log.warn(parse(msg, args), e);
} else {
log.warn(parse(msg, args));
}
}
public void error(String msg, Throwable e, Object... args) {
if (log == null || msg == null || !log.isErrorEnabled()) {
return;
}
if (e != null) {
log.error(parse(msg, args), e);
} else {
log.error(parse(msg, args));
}
}
private enum State { START, DOLLAR, NUMBER }
/**
* Parse string to print.
* <pre>
* parse ("Second arg=$1 first is $0", 1, 2);
* </pre>
* @param msg is like $0 $2 or $* $* escaped $$
* @param args is the matching objects to print.
* @return the parsed String.
*/
public static String parse(String msg, Object... args) {
if (msg == null) {
return "";
}
StringBuilder sb = new StringBuilder();
int index = 0;
int autoIndex = 0;
State state = State.START;
for (int i = 0; i < msg.length(); i++) {
char c = msg.charAt (i);
switch (state) {
case START:
if (c == '$') {
state = State.DOLLAR;
index = 0;
} else {
sb.append (c);
}
break;
case DOLLAR:
if (c == '$') {
sb.append (c);
state = State.START;
break;
}
if (c == '*') {
index = autoIndex++;
state = State.START;
sb.append (printArgs (index, args));
break;
}
/*FALLTHROUGH*/
case NUMBER:
if (c >= '0' && c <= '9') {
index = index * 10 + (c - '0');
state = State.NUMBER;
}
if (c < '0' || c > '9' || i+1 == msg.length()) {
if (state == State.NUMBER) {
state = State.START;
sb.append (printArgs (index, args));
if (c >= '0' && c <= '9') break;
}
if (c == '$') {
state = State.DOLLAR;
index = 0;
} else {
sb.append (c);
state = State.START;
}
}
}
}
return sb.toString();
}
private static String printArgs (int index, Object... args) {
if (args == null) return "arg-error";
if (args.length <= index) return "array-error";
if (args[index] == null) return "null";
StringBuffer sb = new StringBuffer();
if (args[index].getClass().isArray()) {
Object[] ao = (Object[]) args[index];
sb.append ('{');
for (Object o : ao) {
sb.append (" [" + o + "] ");
}
sb.append ('}');
} else {
sb.append ("" + args[index]);
}
return sb.toString();
}
}