'How to put uncaught exceptions in json logstash encoder in Spring / IntelliJ?

I have troubles with having uncaught exceptions in the JSON logs. This is my logback-spring:

<!-- logback-spring.xml -->
<configuration>
  <springProfile name="default">
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
  </springProfile>

  <springProfile name="prod">
    <appender name="jsonConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">
      <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
    </appender>
    <root level="INFO">
      <appender-ref ref="jsonConsoleAppender"/>
    </root>
  </springProfile>
</configuration>

Let's have just null pointer exception in the controller:

@GetMapping("/user/userinfo")
public ResponseEntity<UserInfo> getUserInfo() {
          throw new NullPointerException();
}

However, when logging to console I can see the uncaught exceptions but not in the JSON logger. JSON logger completely ignores this and then I cannot see it in Kibana.

EDIT: This seems to be problem only of IntelliJ! When running the jar file locally, the null pointer exception is correctly written to the log.



Solution 1:[1]

It's bad practice to configure log-levels in logback-spring.xml. Instead, I would recommend to configure log-levels in Spring boot properties (e.g. application.yaml or using environment vars)

The following logback-spring.xml allows you to switch between the default console appender and json:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>

    <appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
    </appender>

    <root>
        <springProfile name="jsonlogs">
            <appender-ref ref="JSON"/>
        </springProfile>
        <springProfile name="!jsonlogs">
            <appender-ref ref="CONSOLE"/>
        </springProfile>
    </root>
</configuration>

You can configure log-levels in application.yaml:

logging:
  level:
    root: info

To switch between text and json, simply activate the 'jsonlogs' profile. If you're using docker you can even add this to your Dockerfile using SPRING_PROFILES_INCLUDE=jsonlogs. That way your docker containers will always log in JSON, while IntelliJ will use text format.

If you really want to log JSON output using the IntelliJ console, please be aware that IntelliJ will fold console lines with specific phrases (e.g. "at org.apache.catalina").intellij console preferences

Since the stacktrace in your JSON output is encoded, the newline characters are replaced by \n. As a result, IntelliJ folds that entire line. If you look really closely, you'll see the 'plus' icon in the console:

folded console line.

If you expand that line, you'll see the error.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1