package com.twitter.common.logging;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import com.google.common.base.Throwables;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
/**
* Log formatter to match the format generated by glog:
*
* I0218 17:36:47.460234 (source) (message)
*
* @author William Farner
*/
public class LogFormatter extends Formatter {
private static final DateTimeFormatter DATE_TIME_FORMATTER =
DateTimeFormat.forPattern("MMdd HH:mm:ss.SSS").withZone(DateTimeZone.UTC);
/**
* Build a level 'label' by taking the first character of the level name and making uppercase.
*/
private static final LoadingCache<Level, String> LEVEL_LABELS = CacheBuilder.newBuilder().build(
new CacheLoader<Level, String>() {
public String load(Level level) {
return String.valueOf(level.getName().charAt(0)).toUpperCase();
}
}
);
private static final int BASE_MESSAGE_LENGTH =
1 // Level char.
+ 4 // Month + day
+ 1 // space
+ 12 // Timestamp
+ 1 // space
+ 6 // THREAD
+ 4 // Room for thread ID.
+ 1; // space
@Override
public String format(final LogRecord record) {
int messageLength = BASE_MESSAGE_LENGTH
+ 2 // Colon and space
+ record.getMessage().length();
if (record.getSourceClassName() != null) {
messageLength += record.getSourceClassName().length();
if (record.getSourceMethodName() != null) {
messageLength += 1; // Period between class and method.
messageLength += record.getSourceMethodName().length();
}
}
StringBuilder sb = new StringBuilder(messageLength)
.append(LEVEL_LABELS.getUnchecked(record.getLevel()))
.append(DATE_TIME_FORMATTER.print(record.getMillis()))
.append(" THREAD")
.append(record.getThreadID());
if (record.getSourceClassName() != null) {
sb.append(' ').append(record.getSourceClassName());
if (record.getSourceMethodName() != null) {
sb.append('.').append(record.getSourceMethodName());
}
}
sb.append(": ").append(formatMessage(record));
if (record.getThrown() != null) {
sb.append('\n').append(Throwables.getStackTraceAsString(record.getThrown()));
}
return sb.append('\n').toString();
}
private static String zeroPad(int value, int width) {
return StringUtils.leftPad(String.valueOf(value), width, '0');
}
}