JDK java.util.logging

JDK comes with the java.util.logging (JUL) library which separates event generation from the filter and final consolidation. 

The use of the JUL library is described in detail on the Oracle website.  For more information, see Java Logging Overview and Javadoc de LogManager.

Log consolidation and distribution are managed by a handler object. The standard JDK comes with handlers that write logs to a console, save them to a file, and more. However, it does not include one for sending the logs using syslog so we will use a third-party object available in the Scoja client library.

This article describes the configuration of the handlers provided by Scoja.

The syslog handler

The handler that the Scoja client library provides for sending log data using syslog is called org.scoja.client.jul.SyslogHandler. It contains properties that enable you to configure syslog elements (such as tag, facility, and level) and transport details (such as protocol, host, and port). 

Configuring a single host destination

Configuration for a single destination

handlers = org.scoja.client.jul.SyslogHandler, java.util.logging.ConsoleHandler
 
org.scoja.client.jul.SyslogHandler.level = INFO
org.scoja.client.jul.SyslogHandler.protocol = stream
org.scoja.client.jul.SyslogHandler.host = relay
org.scoja.client.jul.SyslogHandler.port = 514
org.scoja.client.jul.SyslogHandler.retries = 3
org.scoja.client.jul.SyslogHandler.facility = local0
org.scoja.client.jul.SyslogHandler.levelmap = FINE,CONFIG,INFO,WARNING,950,SEVERE
org.scoja.client.jul.SyslogHandler.program = my.app.jultest
org.scoja.client.jul.SyslogHandler.message = \
${date}|${sequence}|${thread}|${logger}|${level}|${class}|${method}|${message:URL:|}|${exceptionclass}|${exceptionmessage}|${stacktrace}

The following table describes the properties that configure the handler.

Property Value
.level The severity level of events to be sent to the host destination. For example, INFO. Any events with a lesser priority level will be discarded.
.protocol This indicates the transport protocol to use. For TCP, the value is stream. For UDP, the value is packet.
.host The hostname of the destination server.
.port The port of the destination server.
.retries The number of retries to attempt when there is a connection problem. After this number of retries have been attempted, the event will be discarded.
.facility This value combines the event source and the syslog severity level value (0 - 7).
.levelmap Comma-separated list of the syslog levels to include in the logs sent to the destination. 
.program The tag used to identify the log and which will be applied to all log events.
.message The user-defined template that dictates how the outgoing log data will be structured in the message body. See the Templates section below for a more detailed explanation.

Configuring multiple host destinations

In order to send a log simultaneously to multiple host destinations, index and repeat the protocol, host, and port properties, as shown in the following example:

Tho locations configuration

handlers = org.scoja.client.jul.SyslogHandler, java.util.logging.ConsoleHandler
 
org.scoja.client.jul.SyslogHandler.level = INFO
org.scoja.client.jul.SyslogHandler.protocol-1 = stream
org.scoja.client.jul.SyslogHandler.host-1 = relay
org.scoja.client.jul.SyslogHandler.port-1 = 514
org.scoja.client.jul.SyslogHandler.protocol-2 = packet
org.scoja.client.jul.SyslogHandler.host-2 = syslog
org.scoja.client.jul.SyslogHandler.port-2 = 514
org.scoja.client.jul.SyslogHandler.retries = 3
org.scoja.client.jul.SyslogHandler.facility = local0
org.scoja.client.jul.SyslogHandler.levelmap = FINE,CONFIG,INFO,WARNING,950,SEVERE
org.scoja.client.jul.SyslogHandler.program = my.app.jultest
org.scoja.client.jul.SyslogHandler.message = \
${date}|${sequence}|${thread}|${logger}|${level}|${class}|${method}|${message:URL:|}|${exceptionclass}|${exceptionmessage}|${stacktrace}
  • The SyslogHandler handler, explores if there are host-1, host-2, etc. properties. 
  • If they are found, then it will add new destinations, but once one is missing, it stops adding the destinations. 
  • For each destination, it uses the corresponding protocol-i and port-i. If not found, it uses the protocol and port values or the default values.

Templates

The content of both message and program properties are templates where the dollar sign ($) can be used as a reference to a JUL event element. 

The element name and an optional argument that determines the way the element should be handled are contained in braces ({...}) following the dollar sign ($).

Inside the braces, the element and its possible argument are separated by a colon ( : ).

  • The element name is mandatory. 
  • The argument is optional and depends on the element type.

Elements that have no arguments are:

  • class - the name of the class that generates the event.
  • method - the name of the method that generates the event.
  • thread - the name of the thread that generates the event.
  • sequence - the sequence number of the event within the ones generated by the same logger.
  • level - the name of the JUL level
  • level# - same as above but in numerical form
  • exception class - the name of the class if there has been an exception.

The elements that may have arguments are:

  • logger - the name of the logger. It has a pre-processing argument.
  • date - the moment when the JUL event is generated. It has an argument with a date format admissible for java.text.SimpleDateFormat. If omitted, it uses the yyyy-MM-dd HH:mm:ss.SSS format.
  • message - the message of the JUL event. It has a pre-processing argument.
  • parameter - a parameter of the JUL event. It supports 2 arguments, the parameter index (0 if omitted) and a pre-processor.
  • exception message - the exception message. It has a pre-processing argument.
  • stacktrace - the stack trace of the exception. It has a pre-processing argument.

