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?
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);
}
}
}