This document aims to give you an overview of how you can write events of your application with the standard logging frameworks and how the SAP Cloud SDK integrates with that. There are three parts to this document:
- How the SDK integrates with logging frameworks
- How to create log entries
- How to configure those entries
To better differentiate between different kinds of logging we will call the type of logs that are usually only relevant for developers to understand why the system behaves the way it did (for example during debugging) as Application Logging. Other types of logs might be kept due to legislative requirements (audit trails or audit logging) or be part of the terms and conditions (business logging). This document describes how to write and configure Applications Logs.
That means there are two components involved:
The SLF4J API
The API is used to get a logger instance and create log entries:Logger logger = LoggerFactory.getLogger(DummyClass.class);logger.debug("message");
A logging framework which provides the implementation of that API
The framework is then responsible for writing such messages according to a configuration. Which configuration options are available depends on the framework. Typically one can configure a log level (Error, Warn, Debug, etc.) and the format of messages.
The SDK itself only relies upon the SLF4J API, not on any specific logging framework. This is good practice because otherwise all consumers would be forced to use the same logging framework that the SDK comes with, rendering the SDK unusable for many use cases.
That means that you have to provide a logging framework in your application. Otherwise you will not see any log entries the SDK attempts to put out.
In case your project is based on one of the SDK archetypes you will already have Logback set up as the logging provider.
In order to provide a logging framework you have to add it to the dependency tree. Which artifacts are to be added exactly depends on the framework.
To take Logback as an example:
Also (again, depending on the framework) you might have to provide some sort of configuration file.
For our example of Logback we need a
logback.xml within the
main/resources directory of our application.
When running on SCP CloudFoundry using the SAP Java Buildpack the logging implementation is provided at runtime by the container. This means, if you only run the application on Cloud Foundry you don't need to provide any implementation. Still, oftentimes logging is also important for local deployment and testing. For that providing an implementation is required.
To start writing your own log entires you also need to specify a dependency to the SLF4J API:
Depending on the chosen logging implementation you might not need to specify the SLF4J API, but it's in general best practice to not rely on transitive dependencies and therefore reference the SLF4J API anyway.
Having these prerequisite out of the way, you can now start logging:
What do you see in this example?
- In the first line inside the class a new logger is created (once per class), with the class object as a reference. This class name will then be logged alongside the message in the logs.
- Inside the
doSomethingmethod this logger is now used to log the fact that the given method was called. The method you use for that depends on the level at which you want to see the message. Other options besides
As you can see, no reference to the actual logging implementation can be found in the code. This is the benefit of using SLF4J as a logging facade. This allows you to change the logging implementation without any changes to your application code.
If you are logging more and more information you might find yourself in cases where you concatenate
Strings or log inside a loop. This might cause unnecessary load on your system if the runtime log level is higher than the messages you actually want to log. To make this more plastic have a look at the following example:
Now assume that
someResults contains hundreds or thousands of entries and the log level at runtime is set to
INFO. This would mean that the loop is run without actually doing anything.
To prevent this kind of empty loops you can use guards like
logger.isDebugEnabled() in the following way:
That way the loop is only executed if actually necessary.
Logging frameworks offer different options to configure the behavior of the implementation. Which options are available and how to configure them highly depends on the framework you are using.
Generally, all frameworks offer some way of configuring:
- The application log level
- The output format
Please refer to the documentation of the specific logging implementation you are using for detailed information on what is available and how to apply it.
The SDK archetypes already come with Logback preconfigured as the logging implementation. The following gives an overview of how to change these configurations and perform essential steps like changing the log level.
General information about configuring Logback can be obtained from the documentation. This section only explains some basics.
Logback is configured via the configuration file located in the
src/main/resources directory of your
It is named
logback.xml for TomEE and
logback-spring.xml for Spring based projects.
To understand how Logback detects this file have a look at their documentation.
This configuration file is not accounted for when running a TomEE based application on SCP Cloud Foundry! To configure logging on Cloud Foundry refer to the dedicated section below.
In this configuration file you will find a block like this:
This basically tells Logback to log all messages with level
INFO and higher to an appender with the reference
Valid values for the
level property are:
So, if you want to log all packages with level
DEBUG, for example, you could set it the following way:
However, usually you want to set the logging level for certain packages (or classes) only. For this you would add the following line:
So, in the case that you want to log all requests sent and responses received by the Apache HttpClient in your application locally you would have the following configuration block:
If you want to set the debug levels of your application running on Cloud Foundry (using the SAP Java Buildpack) you have to set the
This allows you to also change the log level at runtime, as we will see further down in this section.
To set the environment variable with every start of the application it is advised to set it in your deployment descriptor of your project. This is typically a Manifest or MTA file in your project root directory. It usually looks something like this:
So, in the case that you want to log all requests sent and responses received by the Apache HttpClient in your application on Cloud Foundry you would set
SET_LOGGING_LEVEL to the following value:
As mentioned earlier, it's possible to set environment variable via the Cloud Foundry CLI. The SAP Java BuildPack should then be able to pickup these changes and propagate them to your application.
So, assuming that you have the initial configuration shown above and you want to start logging the Apache HttpClient, you would now issue the following command on your command line:
Don't forget to change the environment variable back to the previous state. In this example case the command would be the following:
- How to use SLF4J with "legacy" logging frameworks: http://www.slf4j.org/legacy.html
- Debug Logging of the Apache HttpClient: https://hc.apache.org/httpcomponents-client-4.5.x/logging.html