9

Okay so I'm trying to make a memory appender (simply a logger, that logs to an ArrayList instead of the console or to a file) but for now I want to disable it from printing to the console.

The questions and websites, I've read so far (but I still cant figure it out is)..

It has all the segments on what I'm trying to achieve, but I'm still kind of confused.

I also read this segment from Logback or Log4j Additivity Explained Which states..

If the aditivity flag of logger X however is set to false, or disabled, then calling x.debug() will only log to the file.

So in theory my log4j.properties file

log4j.rootLogger=ERROR, console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d %5p %c (%F:%L) - %m%n
#hide the Log4jMemoryAppender from console
log4j.logger.nz.ac.massey.cs.sdc.log4jassignment.s06005586.MemoryAppender= ERROR, MEMORY_APPENDER
log4j.appender.MEMORY_APPENDER=nz.ac.massey.cs.sdc.log4jassignment.s06005586.MemoryAppender.Log4jMemoryAppender
log4j.additivity.rootLogger = false
log4j.additivity.console = false
log4j.additivity.MEMORY_APPENDER=false

Should only print ***Hello World and exclude anything else from the MEMORY_APPENDER, rootLogger and console.

package nz.ac.massey.cs.sdc.log4jassignment.s06005586.MemoryAppender;

import java.util.ArrayList;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

public class Log4jMemoryAppender extends AppenderSkeleton {

ArrayList<LoggingEvent> eventsList = new ArrayList();

public static void main (String [] args) {

    PropertyConfigurator.configure("Lib/log4j.properties");
    Log4jMemoryAppender app = new Log4jMemoryAppender();
    Logger logger = Logger.getLogger(Log4jMemoryAppender.class);
    logger.setLevel(Level.INFO);

    logger.addAppender(app);
    logger.info("Hello World");
    logger.debug("Level DEBUG Is SET");

    for (LoggingEvent le: app.eventsList) {
        System.out.println("***" + le.getMessage());
    }
} 

@Override
protected void append(LoggingEvent event) {
    eventsList.add(event);
}

public void close() {
}

public boolean requiresLayout() {
    return false;
}
}

But it doesn't...

appender
(source: iforce.co.nz)

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
classicjonesynz
  • 4,012
  • 5
  • 38
  • 78
  • You have not defined any logger nor any appender for `nz.ac.massey.cs.sdc.log4jassignment.s06005586.MemoryAppender`. – maba Aug 22 '12 at 08:41
  • when I do `Logger logger = Logger.getLogger("nz.ac.massey.cs.sdc.log4jassignment.s06005586.MemoryAppender");` same result, what do you mean defined a logger? – classicjonesynz Aug 22 '12 at 08:42
  • 2
    In your `log4j.properties`. You should have `log4j.logger.nz.ac.massey.cs.sdc.log4jassignment.s06005586.MemoryAppender = ERROR, MEMORY_APPENDER` and `log4j.appender.MEMORY_APPENDER=` – maba Aug 22 '12 at 08:44
  • At least you claim that you have implemented a memory appender. Now you will have to guide the `MEMORY_APPENDER` to point to that actual implementation. – maba Aug 22 '12 at 08:45
  • :) Yeah and I just updated my question with the new properties file. Any ideas? I'm so lost. After defining my logger in the properties and giving it `log4j.additivity.MEMORY_APPENDER=false` its still printing to the console. – classicjonesynz Aug 22 '12 at 08:50
  • 2
    The additivity should not be on `MEMORY_APPENDER`. Change it to `log4j.additivity.nz.ac.massey.cs.sdc.log4jassignment.s06005586.MemoryAppender=false`. And remove the other `additivity` settings. – maba Aug 22 '12 at 09:14
  • Awesome! thank you maba! I've edited your answer with that comment. Thanks so much! – classicjonesynz Aug 22 '12 at 09:21

2 Answers2

6

The line

MEMORY_APPENDER=false

will not work, you cannot set an appender to have the value false.

In you case better do something like this:

log4j.rootLogger=ERROR, console
log4j.appender.console=org.apache.log4j.ConsoleAppender

log4j.logger.nz.ac.massey.cs.sdc.log4jassignment.s06005586.MemoryAppender = ERROR, MEMORY_APPENDER
log4j.additivity.nz.ac.massey.cs.sdc.log4jassignment.s06005586.MemoryAppender = false

The Logger being used in one of your example is nz.ac.massey.cs.sdc.log4jassignment.s06005586.MemoryAppender and that should map to a logger in the log4j.properties or just the package part like nz.ac.massey.cs.sdc.log4jassignment.


It seems like you are mixing a lot here. Is Log4jMemoryAppender your MEMORY_APPENDER or not?

And why are you calling BasicConfigurator.configure()? Don't you want to use the log4j.properties?


Normally in a class you do this to get a logger:

package com.mycompany;

public class MyClass {
    private static final Logger log = Logger.getLogger(MyClass.class);
    ...
}

The logger name will be the fully qualified classname com.mycompany.MyClass.

Then you can have a log4j.properties like this:

log4j.rootLogger=ERROR, console
log4j.appender.console=org.apache.log4j.ConsoleAppender

log4j.logger.com.mycompany=INFO, file
log4j.additivity.com.mycompany=false

logfj.appender.file = <some file appender>

OK, starting from beginning. A very simple example.

src/main/java/Log4JTest.java

package org.stackoverflow;

import org.apache.log4j.Logger;

/**
 * @author maba, 2012-08-22
 */
public class Log4JTest {

    public static final Logger log = Logger.getLogger(Log4JTest.class);

    public static void main(String[] args) {
        log.error("Error in main");
    }
}

src/main/resources/log4j.properties

log4j.rootLogger = ERROR, console

log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

Now compile and make sure that log4j.properties is in your classpath together with the log4j.jar and your own classes when running.

You will see this:

0    [main] ERROR org.stackoverflow.Log4JTest  - Error in main

From here you can try to add a file appender or your own memory appender.

maba
  • 47,113
  • 10
  • 108
  • 118
  • No you put the `log4j.properties` in the classpath and then the Log4J framework will find it and use it. – maba Aug 22 '12 at 06:56
  • Start with the simplest possible setup and go from there. I will add an example. It cannot possibly go wrong. – maba Aug 22 '12 at 07:08
  • Is your `log4j.properties` in the classpath? I guess not. – maba Aug 22 '12 at 07:48
  • Yeah it is in the class path http://www.iforce.co.nz/i/ojz3e3uq.shh.png, the only way I've figured on how I can get access to the `log4j.properties` is by using `PropertyConfigurator.configure("log4j.properties");` is working – classicjonesynz Aug 22 '12 at 08:28
  • is your `log4j.properties` file under your `src` path? If not, add it there that log4j is able to read it and then you don't have to call the PropertyConfigurator. – christian.vogel Aug 22 '12 at 08:43
  • The additivity of the root logger cannot be set to false. – Ceki Aug 22 '12 at 09:41
  • @Ceki True. Removed that part. – maba Aug 22 '12 at 10:25
  • _And why are you calling BasicConfigurator.configure()? Don't you want to use the log4j.properties?_ You made my day, I tried to understand the necessity of using one or another. Thank you! – Daria Apr 11 '16 at 10:54
0

I've just fixed this issue by setting this at log4j.xml, replaced value="TRACE" to value="ERROR". Hope this can help some one :)

    <root>
        <priority value="ERROR" />
        <appender-ref ref="STDOUT"/>
    </root>
  • 1
    I don;t think the OP wanted to change the LEVEL that should be logged... only the output to a particular appender. – Darius X. Jul 09 '20 at 02:56