Article

Learn how to direct EMA Java log to Java Logging API

Jirapongse Phuriphanvichai
Developer Advocate Developer Advocate

The Enterprise Message API is an open source, data-neutral, multi-threaded, ease-of-use API providing access to OMM and RWF data. As part of the Refinitiv Real-Time Software Development Kit, or RTSDK, the Enterprise Message API allows applications to consume and provide Open Message Model data at the message level of the API stack.

EMA Java uses the Simple Logging Facade for Java (SLF4J) logging API to log information, and error messages for the following classes (loggers):

·        com.refinitiv.ema.access.OmmConsumerImpl

·        com.refinitiv.ema.access.OmmIProviderImpl

·        com.refinitiv.ema.access.OmmNiProviderImpl

This article introduces SLF4J and demonstrates how to use it with Java Logging API.

Simple Logging Facade for Java

Simple Logging Facade for Java uses a simple façade pattern to offer a generic API for different logging frameworks (e.g., java.util.logging, logback, Log4j). It allows end users to select the desired logging framework when deploying applications. The SLF4J package contains several jar files referred to as "SLF4J provider" and each provider supports a corresponding framework. For example:

File

Description

slf4j-nop.jar

SLF4J provider for NOP, silently discarding all logging

slf4j-simple.jar

SLF4J provider for Simple implementation which outputs all events to System.err

slf4j-jdk14.jar

SLF4J provider for java.util.logging

slf4j-reload4j.jar

SLF4J provider for reload4j framework

To change logging frameworks, users just replace slf4j providers on an application’s classpath. For example, to switch from java.util.logging to reload4j, just replace slf4j-jdk14.jar with slf4j-reload4j.jar.

The following diagram shows how the SLF4J providers work.

For the full diagram, please refer to the SLF4J user manual.

The next section will focus on how to configure and use EMA Java with the SLF4J JDK logging provider (slf4-jdk14.jar).

Java Logging API  (java.util.logging)

Java Logging API was introduced in JDK 1.4. When using JDK 1.4 or higher, developers can use the built-in logging package provided by the java.util.logging package to log application messages.

SLF4J supports Java Logging API through the SLF4J provider for java.util.logging (slf4j-jdk.jar). To use the Java Logging API with slf4j, users just add or replace the slf4j-jdk.jar file on an application’s classpath.

EMA Java provides the slf4j-jdk.jar file in the Refinitiv Real-Time SDK package. It is in the  RTSDK-BinaryPack\Java\Eta\Libs\SLF4J\slf4j-xxx directory. For example:

Developers can enable Java Logging API via configurations or create custom log handlers to process log entries.

Java Logging API Configurations

The Java logging API (java.util.logging) loads configurations from the logging.properties file. By default, Java 8 locates this file in the $JAVA_HOME/jre/lib/ directory while Java 9 and above locate this file from $JAVA_HOME/conf. However, developers can overwrite this via the JVM arguments or coding.

  • Load the logging.properties file via coding

The following code can be used to load the logging.properties file.

LogManager.getLogManager().readConfiguration(new FileInputStream("logging.properties"));

  • Load the logging.properties file via the JVM arguments

The logging.properties file can also be specified via the java.util.logging.config.file argument.

-Djava.util.logging.config.file=logging.properties

Logging.properties

Users specify active handlers and handlers' settings in the logging.properties file. Here is an example of a Java Logging API configuration file.

    	
            

handlers=java.util.logging.ConsoleHandler, java.util.logging.FileHandler

.level=FINEST

java.util.logging.ConsoleHandler.level=FINEST

java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter

 

java.util.logging.FileHandler.level=FINEST

java.util.logging.FileHandler.pattern= %h/java%u.log

java.util.logging.FileHandler.limit=50000000

java.util.logging.FileHandler.count=20

java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter

java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %4$-7s %2$s %n%5$s

Please see the descriptions of Java Logging API configurations below.

 

Global Configuration

Description

handlers

Specify a comma-separated list of log Handler. There are two default handlers provided by Java Logging API.

·        java.util.logging.ConsoleHandler: This handler writes all the logging messages to console

·        java.util.logging.FileHandler: This handler writes all the logging messages to the file in the XML format

.level

Specify which kinds of events are logged across all loggers. This is the default global logging level which can be overridden by a facility-specific level.

Level mapping between Java Logging API and SLF4J

