Search code examples
log4jlog4j2

log4j set class and method summary length in pattern


Currently I have sth like:

%d{HH:mm:ss.SSS} | %-5.5p | %-15.15t | %-30.70C.%-5.20M:%-3.5L | %msg%n

but this makes full.class.Name.method:line of different lengths - is it possible to make calss.method:line of fixed length ?

I would like sth like

%-60.60CML (but this of course doesn't work)

I would like to make calss.method.line have the same length on all log lines. (so as the actual message started in the same place)

Is it possible ?

Other wors said, is it possible to format multiple conversion characters with one conversion specifier ? Looking at

https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html

Each conversion specifier starts with a percent sign (%) and is followed by optional format modifiers and a conversion character. The conversion character specifies the type of data

The pattern parser knows when it has reached the end of a conversion specifier when it reads a conversion character.

It's now written about multiple conversion characters, so maybe it's simply not possible ?


As @Remko Popma explained, what I want is not possible now:

No, each modifier applies to one conversion. But Log4j could add a new converter that means what you want. You can propose such a new converter on the mailing list or issue tracker.

I created issue: https://issues.apache.org/jira/browse/LOG4J2-2339


Solution

  • Based on help from @Remko-Popma

    https://issues.apache.org/jira/browse/LOG4J2-2339

    below is what worked for me:

    <property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} | %-5.5p | %-15.15t | %-70.70CML | %-10.70X | %msg%n</property>
    
    import org.apache.logging.log4j.core.LogEvent;
    import org.apache.logging.log4j.core.config.plugins.Plugin;
    import org.apache.logging.log4j.core.pattern.ConverterKeys;
    import org.apache.logging.log4j.core.pattern.NamePatternConverter;
    import org.apache.logging.log4j.core.pattern.PatternConverter;
    
    @Plugin(name = "ClassMethodLinePatternConverter", category = PatternConverter.CATEGORY)
    @ConverterKeys({"CML", "classmethodline"})
    public class ClassMethodLinePatternConverter extends NamePatternConverter {
    
        private static final String NA = "?";
    
        private ClassMethodLinePatternConverter(
            final String[] options) {
            super("Class Name", "class name", options);
        }
    
        public static ClassMethodLinePatternConverter newInstance(final String[] options) {
            return new ClassMethodLinePatternConverter(options);
        }
    
        /**
         * Format a logging event.
         *
         * @param event      event to format.
         * @param toAppendTo string buffer to which class name, method name and line will be appended.
         */
        @Override
        public void format(final LogEvent event, final StringBuilder toAppendTo) {
            final StackTraceElement element = event.getSource();
            if (element == null) {
                toAppendTo.append(NA);
            } else {
              toAppendTo.append(element.getClassName()).append(".").append(element.getMethodName()).append(":").append(element.getLineNumber());
            }
        }
    

    }