Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create my own Appender in log4j?

I am new in log4j. Can anyone explain how to create my own Appender? i.e. how to implement the classes and interfaces and how to override it?

like image 222
unknown Avatar asked May 20 '11 13:05

unknown


People also ask

How does log4j Appender work?

In the log4j2 architecture, an appender is basically responsible for sending log messages to a certain output destination. Here are some of the most useful types of appenders that the library provides: ConsoleAppender – logs messages to the System console. FileAppender – writes log messages to a file.

What is Appender name in log4j?

The appender FILE is defined as org. apache. log4j.

How do I create a custom Appender in log4j2?

In log4j 2, We usually create a plugin for creating a custom appender. When we annotate our custom Appender class with @Plugin(name = “MyCustomAppender”, category = Core. CATEGORY_NAME, elementType = Appender. ELEMENT_TYPE, printObject = true) the plugin name becomes the configuration element name.


2 Answers

Update: the provided solution is valid for Log4J 1.x . If you're looking for 2.x versions, take a look at this article: How to create a custom appender in log4j2

You should extend AppenderSkeleton class, that (quoting javadoc) "provides the code for common functionality, such as support for threshold filtering and support for general filters."

If you read the code of AppenderSkeleton, you'll see that it handles almost all, leaving to you just:

  1. protected void append(LoggingEvent event)
  2. public void close()
  3. public boolean requiresLayout()

The core method is append. Remember that you don't need to implement the filtering logic in it because it is already implemented in doAppend that in turn calls append. Here I made a (quite useless) class that stores the log entries in an ArrayList, just as a demo.

public /*static*/ class MyAppender extends AppenderSkeleton {     ArrayList<LoggingEvent> eventsList = new ArrayList();      @Override     protected void append(LoggingEvent event) {         eventsList.add(event);     }      public void close() {     }      public boolean requiresLayout() {         return false;     }  } 

Ok, let's test it:

public static void main (String [] args) {      Logger l = Logger.getLogger("test");      MyAppender app = new MyAppender();      l.addAppender(app);      l.warn("first");     l.warn("second");     l.warn("third");      l.trace("fourth shouldn't be printed");      for (LoggingEvent le: app.eventsList) {         System.out.println("***" + le.getMessage());     } }  

You should have "first", "second", "third" printed; the fourth message shouldn't be printed since the log level of root logger is debug while the event level is trace. This proves that AbstractSkeleton implements "level management" correctly for us. So that's definitely seems the way to go... now the question: why do you need a custom appender while there are many built in that log to almost any destination? (btw a good place to start with log4j: http://logging.apache.org/log4j/1.2/manual.html)

like image 84
AgostinoX Avatar answered Sep 25 '22 06:09

AgostinoX


If you would like to do some manipulations or decisions you can do it like this:

@Override protected void append(LoggingEvent event) {         String message = null;         if(event.locationInformationExists()){             StringBuilder formatedMessage = new StringBuilder();             formatedMessage.append(event.getLocationInformation().getClassName());             formatedMessage.append(".");             formatedMessage.append(event.getLocationInformation().getMethodName());             formatedMessage.append(":");             formatedMessage.append(event.getLocationInformation().getLineNumber());             formatedMessage.append(" - ");             formatedMessage.append(event.getMessage().toString());             message = formatedMessage.toString();         }else{             message = event.getMessage().toString();         }          switch(event.getLevel().toInt()){         case Level.INFO_INT:             //your decision             break;         case Level.DEBUG_INT:              //your decision             break;         case Level.ERROR_INT:             //your decision             break;         case Level.WARN_INT:             //your decision             break;         case Level.TRACE_INT:             //your decision             break;         default:             //your decision             break;         } } 
like image 45
Lior Avatar answered Sep 24 '22 06:09

Lior