Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use AOP with AspectJ for logging?

I would like to add "trace" messages to all my public methods as follows:

public void foo(s:String, n:int) { // log is a log4j logger or any other library
  log.trace(String.format("Enter foo with s: %s, n: %d", s, n))
  ...
  log.trace("Exit foo") 
}

Now I would like to add all those log.trace to my methods automatically with AOP (and byte code instrumentation). I am thinking about AspectJ. Does it make sense? Do you know any open-source, which does exactly that?

like image 707
Michael Avatar asked Jan 12 '12 17:01

Michael


4 Answers

@Loggable annotation and an AspectJ aspect from jcabi-aspects is a ready mechanism for you (I'm a developer):

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

To log both entry and exit, as per the question's requirements:

@Loggable(Loggable.DEBUG, prepend=true)
public String load(URL url) {
  return url.openConnection().getContent();
}

All logs go to SLF4J. Check this post for more details.

like image 22
yegor256 Avatar answered Oct 19 '22 09:10

yegor256


I have created a simple aspect to capture the execution of public methods. The core of this AspectJ code is the pointcut definition:

pointcut publicMethodExecuted(): execution(public * *(..));

Here we are capturing all public methods with any return type, on any package and any class, with any number of parameters.

The advice execution could be visualized on code snippet below:

after(): publicMethodExecuted() {
    System.out.printf("Enters on method: %s. \n", thisJoinPoint.getSignature());

    Object[] arguments = thisJoinPoint.getArgs();
    for (int i =0; i < arguments.length; i++){
        Object argument = arguments[i];
        if (argument != null){
            System.out.printf("With argument of type %s and value %s. \n", argument.getClass().toString(), argument);
        }
    }

    System.out.printf("Exits method: %s. \n", thisJoinPoint.getSignature());
}

This advice use thisJoinPoint to get the method signature and arguments. And that's it. Here is the aspect code:

public aspect LogAspect {

pointcut publicMethodExecuted(): execution(public * *(..));

after(): publicMethodExecuted() {
    System.out.printf("Enters on method: %s. \n", thisJoinPoint.getSignature());

    Object[] arguments = thisJoinPoint.getArgs();
    for (int i =0; i < arguments.length; i++){
        Object argument = arguments[i];
        if (argument != null){
            System.out.printf("With argument of type %s and value %s. \n", argument.getClass().toString(), argument);
        }
    }
    System.out.printf("Exits method: %s. \n", thisJoinPoint.getSignature());
}

For more complex examples I would recommend the book AspectJ: In Action.

like image 140
Pedro Ghilardi Avatar answered Oct 19 '22 11:10

Pedro Ghilardi


You can use different pointcuts to make your requirement. This documentation will help you.

Straight forward solution

like image 4
nidhin Avatar answered Oct 19 '22 10:10

nidhin


You can try out this open source http://code.google.com/p/perfspy/. PerfSpy is a runtime logging, performance monitoring and code inspecting tool. It uses ApsectJ to weave around your application code at runtime, and logs the execution time of every method and its input parameters and values. It has a UI application, in which you can view the method invocations and their input and return values as trees. With it, you can spot performance bottlenecks and understand complex code flow.

like image 1
user2695490 Avatar answered Oct 19 '22 10:10

user2695490