0
votes

I'm configuring logs for Logback.

XML configuration looks like:

<configuration>
   <appender name="console" class="...">
     <encoder>
       <pattern>Message:%nText: %m</pattern>
     </encoder>
  </appender>
  ...
</configuration>

The idea is that log record should be multiline:

Message:
Text: [Message text here]

But when I run app, I get an exception:

ERROR in ch.qos.logback.core.pattern.parser.Compiler@8dbdac1 - There is no conversion class registered for conversion word [nText]

So, problem is that '%n' and 'Text' strings are merged to one string.

As a workaround, I can write them separately with space:

Message:%n Text: %m

But in this case, the space appears in logs before 'Text'

Message:
 Text:

Is there some solution (escape character for empty string or similar)?

Thank you.

2

2 Answers

2
votes

From the logback manual Ch. 6: Layouts:

In most cases literals naturally contain spaces or other delimiting characters so that they are not confused with conversion words. For example, the pattern "%level [%thread] - %message%n" contains the string literals " [" and "] - ". However, if a character which can be part of a java identifier immediately follows a conversion word, logback's pattern parser will be fooled into thinking that the literal is part of the conversion word. For example, the pattern "%date%nHello" will be interpreted as two conversion words %date and %nHello and since %nHello is not a known conversion word, logback will output %PARSER_ERROR[nHello] for %nHello. If you wish the string literal "Hello" to immediately separate %n and Hello, pass an empty argument list to %n. For example, "%date%n{}Hello" will be interpreted as %date followed by %n followed by the literal "Hello".

So, give Message:%n{}Text: %m a try.

1
votes

Logback's PatternLayout contains defaultConverterMap which maps conversion words (%n, %ex etc) to implementations of ch.qos.logback.core.pattern.Converter.

As you correctly spotted %nText is not a conversion word and there is no way to 'escape' the fact that %n and T are contiguous.

However, you could provide your own implementation of ch.qos.logback.core.pattern.Converter and associate it with a custom conversion word as follows ...

  1. Add this to logback.xml

    <conversionRule conversionWord="nt" converterClass="some.package.CustomLineSeparatorConverter" />
    
  2. Implement some.package.CustomLineSeparatorConverter as follows:

    import ch.qos.logback.classic.pattern.ClassicConverter;
    import ch.qos.logback.classic.spi.ILoggingEvent;
    import ch.qos.logback.core.CoreConstants;
    
    public class CustomLineSeparatorConverter extends ClassicConverter {
    
        public String convert(ILoggingEvent event) {
            return CoreConstants.LINE_SEPARATOR + "Text:";
        }
    }
    
  3. Update your encoder pattern to use the conversion word nt:

    <encoder>
        <pattern>Message:%nt %m</pattern>
    </encoder>
    

With these changes in place your custom converter will be engaged and the output will be:

Message:
Text: some log output