. . .

Logging and Debugging


Logging

Logging framework

The default logging frameworks used in ApiOmat services are SLF4J and Logback. More information about these frameworks can be found on the SLF4J site and the Logback site .
You can define an SLF4J logger for your class by using org.slf4j.LoggerFactory to get an implementation of the abstract org.slf4j.Logger :

MyClass.java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...
public MyClass {
private static final Logger LOGGER = LoggerFactory.getLogger( MyClass.class );
}

The org.slf4j.Logger implementation is provided by the Logback framework. You can then use the logger to print a log message at a specific logging level (e.g. DEBUG):

MyClass.java
final String messageToPrint = "msg";
LOGGER.debug( "My message {}", msg );

We recommend using the logger formatter (curly brackets) as shown above, as it checks the log level before doing any String operations and handles String concatenation more efficiently, making it more efficient in terms of time and CPU usage.
To check the enabled log level when not using the formatter, do this (e.g. checking if DEBUG is enabled):

if( LOGGER.isDebugEnabled( ) ) {
LOGGER.debug( "My logged message." );
}

Note that the messages outputted by your application depends on the level they were logged at and the level that has been set for your application: When you set a specific log level for your application, all messages of that level or higher are logged, and all messages of a lower level are not.
For example, setting your application to the INFO level will result in all messages of the INFO, WARN and ERROR levels being logged.

The following levels are available (from the Logback architecture manual ):

images/download/attachments/71320501/Screen-Shot-2020-04-07-at-14.10.24.png

Unlike native modules, services do not send their logs to the Dashboard log console. See Service Limitations .

Configuration

The default Logback configuration file is src/main/resources/logback.xml.

You can use the property logging.config to set an external logging configuration file location, e.g.: logging.config=file:/my/path/resources/logback.xml. See the common service configurations page for more details.

In this configuration, you can define specific log appenders and configure the logging level and used appender of your loggers. To dive deeper into Logback architecture and configuration, have a look at this guide to Logback.

Graylog

You may want to use Graylog to manage the logs of all of your applications from a single UI. To install and set up Graylog, refer to our Graylog installation guide .
Graylog support is added to your application via the GELF Logback dependency:

pom.xml
<dependency>
<groupId>de.siegmar</groupId>
<artifactId>logback-gelf</artifactId>
</dependency>

And can be enabled by configuring the GELF appender in your logback.xml, which is commented out by default (make sure that graylogHost and graylogPort correspond to your setup!):

logback.xml
<appender name="GELF" class="de.siegmar.logbackgelf.GelfUdpAppender">
<graylogHost>localhost</graylogHost>
<graylogPort>12201</graylogPort>
<layout class="de.siegmar.logbackgelf.GelfLayout">
<includeRawMessage>false</includeRawMessage>
<includeMarker>true</includeMarker>
<includeMdcData>true</includeMdcData>
<includeCallerData>true</includeCallerData>
<includeRootCauseData>true</includeRootCauseData>
<includeLevelName>true</includeLevelName>
 
<shortPatternLayout class="ch.qos.logback.classic.PatternLayout">
<pattern>%m%nopex</pattern>
</shortPatternLayout>
 
<fullPatternLayout class="ch.qos.logback.classic.PatternLayout">
<pattern>%m</pattern>
</fullPatternLayout>
 
<staticField>service_name:${serviceName}</staticField>
<staticField>service_version:${serviceVersion}</staticField>
<staticField>os_arch:${os.arch}</staticField>
<staticField>os_name:${os.name}</staticField>
<staticField>os_version:${os.version}</staticField>
</layout>
</appender>

Next, add the GELF appender to e.g. the root logger (in this example, the root logger is set to "DEBUG"):

logback.xml
<root level="DEBUG">
<appender-ref ref="GELF" />
<appender-ref ref="CONSOLE" />
</root>

Zipkin

Zipkin provides features and a centralised dashboard for service to service tracing. To install and set up Zipkin, please refer to our Zipkin Installation documentation .
Service to service tracing is enabled via the Spring Cloud starter Zipkin dependency:

pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>

Zipkin is disabled by default, to enable it remove the spring.zipkin.enabled property, or set it to true, and set the spring.zipkin.url property to the available Zipkin server (make sure to add http/https to the URL!):

application.yml
spring:
zipkin:
enabled: false
# baseUrl: http://localhost:9411

The % rate of traces sent to the Zipkin server is configured through the spring.sleuth.sampler.probability property, whose value can be set from 0 (0% of all traces will be sent) to 1.0 (100%). The default value is 0.1 (10%). Sleuth is disabled by default, to enable it remove the spring.sleuth.enabled property or set it to true, as for Zipkin, and set spring.sleuth.sampler.probability to the desired percentage:

