Skip to content

Overview

Karsten Schnitter edited this page Dec 12, 2025 · 7 revisions

Java Logging Support for Cloud Foundry

This repository contains a collection of support libraries for Java applications. They serve two main purposes:

  1. Provide means to emit structured application log messages in JSON format.
  2. Instrument parts of your application stack to collect request metrics in a JSON request log.

The libraries take an opinionated approach on the fields contained in the generated JSON. It produces a standard format, that can be easier parsed and analysed in log analysis services. Details on the standard fields can be found in the fields.yml files for application logs and request logs. With proper configuration those fields should be populated automatically. Users can change the field values add additional fields known as custom fields to the generated messages. See the article on Custom Fields for details.

The library contains special support to add application metadata from a Cloud Foundry runtime environment, such as application id and name. This support is now optional, since the runtime usually sends these metadata in a side-channel when exporting the logs. See the article on Writing Application Logs for configuration details.

A Short Overview of the Log Formats

cf-java-loggging-support will generate two kind of log messages. While the full specification of the log formats can be found in the beats folder, we start off with a short overview of what messages would look like when using these support libraries.

Application Logs

You can run the sample application locally and create a simple log message with the following curl command:

curl -X POST -u user:secret 'localhost:8080/log/test/info?m=Hello+cf-java-logging-support!'

The response will be `Generated info log with message: "Hello cf-java-logging-support!" with the following associated application log. Note, that the library will emit JSON in a single line but for better readability the examples are formatted in this documentation.

{
  "msg":"Hello cf-java-logging-support!",
  "level":"INFO",
  "written_ts":"1648619448171070000",
  "logger":"test",
  "thread":"http-nio-8080-exec-1",
  "type":"log",
  "correlation_id":"6e72144d-ff3f-4d67-93e9-a5b57726017d",
  "written_at":"2022-03-30T05:50:48.171070Z"
}

This line actually stems from the following log statement in the code

    logger.info(message);

The fields that should be familiar to you are logger, thread, level, and msg and directly correspond to pattern fields known from log4j2 or logback. There is, of course, also a "date" included in that message, but we've decided to call that field written_at. Next to it is a field written_ts which represents the "timestamp" when the message was written with nanosecond precision.

The field categories may contain additional category keys that can be later used to filter log messages by specific categories. How this field can be filled is covered in more detail in the section Writing Application Logs.

The remaining fields provide context information that is either derived from information provided by the Cloud Foundry runtime environment or via request instrumentation and is kept in mapped diagnostic contexts.

Request Logs

For the same curl command, the library's servlet instrumentation also generates a request log. This log captures details about the HTTP request and response in a single JSON line.

{
  "categories":[ "request" ],
  "request":"/log/test/info?m=Hello+cf-java-logging-support!",
  "request_size_b":-1,
  "logger":"com.sap.hcp.cf.logging.servlet.filter.RequestLogger",
  "type":"request",
  "layer":"[SERVLET]",
  "protocol":"HTTP/1.1",
  "remote_ip":"redacted",
  "response_content_type":"text/plain;charset=ISO-8859-1",
  "request_received_at":"2022-03-30T05:50:47.986380Z",
  "written_at":"2022-03-30T05:50:48.196559Z",
  "response_time_ms":208.262,
  "direction":"IN",
  "response_sent_at":"2022-03-30T05:50:48.194642Z",
  "response_status":200,
  "method":"POST",
  "level":"INFO",
  "response_size_b":66,
  "written_ts":"1648619448196559000",
  "remote_port":"redacted",
  "thread":"http-nio-8080-exec-1",
  "remote_host":"redacted",
  "correlation_id":"6e72144d-ff3f-4d67-93e9-a5b57726017d"
}

As you can see, it shares all the context fields with application log messages. The log pattern fields though have been replaced by a set of request metric fields, like, e.g., response_status, response_time_ms, and response_size_b.

Logging Sensitive User Data:

For security and data privacy reasons, certain request headers and connection details are not logged by default. These include fields like remote_ip, remote_host, remote_user, and referer.

You can enable logging for these fields by setting the following environment variables:

Environment Variable Optional Fields
LOG_SENSITIVE_CONNECTION_DATA: true activates the fields remote_ip, remote_host, remote_port, x_forwarded_for
LOG_REMOTE_USER: true activates the field remote_user
LOG_REFERER: true activates the field referer

An example for this can be found in the manifest.yml of the sample app:.

Correlation IDs

You may also notice that both log messages contain a field correlation_id which allows you to correlate an incoming request to application log messages that have been emitted during the cause of processing that request.

When an incoming request is processed, the library's instrumentation (e.g., the servlet filter) injects a unique correlation ID into the logging context (MDC). All application logs generated during the processing of that request will automatically include this ID, making it simple to filter and correlate all related activities in your log analysis tool.

The necessary configuration will be covered in the section Request Instrumentation.

Clone this wiki locally