java.util.logging

SLF4J

OFF

No Logger on

FINEST

TRACE

FINER

DEBUG

FINE

DEBUG

CONFIG

INFO

INFO

INFO

WARNING

WARN

SEVERE

ERROR

 

ConsoleHandler Configuration

Description

java.util.logging.ConsoleHandler.level

Specify the default level for the Handler (defaults to Level.INFO).

java.util.logging.ConsoleHandler.filter

Specify the name of a Filter class to use (defaults to no Filter).

java.util.logging.ConsoleHandler.formatter

Specify a formatter used to format the log messages. There are two available formatters in java logging API.

  • java.util.logging.SimpleFormatter: This formatter generates text messages with basic information. ConsoleHandler uses this formatter class to print log messages to the console.
  • java.util.logging. XMLFormatter: This formatter generates XML message for the log, FileHandler uses this as a default formatter.

java.util.logging.ConsoleHandler.encoding                     

Specify the name of the character set encoding to use (defaults to the default platform encoding).

FileHandler Configuration

Description

java.util.logging.FileHandler.level

Specify the default level for the Handler (defaults to Level.ALL).

java.util.logging.FileHandler.filter

Specify the name of a Filter class to use (defaults to no Filter).

java.util.logging.FileHandler.formatter

Specify a formatter used to format the log messages. There are two available formatters in java logging API.

  • java.util.logging.SimpleFormatter: This formatter generates text messages with basic information. ConsoleHandler uses this formatter class to print log messages to the console.
  • java.util.logging. XMLFormatter: This formatter generates XML message for the log, FileHandler uses this as a default formatter.

java.util.logging.FileHandler.encoding     

Specify the name of the character set encoding to use (defaults to the default platform encoding).

java.util.logging.FileHandler.limit

Specify an approximate maximum amount to write (in bytes) to any one file. If this is zero, then there is no limit. (Defaults to no limit).

java.util.logging.FileHandler.count

Specify how many output files to cycle through (defaults to 1).

java.util.logging.FileHandler.pattern

Specify a pattern for generating the output file name.

A pattern consists of a string that includes the following special components that will be replaced at runtime:
  • "/": the local pathname separator
  • "%t": the system temporary directory
  • "%h": the value of the "user.home" system property
  • "%g": the generation number to distinguish rotated logs
  • "%u": a unique number to resolve conflicts
  • "%%": translates to a single percent sign "%"

java.util.logging.FileHandler.append

Specify whether the FileHandler should append onto any existing files (defaults to false).

Java.util.logging.FileHandler.maxLocks

Specify the maximum number of concurrent locks held by FileHandler (defaults to 100).

Logger Configuration

Description

<Logger Name>.level

Specify the log level for the logger

SimpleFormatter Configuration

Description

java.util.logging.SimpleFormatter.format

Specify a format for the log messages. The format specifiers have the following syntax.

%[argument_index$][flags][width][.precision]conversion

For more information, please refer to the Format String Syntax document.

The arguments’ indices of LogRecord are:

  1. Date: a Date object representing the event time of the log record.
  2. Source: a string representing the caller, if available; otherwise, the logger's name.
  3. Logger: the logger's name.
  4. Level: the log level.
  5. Message: the formatted log message returned from the Formatter
  6. Thrown - a string representing the throwable associated with the log record and its backtrace beginning with a newline character, if any; otherwise, an empty string.

 

Custom Log Handlers

Instead of using the java.util.logging.ConsoleHandler or java.util.logging.FileHandler to get logging messages, developers can implement custom log handlers to retrieve logging messages from Java Logging API.

Define a custom handler

Custom Log Handlers inherit from java.util.logging.Handler. A java.util.logging.Handler object takes log messages from a Logger and exports them.

The handler can override the publish method to retrieve the logging messages. LogRecord objects are used to pass logging requests between the logging framework and individual log Handlers so developers can access logging messages from the LogRecord objects. For example, the code below gets the logging message level, the source logger’s name, and the log message from the LogRecord object. Then, print them to standard output. 

    	
            

import java.util.logging.Handler;

import java.util.logging.LogRecord;

 

public class MyLogHandler extends Handler{

   @Override

   public void publish(LogRecord record) {

      // TODO Auto-generated method stub

      System.out.println("##### Log: "+record.getLoggerName()+" #####");

      System.out.println("Level: "+ record.getLevel());

      System.out.println("Message: \n"+ record.getMessage());

   }

