Logging configuration with JBoss EAP and Spring Boot

5 minute read | By Anthony Salemo

This post will cover some logging configuration that can be done with Spring Boot, packaged as a WAR file, deployed to a JBoss EAP instance on App Service Linux.

Overview

If deploying a Spring Boot application, packaged as a WAR, to a JBoss EAP instance - you may notice that Spring specific output may not show. By default, we’ll see stdout and stderr from JBoss.

We’ll cover some different methods below to configure logging to change this.

Log File locations

As with all “Blessed” Images, stdout and stderr is redirected to default_docker.log. This includes typically the Web Server logging (in this case, Jboss and Undertow) - plus, application logging.

If absolutely needed, logging directory locations can be changed for certain files. In the current JBoss Blessed Image, there are a few files that are created for JBoss, GC, and the application. Some of this is redirected to default_docker.log already - and should generally suffice, however, some other files live under /tmp/LogFiles. The files under /tmp/LogFiles are:

  • gc.log - Logs for Garbage Collection
  • audit.log
  • server.log - Logs for JBoss specific activity (the content here is redirected to default_docker.log)
  • Application/server.[host].log - Logs for JBoss specific activity and application stdout/err (the content here is redirected to default_docker.log)
  • http/RawLogs/site_access_log.[host].txt - HTTP access logs

This location is configured through a default JAVA_OPTS parameter on startup, provided a part of the Blessed Image, for example:

JAVA_OPTS:  -server -Xlog:gc*:file="/tmp/LogFiles/gc.log": ... -Djboss.server.log.dir=/tmp/LogFiles ... -XX:ErrorFile=/home/LogFiles/java_error_test-jboss_ln0sdlwk0000M2_%p.log ... -XX:HeapDumpPath=/home/LogFiles/java_memdump_test-jboss_ln0sdlwk0000M2.log  

You can override these locations by setting your own location for. For example, by changing the parameter of -Djboss.server.log.dir=/tmp/LogFiles to -Djboss.server.log.dir=/home/LogFiles/Custom - this will now create all of the above files under /home/LogFiles/Custom.

Note: Doing this could potentially more quickly fill up the persistent Storage quota. Or potentially impact performance since more I/O operations will be going through the mounted volume to the File Server

Spring Boot logging and JBoss

Enable logging - application.properties/application.yaml

This is one of the more simple ways. Update the application.properties or application.yaml file under src/main/resources in the application with the below:

(application.properties)

logging.level.root=info

(application.yaml)

logging:
    level:
        root: info

NOTE: If Log Level is not info, normal logging, such as println statements may not show. Additionally, you may see this message if this is logging.level.root is not set:

Handler java.util.logging.ConsoleHandler is not defined

Enable logging - JBoss CLI

You can use the JBoss CLI and custom startup scripts to override this. This is a combination of:

  1. (Optional): Add JAVA_OPTS as an App Setting with the value of -Djboss.server.log.dir=/home/LogFiles.
  2. Ideally, the updated logging will also be written to default_docker.log

Add a file named startup_script.sh under /home:

#!/usr/bin/env bash

echo "Entering startup_script.sh.."

$JBOSS_HOME/bin/jboss-cli.sh --connect --file=/home/site/deployments/tools/jboss-cli-commands.cli
  1. Add a file named jboss-cli-commands.cli under /home/site/deployments/tools
  2. In this file, add the below:
#!/usr/bin/env bash

# Replace com.jboss.azure with the main package name of the application
/subsystem=logging/logger=com.jboss.azure:add 
# Add a category for 'stdout', otherwise stdout from print statements or others from the application may not show
/subsystem=logging/logger=stdout:add
/subsystem=logging/logger=com.jboss.azure:write-attribute(name="level", value="INFO") 
/subsystem=logging/logger=com.jboss.azure:write-attribute(name="use-parent-handlers", value="true") 
/subsystem=logging/logger=stdout:write-attribute(name="level", value="INFO") 
/subsystem=logging/logger=stdout:write-attribute(name="use-parent-handlers", value="true") 

You should now start seeing Spring Boot logging in server.[machineName].log and default_docker.log:

2023-05-22T20:24:13.152474492Z 20:24:13,151 INFO  [stdout] (ServerService Thread Pool -- 82) 
2023-05-22T20:24:13.153479310Z 20:24:13,152 INFO  [stdout] (ServerService Thread Pool -- 82)   .   ____          _            __ _ _
2023-05-22T20:24:13.154400426Z 20:24:13,153 INFO  [stdout] (ServerService Thread Pool -- 82)  /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
2023-05-22T20:24:13.156788269Z 20:24:13,156 INFO  [stdout] (ServerService Thread Pool -- 82) ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
2023-05-22T20:24:13.157297978Z 20:24:13,156 INFO  [stdout] (ServerService Thread Pool -- 82)  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
2023-05-22T20:24:13.158924407Z 20:24:13,157 INFO  [stdout] (ServerService Thread Pool -- 82)   '  |____| .__|_| |_|_| |_\__, | / / / /
2023-05-22T20:24:13.159758122Z 20:24:13,158 INFO  [stdout] (ServerService Thread Pool -- 82)  =========|_|==============|___/=/_/_/_/
2023-05-22T20:24:13.160641038Z 20:24:13,160 INFO  [stdout] (ServerService Thread Pool -- 82)  :: Spring Boot ::                (v2.6.7)
2023-05-22T20:24:13.161472853Z 20:24:13,160 INFO  [stdout] (ServerService Thread Pool -- 82) 
2023-05-22T20:24:13.170895022Z 20:24:13,170 INFO  [com.jboss.azure.ServletInitializer] (ServerService Thread Pool -- 82) No active profile set, falling back to 1 default profile: "default"
2023-05-22T20:24:13.369726587Z 20:24:13,369 INFO  [com.jboss.azure.ServletInitializer] (ServerService Thread Pool -- 82) Started ServletInitializer in 0.27 seconds (JVM running for 110.683)

2023-05-22T20:24:57.671594299Z 20:24:57,670 INFO  [stdout] (default task-1) This is logged from:com.jboss.azure.Controllers.HomeController

For other ways on how to use the JBoss CLI and the logging subsystem, check out Redhat’s JBoss EAP documentation here:

Spring Boot Starter logger dependency conflict

If trying to use slf4j within code, you may see this:

Caused by: java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath

To resolve this, you need to exclude spring-boot-starter-logging which is apart of spring-boot-starter.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
    <exclusions>
      <exclusion>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-logging</artifactId>
    </exclusion>
  </exclusions>
</dependency>

NOTE: If you exclude spring-boot-starter-logging, you may notice that there will be no logs from your Spring Boot application - only logs from JBoss’s context. You can use the above methods for reenabling this functionality.