How to log FATAL (or any user level log) using SLF4J and Log4j2

I have those specific requirements :

  • You must be able to log in to the FATAL system.
  • Must use SLF4J
  • Must use Log4j2

Right now, here is my implementation :

final Logger logger = LoggerFactory.getLogger(HelloWorld.class); final Marker marker = MarkerFactory.getMarker("FATAL"); logger.error(marker, "!!! Fatal World !!!"); 

Here is my PatternLayout (in yaml):

 PatternLayout: Pattern: "%d{ISO8601_BASIC} %-5level %marker [%t] %logger{3.} - %msg%n" 

Here is my log output :

 20150506T155705,158 ERROR FATAL [main] - !!! Fatal World !!! 

Do you have any idea how to effectively remove "ERROR" from the output of a journal?

Many thanks

+7
java slf4j log4j2
source share
6 answers

In this near working solution, I came with some colleagues:

  • Create a lethal marker class using SLF4J markers.
  • Using RoutingAppender , use a marker as a routing pattern: "$$ {marker:}"
  • Set up a Fatal-specific appender that has its own PatternLayout, which does not include LogLevel, but a hard-coded FATAL level.

Here's a Java example:

 Marker fatal = MarkerFactory.getMarker("FATAL"); // Usage example final Logger logger = LoggerFactory.getLogger(FatalLogger.class); logger.log(fatal, "this is a fatal message"); // Log sample : 20150514T115144,279 FATAL [main] FatalLogger - this is a fatal message 

Here is a YAML example:

 Configuration: status: debug Appenders: RandomAccessFile: - name: APPLICATION_APPENDER fileName: logs/application.log PatternLayout: Pattern: "%d{ISO8601_BASIC} %-5level %msg%n" - name: FATAL_APPENDER fileName: logs/application.log PatternLayout: Pattern: "%d{ISO8601_BASIC} FATAL %msg%n" Routing: name: ROUTING_APPENDER Routes: pattern: "$${marker:}" Route: - key: FATAL ref: FATAL_APPENDER - ref: APPLICATION_APPENDER #DefaultRoute Loggers: Root: level: trace AppenderRef: - ref: ROUTING_APPENDER 
+2
source share

Marker is actually not what you want here. Marker designed to "enrich" the log messages, which makes them more convenient to search. You are trying to change the log level / priority, which is slightly different.

You use logger.error() , which will log the message as an ERROR level.

If the FATAL level is not predefined (usually there is, for example, logger.fatal() ), use the general logger.log() , which allows you to specify the log level.

 logger.fatal(yourMessage); 

OR

 logger.log(priorityLevel, yourMessage); 

UPDATE:

From the SLF4J website:

The Marker interface in the org.slf4j package makes the FATAL level pretty much redundant. If a given error needs attention, except for those highlighted for common errors, simply mark the registration operator with a specially marked marker, which can be called "FATAL" or any other name to your liking.

http://www.slf4j.org/faq.html#fatal

Thus, with SLF4J it is not possible to have a FATAL log level. I strongly disagree with the rationale for this decision, but that is what it is.

+7
source share

The only solution I have found so far is to use 5 markers:

 final Marker traceMarker = MarkerFactory.getMarker("TRACE"); final Marker debugMarker = MarkerFactory.getMarker("DEBUG"); final Marker infoMarker = MarkerFactory.getMarker("INFO"); final Marker warnMarker = MarkerFactory.getMarker("WARN"); final Marker errorMarker = MarkerFactory.getMarker("ERROR"); final Marker fatalMarker = MarkerFactory.getMarker("FATAL"); 

And the log going through the marker every time:

 logger.info(infoMarker, "!!! INFO World !!!"); logger.error(errorMarker, "!!! ERROR World !!!"); logger.error(fatalMarker, "!!! FATAL World !!!"); 

And modify PatternLayout to completely remove LogLevel and always register a marker, for example:

 PatternLayout: Pattern: "%d{ISO8601_BASIC} %marker [%t] %logger{3.} - %msg%n" 

I think this solution is a hack ... It will also remove the log level of any external library using the correct LogLevel.

Summary This solution is not a good solution.

UPDATE . I tried another solution by writing RewritePolicy:

 public class FatalRewritePolicy implements RewritePolicy { public static final String FATAL = "FATAL"; @Override public LogEvent rewrite(final LogEvent logEvent) { final Marker marker = logEvent.getMarker(); if (marker == null) return logEvent; // Log Level is final in the LogEvent, there no way we can modify it. Level level = logEvent.getLevel(); return null; } } 

There seems to be no way to change LogLevel for LogEvent in Log4j2 (which makes sense).

Summary : There is still no solution.

0
source share

Here is what I did for log4j , which I also recommend for log4j2 ....

Write your own slf4j static aka bridge middleware. This requires a little work, but it’s worth it, for many difficult reasons, 1 that I will blog about one day.

Here is what you do.

<soap dish-bombing>

Honestly, slf4j is badly damaged because

  • it is very difficult / impossible to override the static initialization of hardcore, and also not provide logger.fatal(...) .
  • Markers are unnecessary and inherently complex:
    • Very few projects use markers. I really watched / grepped open source projects and the use of markers is close to zero.
    • Those that use the marker because fatal absent. This is not 80/20. Markers for 1% and fatal for 99%.
    • Many developers believe that somehow using the β€œfatal” marker will match it with the fatal.
    • Few people know that a separate marker includes me .
    • There is a match for what the MDC context provides. Event-oriented database data (elasticsearch, druid, etc.), the MDC context is excellent (name / value pair).

</ soap-box-bombastic>

1 one of them can actually be part of the loading process of your logging structure, against which it is difficult to determine an almost arbitrary static initialization

0
source share

I know the question is for log4j. I found this page looking in relation to logback. Here, sl4j recommends: https://www.slf4j.org/faq.html#fatal .

0
source share

You can add "FATAL" at the beginning of your message. For example:

 LOGGER.error("FATAL: database connection lost."); 

You lose some things, such as level-based filtering, but it can be good for many people, especially since you are unlikely to filter out FATAL statements (debugging and tracing, of course).

0
source share

All Articles