tags:

views:

184

answers:

1

I am starting using logback and I want to know if there are better ways of doing something. I have this code:

public class ClassA {
    private List<String> l;
    private Logger logger;

    public ClassA(){
        this.logger = LoggerFactory.getLogger(this.getClass().getName());
    }
....
    public List<String> method() {
        this.logger.debug("method()");
        List<String> names;

        try {
            names = otherClass.getNames();
        } catch (Exception e) {
            String msg = "Error getting names";
            this.logger.error(msg);
            throw new ClassAexception(msg, e);
        }

        this.logger.debug("names: {}", xxxxx);
        return names;
}

I have some doubts so far:

  • Every class will have a this.logger = LoggerFactory.getLogger(this.getClass().getName()); to create a logger.
  • Every method will have a this.logger.debug("method()"); to know when a method is called.

That doesn't look good. Is there a way to solve it?

Also I want to print a list in the .log in this line: this.logger.debug("names: {}", xxxxx);

the xxxxx should be replaced with something to print the list. An anonymous class?

Thanks for reading!

+3  A: 

Using AspectJ and log4j you can use this. Compile your code with ajc compiler instead of javac and then run as normal with java executable.

You need to have the aspectjrt.jar and log4j.jar on the classpath.

import org.aspectj.lang.*;
import org.apache.log4j.*;

public aspect TraceMethodCalls {
    Logger logger = Logger.getLogger("trace");

    TraceMethodCalls() {
        logger.setLevel(Level.ALL);
    }

    pointcut traceMethods()
        //give me all method calls of every class with every visibility
        : (execution(* *.*(..))
        //give me also constructor calls
        || execution(*.new(..)))
        //stop recursion don't get method calls in this aspect class itself
        && !within(TraceMethodCalls);

    //advice before: do something before method is really executed
    before() : traceMethods() {
        if (logger.isEnabledFor(Level.INFO)) {
            //get info about captured method and log it
            Signature sig = thisJoinPointStaticPart.getSignature();
            logger.log(Level.INFO,
                        "Entering ["
                        + sig.getDeclaringType().getName() + "."
                        + sig.getName() + "]");
        }
    }
}

Check out the AspectJ documentation on how to change the TraceMethodCalls calls.

// e.g. just caputre public method calls
// change this
: (execution(* *.*(..))
// to this
: (execution(public * *.*(..))


Regarding the

Also I want to print a list in the .log in this line: this.logger.debug("names: {}", xxxxx);

That's supported by slf4j/logback by default. Just do

logger.debug("names: {}", names);

for example

List<String> list = new ArrayList<String>();
list.add("Test1"); list.add("Test2"); list.add("Test3");
logger.debug("names: {}", list);

//produces
//xx::xx.xxx [main] DEBUG [classname] - names: [Test1, Test2, Test3]

Or do you want something specifically different?

jitter
Added answer to print list question
jitter
Note that any object can be printed with the {}-construction. It is a call to toString(). If you need another rendering than that, then create a wrapper that holds the object you want to log, with a custom toString method.See http://www.mail-archive.com/[email protected]/msg02259.html
Thorbjørn Ravn Andersen
@Thorbjørn Ravn Andersen: I was willing to do it with an anonymous class because toString() method in the class I have uses the one from object.
Macarse