Pre-processing arguments are used to format the element, eliminating any characters that may truncate the syslog event. They are always optional. If no pre-processing argument is specified, the element is not re-formatted. These arguments are composed of two values separated by a colon ( : ) :

  • First, the name of the pre-processor. This is URL if you want to replace the disruptive characters with a %. This is C if you want to replace the disruptive characters with C escape sequences.
  • Second, the dangerous characters to be replaced before the data is sent.

For example, ${message:URL:|} indicates that and | character found in the message element of the event should be replaced with a %.

Examples

Suppose you want to show the exceptions traces.

  • You refer to an exception trace with:

 ${stacktrace}

  • The line endings of the tracers usually are characters that cannot go into a syslog event, so you must do some processing to remove them: 

${stacktrace:URL:\n}

  • Since Scoja handler is designed to send through syslog, it knows that whenever a pre-processing is done and no special characters are indicated, it must include those dangerous characters to syslog, so you can use:

 ${stacktrace:URL}

Suppose you want to build a message with various elements of the JUL event separated by pipes (|) and that your application generates messages where any character may appear, including line ends and pipes.

  • We cannot use ${message} because there might be line ends.
  • We cannot use ${message:URL}because there might be pipes. 
  • You should include the pipe and use:

 ${message:URL:|}

Extracting info from the message

The application of the syslog tag is critical for Devo to correctly process events. The SyslogHandler handler lets you define the tag using the program property, and this tag is applied to all events processed by the handler. However, if you want to apply multiple tags to different events in a simple log, you can use the MessageSyslogAttributer handler from Scoja. This handler allows the extraction of information from the message, delete it and use it to determine other elements of the syslog event.

The following example shows the use of this handler to determine which tag to apply based on the prefix of the message element. 

Configuration with multiple tags

handlers = org.scoja.client.jul.MessageSyslogAttributer, java.util.logging.ConsoleHandler
 
org.scoja.client.jul.MessageSyslogAttributer.target = org.scoja.client.jul.SyslogHandler
org.scoja.client.jul.MessageSyslogAttributer.pattern = ^([a-zA-Z0-9.]+):
org.scoja.client.jul.MessageSyslogAttributer.keyGroup = 1
org.scoja.client.jul.MessageSyslogAttributer.dropGroup = 0
org.scoja.client.jul.MessageSyslogAttributer.program = my.app.app1.out
org.scoja.client.jul.MessageSyslogAttributer.message = ${message}
org.scoja.client.jul.MessageSyslogAttributer.key-1 = info
org.scoja.client.jul.MessageSyslogAttributer.program-1 = my.app.app1.info
org.scoja.client.jul.MessageSyslogAttributer.key-2 = error
org.scoja.client.jul.MessageSyslogAttributer.program-2 = my.app.app1.error
org.scoja.client.jul.MessageSyslogAttributer.priority-2 = local1.error
 
org.scoja.client.jul.SyslogHandler.level = INFO
org.scoja.client.jul.SyslogHandler.protocol-1 = stream
org.scoja.client.jul.SyslogHandler.host = relay
org.scoja.client.jul.SyslogHandler.port = 514
org.scoja.client.jul.SyslogHandler.message = \
${date}|${sequence}|${thread}|${logger}|${level}|${class}|${method}|${message:URL:|}|${exceptionclass}|${exceptionmessage}|${stacktrace}

MessageSyslogAttributer is an intermediate handler that processes the JUL event and sends the result to the handler specified by the .target property. This should always be set to org.scoja.client.jul.SyslogHandler since it is the only handler capable of recieving events processed by MessageSyslogAttributer.

MessageSyslogAttributer scans the message, searching for the regular expression specified by the value of the .pattern property. In the example above, .pattern identifies the message prefix up to the first colon (:). If this pattern is found, then MessageSyslogAttributer processes the event as follows: 

  1. It deletes the character sequence captured with the group of parentheses specified in the dropGroup property from the message. If this property is missing, it doesn't delete anything from the message. The parentheses are numbered in the regular expression the usual way and they can be consulted on the javadoc of the Pattern class. 
  2. Extracts the sequence captured with the group of parentheses specified in the keyGroup property (called K).
  3. Search for the first i in which the key-i property is equal to K.
  4. Browse all other properties that have that and writes the values in the JUL event.

As shown in the above example, the prefix is captured until the colon (:). Since dropGroup is 0, everything captured by that expression is removed from the message, so the message is defined as the suffix after the first colon (:), but excluding the colon.

Two key properties are defined, key-1 and key-2, with info and error values, respectively. The K value that we extracted is compared with these values.

  • If the result is info, all the JUL event elements with a definition ending in -1 will be changed. In this case, is the program-1 so, only the tag from my.app.app1.info will be changed.
  • If the result is error, the program-2 and priority-2 will be converted to my.app.app1.error and local1.error, respectively. 

In this case, if you want to send an event to Devo and place it on my.app.app1.info, please use the following code:

Sending to my.app.app1.info

Logger log = Logger.getLogger("MyClass");
log.info("info:rest of the event message");

If you want to send to my.app.app1.error, you should use the following code:

Sending to my.app.app1.error

Logger log = Logger.getLogger("MyClass");
log.info("error:rest of the event message");

Have we answered your question?

If not, please contact our technical support team via email by clicking the button below.

CONTACT US