1

I'm using logback 1.1.3 over slf4j-api 1.7.7.

I'm reading the following documentation here.

The code (which I can't modify) that I'm trying to restrict the logging logs and throws exceptions in the following way.

try {.. }
catch( Exception e ) {
  log.error( "Houston we have a problem", e );
  throw new TestException( "Houston we have a problem", e );
}

The log format I'm using is the following.

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <layout class="ch.qos.logback.classic.PatternLayout">
        <Pattern>
            %d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg%n
        </Pattern>
    </layout>
</appender>

And I want some loggers to restrict the display of their stacktrace to just 2 lines so I thought I could simply modify that to the following format as stipulated in the documentation.

<appender name="STDOUT_COMPACT" class="ch.qos.logback.core.ConsoleAppender">
    <layout class="ch.qos.logback.classic.PatternLayout">
        <Pattern>
            %ex{2} %d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg%n
        </Pattern>
    </layout>
</appender>

I was expecting to get something like the following.

mainPackage.foo.bar.TestException: Houston we have a problem
  at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)

But instead, I was getting the following.

mainPackage.foo.bar.TestException: Houston we have a problem
  at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
mainPackage.foo.bar.TestException: Houston we have a problem
  at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
  at mainPackage.foo.bar.TestThrower.fire1(TestThrower.java:12)
  at mainPackage.foo.bar.TestThrower.fire2(TestThrower.java:44)
  at mainPackage.foo.bar.TestThrower.fire3(TestThrower.java:122)
  at mainPackage.foo.bar.TestThrower.fire4(TestThrower.java:322)
  at mainPackage.foo.bar.TestThrower.fire5(TestThrower.java:72)
  ..

The log was simply repeated instead of being truncated to just 2 lines. What am I doing wrong? How exactly do I use the ex{n} format appropriately? I don't prefer to write my custom logger for this.

supertonsky
  • 2,563
  • 6
  • 38
  • 68

1 Answers1

4

You have to include %nopex in your pattern. Otherwise Logback will tack on the stacktrace even though you've already printed the stacktrace. Your pattern should look like this:

%ex{2} %d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg%nopex%n

It's more common to include the exceptions on the end like this:

%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg %ex{2}%nopex%n
  • 2
    This contradicts the documentation in http://logback.qos.ch/manual/layouts.html#ex which states that the stacktrace is only appended if no `%ex` token at all is present. Yes, I also tried it out. – Michael Piefel Jan 13 '21 at 13:38
  • @MichaelPiefel I've looked at that link Michael, and it doesn't specify that you need %ex: "If you do not specify %throwable or another throwable-related conversion word in the conversion pattern, PatternLayout will automatically add it as the last conversion word, on account of the importance of stack trace information. The $nopex conversion word can be substituted for %throwable, if you do not wish stack trace information to be displayed. See also the %nopex conversion word." – Raid Jan 17 '22 at 23:12
  • @MichaelPiefel It states that if you don't specify %throwable or the like, it will automatically add it as the last conversion word. But the $nopex conversion word can be substituted for that if **you do not wish stack information to be display** .. May I ask where the contradiction is? – Raid Jan 17 '22 at 23:14
  • @Raid: The pattern in _this answer_ contains `%ex`. – Michael Piefel Jan 18 '22 at 07:45
  • @MichaelPiefel I know. He's putting it in a specific place instead of the end where it automatically appends. So he's choosing his placement where he wants the exception trace to be. Make sense? :) – Raid Jan 18 '22 at 16:25