Kat
Kat

Reputation: 4695

Logging local variable values with AspectJ

I heard a lot of great things about how AOP could help modularize things like logging, but now as I am trying to implement this, I am finding AspectJ is very limited.

Not only is it sometimes impossible to add logging to the correct lines, but accessing local variable values seems very difficult. You have to make sure that variable is either returned by a method or used as arguments to a method.

The simple fact that the logging is outside of the scope of the code being logged is a severe limitation.

Is there a better approach to accessing local variable values for the purpose of logging them?

For example, I have some code that maintains a counter, and I want to log the value of that counter. The original code looked something like this:

int totalMoves = 0;

while(canMove()) {
    // ...
    totalMoves++;
}

Logger.log(totalMoves);

I can't find a clean way to move this logging code to an aspect. There's simply no way to access totalMoves as it is. It appears that my options are:

  1. Make totalMoves a publicly accessible field (in opposition to information hiding and encapsulation)
  2. Create a dummy function that does nothing but allow a "hook" for AspectJ (no better than just logging directly)
  3. Make totalMoves a private field, but use reflection to access it (seems like a bad code smell; creates an unnecessary field and complicates access to the variable)

To be honest, I guess what I was expecting when looking into AOP was inserting code verbatim to remove cross cutting concerns. These limitations make me question if AspectJ is even worth using in the current context.

Is there anyway around this issue? Or am I approaching this the wrong way? In which case, how can I cleanly log local variables?

TL;DR: Logging local variable values with AspectJ is a mess, how can I make it better?

Upvotes: 0

Views: 2267

Answers (2)

Behrang Saeedzadeh
Behrang Saeedzadeh

Reputation: 47913

Another option is to refactor that chunk of your code and extract a method out of it and add an aspect that logs its return value:

@Log
private int totalMoves() {
    int totalMoves = 0;

    while(canMove()) {
        // ...
        totalMoves++;
    }

    return totalMoves;
}

Upvotes: 0

kriegaex
kriegaex

Reputation: 67297

This question has been asked many times before. The answer is no. AspectJ cannot intercept read/write operations on local variables, only on members. Besides, the JVM might optimise away some of your source code dealing with local variables under certain circumstances, but that is another topic.

Abusing AOP frameworks like that would not a good idea anyway, even if it was possible. They are made for decorating classes with additional functionality or intercepting some actions accessible from outside, not for hacking local state. What does it say about your application design if an aspect needs to know local variable names?

As for the three options you are mentioning, they are not the only ones you have. You can also make totalMoves a private field and provide a getter and/or a setter if that makes sense. Furthermore, even if you decide not to use getter/setter, you can still use a privileged aspect which is able to access private or protected fields in combination with get|set() pointcuts.

Feel free to ask if you do not understand this answer after reading the provided links.

Upvotes: 3

Related Questions