patternjavaMinor
Logging and profiling - automatic logging through annotations
Viewed 0 times
loggingthroughandautomaticannotationsprofiling
Problem
I am working with a little project intended to allow applications to benefit from aspect oriented programming. The first aspect is logging, which is already working. However I want this code to be more performatic and cleaner.
Whole project
The basic goals is to annotate methods - private/public static or instance - with and Custom annotation
Since it uses reflection in many steps, I am afraid I might have missed something. I would appreciate if anyone reviewed my code.
This code processes the annotations and instruments the methods. How can the method
```
package org.greentea.aspect.log;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.greentea.aspect.log.annotation.LoggableObject;
/**
* LoggableObjects are either Methods or Constructors that migh be logged
* The information logged is the method signature, its arguments and execution
* time
*
* The level of verbosity, and information might be configurable through the use
* of the annotation @LoggableObjet
*
* @author Filipe Gonzaga Miranda
*/
@Aspect
public class LoggableObjects {
PluggableLogger pluggableLogger;
public static ConcurrentMap, PluggableLogger> cachedLoggers = new ConcurrentHashMap<>();
static{
cachedLoggers.putIfAbsent(DefaultPluggableLoggerIfNotInjected.class, new DefaultPluggableLoggerIfNotInjected());
}
/**
* Captures the Annotations {@link LoggableObjects}
*
* And applies the logic to decid
Whole project
The basic goals is to annotate methods - private/public static or instance - with and Custom annotation
@LoggableObjects. This annotation has options to define level of log - how much information to log (only args values, profiling information). Since it uses reflection in many steps, I am afraid I might have missed something. I would appreciate if anyone reviewed my code.
This code processes the annotations and instruments the methods. How can the method
aroundObjects be better executed? Is this a valid idea?```
package org.greentea.aspect.log;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.greentea.aspect.log.annotation.LoggableObject;
/**
* LoggableObjects are either Methods or Constructors that migh be logged
* The information logged is the method signature, its arguments and execution
* time
*
* The level of verbosity, and information might be configurable through the use
* of the annotation @LoggableObjet
*
* @author Filipe Gonzaga Miranda
*/
@Aspect
public class LoggableObjects {
PluggableLogger pluggableLogger;
public static ConcurrentMap, PluggableLogger> cachedLoggers = new ConcurrentHashMap<>();
static{
cachedLoggers.putIfAbsent(DefaultPluggableLoggerIfNotInjected.class, new DefaultPluggableLoggerIfNotInjected());
}
/**
* Captures the Annotations {@link LoggableObjects}
*
* And applies the logic to decid
Solution
I know little about AspectJ, but have a number of more basic points to call out in your code.
Hygiene
Performance
-
You jump through hoops getting the
this can be done instead as:
The above will lock the map only once, not multiple times.
Hygiene
cachedLoggersshould beprivate static finaland notpublic static. Do you really want anyone to be able to replace your instance?
PluggableLogger pluggableLoggeris an instance field, but it should be in the method only (perhaps just calledlogger). As things are at the moment, you risk a race condition when the method is called concurrently.... you could be overwriting the logger part-way through one call, with another call.
throws Throwable.... really? you should always narrow your exceptions down more than that.
throw new AssertionError(...)... really? Why not just anIllegalArgumentException?
Performance
- The
Pattern.compile(...)should be a private-static-final field. The patterns are thread-safe, and designed to be reused.
- Instead of a ConcurrentMap I would consider a thread-local HashMap. This would require benchmarking to resolve, but, it could be significantly better at memory management, especially when there's only the default plugin used.
- You can do the
isDisabledcheck before getting the declaring class, and method name
-
You jump through hoops getting the
clazzPluggLogg ..:Class clazzPluggLogg = loggObject.pluggableLoggerClass();
if(clazzPluggLogg != DefaultPluggableLoggerIfNotInjected.class){
if(cachedLoggers.containsKey(clazzPluggLogg)){
pluggableLogger = cachedLoggers.get(clazzPluggLogg);
}else{
pluggableLogger = clazzPluggLogg.newInstance();
cachedLoggers.putIfAbsent(clazzPluggLogg, pluggableLogger);
}
}else{
pluggableLogger = cachedLoggers.get(clazzPluggLogg);
}this can be done instead as:
Class clazzPluggLogg = loggObject.pluggableLoggerClass();
pluggableLogger = cachedLoggers.computeIfAbsent(clazzPluggLogg, k -> k.newInstance());The above will lock the map only once, not multiple times.
Code Snippets
Class<? extends PluggableLogger> clazzPluggLogg = loggObject.pluggableLoggerClass();
if(clazzPluggLogg != DefaultPluggableLoggerIfNotInjected.class){
if(cachedLoggers.containsKey(clazzPluggLogg)){
pluggableLogger = cachedLoggers.get(clazzPluggLogg);
}else{
pluggableLogger = clazzPluggLogg.newInstance();
cachedLoggers.putIfAbsent(clazzPluggLogg, pluggableLogger);
}
}else{
pluggableLogger = cachedLoggers.get(clazzPluggLogg);
}Class<? extends PluggableLogger> clazzPluggLogg = loggObject.pluggableLoggerClass();
pluggableLogger = cachedLoggers.computeIfAbsent(clazzPluggLogg, k -> k.newInstance());Context
StackExchange Code Review Q#92959, answer score: 2
Revisions (0)
No revisions yet.