application.yml
spring:
sleuth:
enabled: false
# sampler:
# probability: 0.1

Be aware that service to service tracing with Zipkin is only possible when both services are communicating with each other and have Zipkin enabled.

In some cases, logs may not be enough to reveal the source of a problem. When that happens, you will have to debug your application logic.

Debugging

We do not provide an out-of-the-box solution for debugging purposes, but rely on Java and Spring Boot. As a developer, you have two options for debugging your service logic:

Debug with a local instance

You can setup a service locally and debug it in some simple steps:

  1. Download your service project on your local machine.

  2. Import the project into your preferred IDE.

  3. Place relevant debugging breakpoint(s).

  4. Run the application there in debug mode:

    1. By using the Spring Tools suite.

    2. By starting your Spring Boot application from your IDE via Maven (see documentation on the Spring Boot run MOJO ):

      mvn spring-boot:run

Remote debugging

Make sure that your service project sources are up to date locally (that they match the remote instance).

You may start your application with remote debugging enabled and connect from your IDE to the remote debugging port:

  1. Start your service using the Dashboard and the Executor service with the following JVM arguments to enable remote debugging (e.g. with 5005 as the port to use):

    -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005

    Make sure that the configured remote server where your service will get deployed is accessible from your local developer machine and that the configured port is available.
    You can also start the service for remote debugging locally using the Spring Boot run MOJO:

    mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"
  2. Download your service project on your local machine.

  3. Import the project into your preferred IDE.

  4. Place relevant debugging breakpoint(s).

  5. Configure remote debugging in your IDE:

    1. Eclipse:

      1. Click RunDebug Configurations and double click on Remote Java Application.

      2. Configure with the specific application host and port:

        images/download/attachments/71320501/Screen-Shot-2020-04-07-at-16.49.35.png

    2. Intellij:

      1. Click RunEdit Configurations..., then click the + button in the upper left corner and select Remote from the dropdown menu.

      2. Configure with the specific application host and port:

        images/www.baeldung.com/wp-content/uploads/2019/11/run_configuration.png

Monitor your application with Spring Boot Admin

Spring Boot Admin is a community driven open source tool that provides a dashboard to monitor your Spring Boot application by using the actuator endpoints. For more information, you can refer to its documentation .

Create a Spring Boot Admin server application

The first step is to create a simple Spring Boot Admin server project. We recommend using Spring Initializr to create and download a Spring Boot project with the dependency Spring Boot Admin (Server) that you can simply import into your IDE.
You can also add the dependency manually (make sure the version matches the Spring Boot version you are using, as errors may occur if they are not identical!):

pom.xml
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.0.5</version>
</dependency>

Next, do the following:

  1. Add the @EnableAdminServer annotation to the application's main class:

    MyAdminServerApplication.java
    @SpringBootApplication
    @EnableAdminServer
    public class MyAdminServerApplication 
    {
    public static void main(String[] args) 
    {
    SpringApplication.run(MyAdminServerApplication.class, args);
    }
    }
  2. Configure the application server port and the Spring Boot Admin server URL in the application.properties file:

    application.properties
    server.port = 6699
    spring.boot.admin.server.url=http://localhost:8889

And that's all, now you can start the server and access it on e.g. http://localhost:6699:

images/download/attachments/71320501/Screen-Shot-2020-03-24-at-09.02.07.png

Configure your client application

To connect your Spring Boot application and show statistics about it, the following steps have to be followed:

  1. In your pom.xml, add the Spring Boot Admin client dependency (make sure the version matches the Spring Boot version you are using, as errors may occur if they are not identical!):

    pom.xml
    <dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
    <version>2.0.5</version>
    </dependency>
  2. Expose all actuator endpoints, so that all metrics will be shown in the Spring Boot Admin dashboard:

    application.yml
    management:
    endpoints:
    web:
    exposure:
    include: '*'

    You should only expose all endpoints like this for testing purposes, NEVER in production!
    In production, carefully choose which endpoints to expose. You can also use Spring Security to add security to all actuator endpoints - see here for information on how to connect Spring Boot Admin in that case).

  3. Add the Spring Boot Admin server URL to your properties:

    application.yml
    spring:
    boot:
    admin:
    client:
    url: http://localhost:6699
  4. Start your service, you can now monitor it from the Spring Boot Admin dashboard (e.g. http://localhost:6699):

    images/download/attachments/71320501/Screen-Shot-2020-03-24-at-12.19.02.png