问题
I know how to output classname and methodname with log4j, both fields can be aligned and padded separately, e.g. this pattern:
[%d{ISO8601}] %-5p %-10C{1}:%-10M %m%n
produces something like:
[2012-09-20 08:25:12,111] WARN Class :method Logtext1 which should align
[2012-09-20 08:25:12,111] WARN ClassTwo :methodName Logtext2 which should align
This will align the logged text (in most cases), but the classname and methodname are ugly spaced.
So what I would like to output is something like:
[2012-09-20 08:25:12,111] WARN Class:method Logtext1 which should align
[2012-09-20 08:25:12,111] WARN ClassTwo:methodName Logtext2 which should align
Is this possible using only configuration?
Can you suggest another way of outputting methodname and classname, keeping the logged message text aligned?
回答1:
It seems like this is not possible using only configuration. The next simpler solution seems to be a custom PatternLayout, which then can be used in the log4j.ini with the character 'b':
log4j.appender.filelog.layout= your.full.namespace.BPatternLayout log4j.appender.filelog.layout.ConversionPattern=[%d{ISO8601}] %-5p %-30b %m%n
Hope it helps someone else, too.
BPatternLayout.java:
import org.apache.log4j.PatternLayout;
import org.apache.log4j.helpers.PatternParser;
public class BPatternLayout extends PatternLayout
{
@Override
protected PatternParser createPatternParser(String pattern)
{
return new BPatternParser(pattern);
}
}
BPatternParser.java:
import org.apache.log4j.helpers.FormattingInfo;
import org.apache.log4j.helpers.PatternConverter;
import org.apache.log4j.helpers.PatternParser;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;
public class BPatternParser extends PatternParser
{
public BPatternParser(String pattern)
{
super(pattern);
}
@Override
protected void finalizeConverter(char c)
{
switch (c)
{
case 'b':
currentLiteral.setLength(0);
addConverter(new BPatternConverter(formattingInfo));
break;
default:
super.finalizeConverter(c);
}
}
private class BPatternConverter extends PatternConverter
{
BPatternConverter(FormattingInfo formattingInfo)
{
super(formattingInfo);
}
@Override
protected String convert(LoggingEvent evt)
{
LocationInfo locationInfo = evt.getLocationInformation();
return getPartialClassName(locationInfo, 1) + ":" + locationInfo.getMethodName();
}
/**
* Code from org.apache.log4j.helpers.PatternParser.NamedPatternConverter
*/
private String getPartialClassName(LocationInfo loc, int precision)
{
String n = loc.getClassName();
if (precision <= 0) {
return n;
}
int len = n.length();
// We substract 1 from 'len' when assigning to 'end' to avoid out of
// bounds exception in return r.substring(end+1, len). This can happen if
// precision is 1 and the category name ends with a dot.
int end = len - 1;
for (int i = precision; i > 0; i--)
{
end = n.lastIndexOf('.', end - 1);
if (end == -1)
return n;
}
return n.substring(end + 1, len);
}
}
}
来源:https://stackoverflow.com/questions/12507220/is-it-possible-to-use-format-modifiers-for-two-conversion-characters-combined