UPP Java Logging

Tsvetan Dimitrov

Agenda

  • Structured Logging

  • Yet another private library! Why?

  • Library features

Structured Logging

  • No special parsing rules.

  • The format follows an official encoding format (JSON).

  • For interfaces designed for humans, they can simply display the "message" key and hide the other metadata.

Yet another private library! Why?

  • Simplification.

  • Control over library updates.

  • Membership's fluent-logging library contains features not needed by UPP.

  • Built on top of slf4j, logback and slf4j-fluent.

JSON Logging

{
   "@timestamp":"2020-10-30T12:40:58.083+02:00",
   "@version":"1",
   "message":"Example new response log",
   "logger_name":"com.ft.upp.logger.UppLoggerTest",
   "thread_name":"main",
   "level":"DEBUG",
   "level_value":10000,
   "content_type":"application/json",
   "service_name":"example_service",
   "user_agent":"dummy-user-agent",
   "status":200,
   "accept": "application/json"
}

YAML Configuration

config:
  mandatory_fields:
    service_name: "example_service"
  • A file called upp-logger.yml located in src/main/resource.

  • For tests just copy and/or modify the file in src/test/resources.

Log Field Validation

  • Built-in mandatory fields validator (validates for the existence of service_name field).

  • Ability to add new validators and configure them through upp-logger.yml.

Lazy Evaluation

public void info(final String message, Object... args) {
    logInternal(message, m -> logger.info()
    		.log(m, lazy(() -> entries(this.keyConfig))), args);
}
  • All constructed fields are evaluated lazy (the first time they are used) when logging a statement.

Request and Response Logging

  • Logs HTTP request and response metadata by only passing the corresponding request or response object.

log.withRequest(<request_object>).info("Example request");
...

log.withResponse(<response_object>).info("Example response");

Lombok Integration

  • Instantiate UppLogger by using Lombok's @CustomLog annotation.

@CustomLog
public class ExampleApp {

  void doSometing(String randomStuff) {
    log
      .withTransactionId(<tid>)
      .withUuid(<uuid>)
      .withMethodName("doSomething")
      .info("Example" + randomStuff);
  }
}
  • Injects a constant called "log" that contains the instance of UppLogger.

Questions?