   @Override

   public void flush() {

      // TODO Auto-generated method stub

   }

 

   @Override

   public void close() throws SecurityException {

      // TODO Auto-generated method stub

   }

 

}

Add a custom handler

A custom handler must be added to a logger to receive logging messages. It can be added to a logger via coding or the handlers configuration.

Use the code below to add a custom handler. 

    	
            

import java.util.logging.Handler;

import java.util.logging.LogManager;

import java.util.logging.Logger;

Logger rootLogger = LogManager.getLogManager().getLogger("");

rootLogger.addHandler(new MyLogHandler());

...

The code calls the getLogger(“”) method to get the root logger, and then adds a custom handler to the root logger.

Otherwise, a custom handler can be specified in the logging.properties file by adding its class name to the handlers configuration.

    	
            

handlers=MyLogHandler

.level=FINEST

After that, the following logging messages from the custom handler (MyLogHandler) will be printed to the console.

    	
            

##### Log: com.refinitiv.ema.access.OmmConsumerImpl #####

Level: FINEST

Message:

loggerMsg

    ClientName: Consumer_1_1

    Severity: Trace

    Text:    Successfully created Reactor.

loggerMsgEnd

 

 

##### Log: com.refinitiv.ema.access.OmmConsumerImpl #####

Level: FINEST

Message:

loggerMsg

    ClientName: LoginCallbackClient

    Severity: Trace

    Text:    Created LoginCallbackClient

loggerMsgEnd

Summary

EMA Java uses the Simple Logging Facade for Java (SLF4J) logging API which is a generic API for different logging frameworks (e.g., java.util.logging, logback, Log4j). This article focuses on how to use SLF4J logging API with Java Logging API  (java.util.logging). Users can either enable Java Logging API via configurations (logging.properties) or create custom log handlers to process log entries.

References

1.      Docs.oracle.com. n.d. ConsoleHandler (Java SE 11 & JDK 11 ). [online] Available at: <https://docs.oracle.com/en/java/javase/11/docs/api/java.logging/java/util/logging/ConsoleHandler.html> [Accessed 23 September 2022].

2.      Docs.oracle.com. n.d. FileHandler (Java SE 11 & JDK 11 ). [online] Available at: <https://docs.oracle.com/en/java/javase/11/docs/api/java.logging/java/util/logging/FileHandler.html> [Accessed 23 September 2022].

3.      Docs.oracle.com. n.d. Formatter (Java SE 11 & JDK 11 ). [online] Available at: <https://docs.oracle.com/en/java/javase/11/docs/api/java.logging/java/util/logging/Formatter.html> [Accessed 23 September 2022].

4.      Docs.oracle.com. n.d. Handler (Java SE 11 & JDK 11 ). [online] Available at: <https://docs.oracle.com/en/java/javase/11/docs/api/java.logging/java/util/logging/Handler.html> [Accessed 23 September 2022].

5.      https://mkyong.com/. 2021. Java Logging APIs Tutorial. [online] Available at: <https://mkyong.com/logging/java-logging-apis-tutorial/> [Accessed 23 September 2022].

6.      Digitalocean.com. 2022. Logger in Java - Java Logging Example | DigitalOcean. [online] Available at: <https://www.digitalocean.com/community/tutorials/logger-in-java-logging-example> [Accessed 23 September 2022].

7.      Docs.oracle.com. n.d. LogManager (Java SE 11 & JDK 11 ). [online] Available at: <https://docs.oracle.com/en/java/javase/11/docs/api/java.logging/java/util/logging/LogManager.html> [Accessed 23 September 2022].

8.      Docs.oracle.com. n.d. LogRecord (Java SE 11 & JDK 11 ). [online] Available at: <https://docs.oracle.com/en/java/javase/11/docs/api/java.logging/java/util/logging/LogRecord.html> [Accessed 23 September 2022].

9.      Developers.refinitiv.com. 2022. Refinitiv Real-Time Java SDK. [online] Available at: <https://developers.refinitiv.com/en/api-catalog/refinitiv-real-time-opnsrc/rt-sdk-java> [Accessed 23 September 2022].

10.   Slf4j.org. 2022. SLF4J Manual. [online] Available at: <https://www.slf4j.org/manual.html> [Accessed 23 September 2022].