Concepts

Concepts

Pax Logging is not trivial bridge to different (3 actually) logging frameworks (Log4J1, Log4J2, Logback), it also provides SPI layer that allows users to extend any logging framework. The most clear usage is when user wants to provide custom appender that processes logging events.

Here’s a summary of logging concepts used by all/most popular logging frameworks and how these concepts map to what Pax Logging provides.

Logging events

Each time a method like log.info() is called in any code fragment, new logging event is created. This event is a representation of a fact that user wants to log some message/information. Each logging event has some information associated like timestamp, code location (if available), message, exception (if needed) and severity (importance) of the event.

Appenders

Appender is kind of processor that does something with the logging event - usually appending new information (typically a line) to a file.

Level and threshold

This is a bit confusing part. At first glance it looks trivial - when user wants to invoke logging method, he/she may use one of typical methods like info(), warn(), trace() or other.

Simply from this set of alternatives we can derive the concept of logging event level (or severity).

Let’s start with something we can treat as canonical - Syslog. Here are the level names and their numerical equivalents:

Table 1. Syslog levels

Numerical value

Severity/level name

Numerical value

Severity/level name

0

Emergency

1

Alert

2

Critical

3

Error

4

Warning

5

Notice

6

Informational

7

Debug

From the above, we can try to summarize:

Numerically higher level is less important.

A concept related to level is threshold. Without giving precise constraints, threshold is a limit for logging events. For the above, Syslog example, setting a threshold value to Warning means that we’re interested in events with Warning or (numerically) lower events.

Thus:

The higher (numerically) the threshold, the more logging events are processed. Less important events are processed.

Adding more confusion:

Logging frameworks (and APIs) used in pax-logging treat the level concept differently…​ Log4J1 has direct relation to Syslog levels, but it’s not a case with Log4J2 and java.util.logging. Here’s a table where Syslog and Log4J1 can be directly related. Placement of levels from other libraries is a bit arbitrary and related to logging level name equivalents.

  • Log4J1: constants in org.apache.log4j.Level class

  • Log4J2: values in org.apache.logging.log4j.spi.StandardLevel enum

  • Logback: constants in ch.qos.logback.classic.Level class

  • java.util.logging: values in java.util.logging.Level class

  • Slf4J: constants in org.slf4j.spi.LocationAwareLogger interface

  • OSGi: constants in org.osgi.service.log.LogService interface

Syslog

Log4J1

Log4J2

Logback

java.util.logging

SLF4J

OSGi

Syslog

Log4J1

Log4J2

Logback

java.util.logging

SLF4J

OSGi

0 - Emergency

Integer.MAX_VALUE - OFF

0 - OFF

Integer.MAX_VALUE - OFF

Integer.MAX_VALUE - OFF

 

 

0 - Emergency

50000 - FATAL

100 - FATAL

 

1000 - SEVERE

 

 

1 - Alert

 

 

 

 

 

 

2 - Critical

 

 

 

 

 

 

3 - Error

40000 - ERROR

200 - ERROR

40000 - ERROR

1000 - SEVERE

40 - ERROR

1 - ERROR

4 - Warning

30000 - WARN

300 - WARN

30000 - WARN

900 - WARNING

30 - WARN

2 - WARNING

5 - Notice

 

 

 

 

 

 

6 - Informational

20000 - INFO

400 - INFO

20000 - INFO

800 - INFO, 700 - CONFIG

20 - INFO

3 - INFO

7 - Debug

10000 - DEBUG

500 - DEBUG

10000 - DEBUG

500 - FINE

10 - DEBUG

4 - DEBUG

7 - Debug

5000 - TRACE

600 - TRACE

5000 - TRACE

400 - FINER

0 - TRACE

 

 

 

 

 

300 - FINEST

 

 

7 - Debug

Integer.MIN_VALUE - ALL

Integer.MAX_VALUE - ALL

Integer.MIN_VALUE - ALL

Integer.MIN_VALUE - ALL

 

 

Notes and confusing parts:

  • Log4J1’s OFF level matches numerical value of Syslog Emergency level

  • java.util.logging: there are too many less important levels (FINE, FINER, FINEST) and too little more critical ones (only SEVERE)

  • Syslog doesn’t define trace level, so its debug entry is duplicated to cover constants from logging frameworks

  • Syslog, Log4J2 and OSGi use increasing numerical level for decreasing event importance

  • Log4J1, java.util.logging and SLF4J use higher numerical levels for more important events

  • Mapping of java.util.logging levels to more popular level names is implemented in org.ops4j.pax.logging.spi.support.BackendSupport.toJULLevel()

  • OFF and ALL special levels have to be treated carefully by pax-logging because the usage of numerical values is totally unintuitive.

Markers

Markers allow to pass/associate additional, dynamic information with logging operation itself. Just as logger name (category) and level are static aspects of the logger itself, marker is associated with single logging invocation (thus effectively with logging event). Single logger may be used to log message with or without marker and it’s up to specific implementation (Logback, Log4J2) to handle the marker accordingly.

For example, Log4J1 doesn’t support markers, so slf4j-log4j12 bridges to Log4J1 using org.slf4j.helpers.MarkerIgnoringBase abstract base class which simply ignores markers. Logback and Log4J2 implement full org.slf4j.spi.LocationAwareLogger with marker support.

Markers are used usually by implementation-specific filters and appenders:

  • filters may be configured to restrict logging statements to ones using (or not using) particular marker

  • some appenders may simply do not do anything if specific marker is (or is not) present (for example that’s the case with ch.qos.logback.classic.boolex.OnMarkerEvaluator that may be attached to ch.qos.logback.classic.net.SMTPAppender)

Finally, a marker may have parent (or child) marker(s) associated - making them something slightly more complex than single name.

In Pax Logging, org.ops4j.pax.logging.PaxLogger interface didn’t contain methods accepting markers. PAXLOGGING-160 passed marker as String attribute through thread-bound org.ops4j.pax.logging.PaxContext. PAXLOGGING-259 adds such methods to this interface.

Remember - in Pax Logging, it’s possible to use for example Log4J2 API to log information that’s effectively handled by Log4J1, so despite the API being aware of markers, they may not be used correctly by actual logging implementation. As consequence, isXXXEnabled(…​, marker, …​) methods may not be handled early in the process of logging.