Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can i log every method called in a class automatically with log4j

Tags:

java

log4j

I have a class with database calls, and I generally want to log every method called (with arguments) in this class with log4j:

logger.debug("foo(id="+id+") initiated");

Is it possible to do this automatically? Maybe by using some sort of annotation in start of each method instead of writing every single logger.debug?

Today I have to update my logging.debug every time I change arguments or method name.

like image 274
Peeer Avatar asked Nov 13 '12 06:11

Peeer


People also ask

How do you create a Logger class in Java?

The process of creating a new Logger in Java is quite simple. You have to use Logger. getLogger() method. The getLogger() method identifies the name of the Logger and takes string as a parameter.

Why do we use log4j instead of system out Println?

Log4j allows logging on class-by-class basis i.e., each class can be covered whereas System. out. println can be controlled at application level. Through Log4j we can turn on or off the logging at runtime by changing the configuration file.

How do you add a log statement in Java?

To use a different Layout with java. util. logging , set the Appender 's formatter property to the Layout of your choice. To do this in code, you can create a new Handler and use its setFormatter method, then assign the Handler to the Logger using logger.


2 Answers

Try @Loggable annotation and an AspectJ aspect from jcabi-aspects (I'm a developer):

@Loggable(Loggable.INFO)
public String load(URL url) {
  return url.openConnection().getContent();
}

All method calls are logged through SLF4J.

This blog post explains it step by step: Java Method Logging with AOP and Annotations

like image 128
yegor256 Avatar answered Sep 17 '22 02:09

yegor256


If you have interfaces declaring the methods you want to log calls to, you can use the standard Proxy API to achieve what you want.

The Proxy API would allow you to wrap your actual implementation in a new, proxy class, that would log the call, and the forward the call to implementation. You just have to implement one InvocationHandler that does the logging and the forwarding.

For example,

interface Calculator {
  int add(int a, int b);
}

class CalculatorImpl implements Calculator {
  @Override public int add(int a, int b) { return a+b; }
}

class LoggingInvocationHandler implements InvocationHandler {
  private final Object delegate;
  public LoggingInvocationHandler(final Object delegate) {
    this.delegate = delegate;
  }
  @Override invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("method: " + method + ", args: " + args);
    return method.invoke(delegate, args);
  }
}

class X {
  public static void main(String... args) {
    final Calculator calc = new CalculatorImpl();
    final Calculator loggingCalc =
      (Calculator) Proxy.newProxyInstance(X.class.getClassLoader(),
                                          new Class[] {Calculator.class},
                                          new LoggingInvocationHandler (calc));
    loggingCalc.add(2, 3); // shall print to the screen
  }
}

You can also easily log the return values and exceptions thrown by the methods, just by changing the code in the InvocationHandler. Also, you could use any logging framework you like instead of System.out.println as in the example.

To log return values and exceptions, you could do something like:

  @Override invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("method: " + method + ", args: " + args);
    try {
      final Object ret = method.invoke(delegate, args);
      System.out.println("return: " + ret);
      return ret;
    } catch (Throwable t) {
      System.out.println("thrown: " + t);
      throw t;
    }
  }
like image 45
Bruno Reis Avatar answered Sep 19 '22 02:09

Bruno Reis