I'm planning to handle logging in spring.
Few suggest to handle it via LoggingInterceptor and some suggest to use AOP cross cutting concerns
which one is the recommended or best practice to follow for enterprise applications?
Thanks.
Both approaches have there own benefits and shortcomings. Logging via LoggingInterceptor is better approach as It is a standard library provided by Java to handle logging, you can do custom logging also.
AOP is better appraoch when you want to implement logging on more granular level as on certain return values of functions or classes. e.g if you want to log request only when the returning value is null. you can do it using AOP as :
#AfterReturning(pointcut = "execution(* com.foo.bar..*.*(..))", returning =
"retVal")
public void logAfterMethod(JoinPoint joinPoint, Object retVal) {
...
}
You can also do logging on returning value using Logging Interceptor but you need to write another function for that. i-e
public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object
arg3) throws Throwable {
log = LogFactory.getLog(arg3.getClass());
log.info("LOGGING IS: "+arg1.getName());
}
For production point of view AOP has performance overhead as you are adding overhead to execution of all your service calls. While Logging Intercept is just a class with normal execution cycle.
Related
My application has several JAX-RS API, all of them are getting a transaction id as header, is there way we can access transaction id into Jboss Logger? we tried MDC but does that not help. Basically I am looking efficient way to add transaction id into each log.
You did not mention how you actually do the logging: explicit log. statements in the code, or some CDI/JAXRS interceptors...
A common way to achieve the desired functionality is to define a filter/interceptor on the boundary layer (JAX-RS in your case), that extracts the relevant request data and stores it in a context thats available to logger during execution of that request. Which is exactly what JAX-RS filters and MDC are for.
A simple example:
#Provider
public class TransactionLoggingFilter implements ContainerRequestFilter, ContainerResponseFilter {
#Context
HttpServerRequest request;
#Override
public void filter(ContainerRequestContext context) {
MDC.put("transactionId", request.getHeader("transactionId"));
}
#Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
MDC.remove("transactionId");
}
}
With that, you will store the value of your transactionId header in MDC scope before each HTTP request is processed and remove it after processing is complete.
Note: if you have other JAX-RS filters, you might need to configure priorities correctly (so that your logging extraction filter runs before others for example) see documentation
MDC scope is bound the thread that executes the request(careful if you use Quarkus reactive, make sure that it is propagated correctly) and will be passed to the logger impl with every log invocation.
To actually print out the value from MDC in your logs, you need to modify the Quarkus log format via:
quarkus.log.console.format=%d{HH:mm:ss} %-5p %X{transactionId} [%c{2.}] (%t) %s%e%n
You can access any MDC scope var with expression %X{var_name}.
See Quarkus documentation on logging for more info.
I'm using spring data rest with #RepositoryRestResource where all the verbs are automatically handled for all the entities in the system.
There is no controller necessary for my project.
But I do want to perform certain action before the GET call is made to an entity. What is the best way to do this without writing a custom controller?
There are event handlers I can write in Spring Data Rest like #HandleAfterDelete but there are not handlers for GET.
I'm afraid there is currently no solution which would provide this out of the framework itself. However, there is a pull request which was discussed but not yet implemented as there are still open questions with regard to the universality of findBy* methods.
In case you do not need a that general solution the yet suggested HandlerInterceptor is the way to go…
public class YourInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) throws Exception {
// decide on request.getMethod() what to do next
}
}
I want to create an annotation for sending timer metrics for my methods. I thought about doing something like that:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Timer {
}
And then I want to use AspectJ for doing the metrics collection logic as follows:
#Aspect
public class TimerAspect {
#Pointcut("#annotation(Timer)")
public void timerPointcut() {}
#Pointcut("execution(* com.mycompany.**.*(..))")
public void methodPointcut() {}
#Before("methodPointcut() && timerPointcut()")
public void startTimer() throws Throwable {
// start timer logic here
}
#After("methodPointcut() && timerPointcut()")
public void sendTimer() throws Throwable {
// stop timer and send metrics logic here
}
}
What I would like to understand, and I'm not sure how to benchmark it, is whether I have a performance penalty here when using this annotation.
The Spring AOP performance penalty is considerable because dynamic proxies are being used through which each call will be routed.
AspectJ performance is much better, the penalty is really small because no dynamic proxies are needed. You can use native AspectJ from within Spring as described in the Spring manual, chapter "Using AspectJ with Spring applications".
As described in my comments here, you need to be careful what you measure. For instance, it makes no sense to measure the additional time it takes to do the actual timekeeping and logging compared to the original application without any timekeeping/logging because if you would add those manually via scattered timekeeping/logging statements, the penalty would also exist. I am also reasoning about profiling aspects here.
If you want to measure the pure aspect penalty, maybe you could do it similar to my sample code here.
I'm newbie to Spring AOP. I do understand the concept behind it and i also do understand the concept of #Before or #After etc usage. What i am so confused is still the usage of Spring AOP. Think of the below method of a class.
public void test(int x) {
:
x++;
logger.info("This is a test" + x);
:
try {
:
} catch (Exception e) {
throw new ...
}
:
}
The old way of capturing the log is as shown above.
Here's my questions:
If i were to implement the above method using Spring AOP, this logger will be removed but then does Spring AOP able to capture this log message? (from what i know Spring AOP does not look inside a method)
If answer to clause 1) is yes then how is it done?
If answer is no what's the point of using Spring AOP. Usage of #Before is useless unless you want to capture the information like parameters prior to execution of the method. Most of the time we want to capture some log inside a method itself.
Forget about AspectJ. I do know that AspectJ can do the above job.
I just want to know what's the point of using Spring AOP if it cannot do the very fundamental thing of capturing logs inside a method.
Any help is appreciated.
Further note:
I assume after implementating Spring AOP the above code would be like this. The logger call is no longer in the test method since it will be taken care of by the aspect class. Isn't that the purpose of AOP? To remove cross cutting concern from objects (since it's not related to the actual service of the object) and be taken care of by the aspect class?
public void test() {
:
try {
:
} catch (Exception e) {
throw new ...
}
:
}
If Spring AOP cannot do this what's the point of having a AOP?
I am having difficulty understanding what you are asking for here. In general, I don't know what it means to 'capture logs inside a method', but I think I can provide some assistance anyways.
It sounds to me like you want to arbitrarily insert code into random points in a method, not necessarily at the beginning or the end of the method. In general, Spring AOP cannot do this, and I am not sure that AspectJ will be able to help with either, but I am less familiar with that to give you a definitive answer.
Spring AOP, like you said, can inject before/after/around various JoinPoints in your codebase. These JoinPoints are going to be methods, and only in Spring managed classes.
So if you have a method like the following, you can add logging (via System.out in this case) around it via an #Around aspect.
The code:
public void test() {
System.out.println("I am in a method now");
}
The aspect:
#Around("execution(public * *(..))")
public void publicMethods(ProceedingJoinPoint pjp) {
System.out.println("before in an aspect");
pjp.proceed();
System.out.println("after in an aspect");
}
This essentially turns the initial method into this (as well as adding these System.out's to all public methods):
public void test() {
System.out.println("before in an aspect");
System.out.println("I am in a method now");
System.out.println("after in an aspect");
}
Depending on the layout of your code, you may be able to effectively insert arbitrarily by creating methods at the points that you want to insert. I wouldn't recommend this, but it certainly is possible.
Finally, here are the answers to your questions:
You could replace the logger with a #Before aspect, assuming the logging line is the first code in the method. If you were to do that, you would then be able to remove the logging from within the method. I don't quite know what you are asking for with the last sentence, but no, Spring AOP does not look 'inside' a method.
Spring AOP is able to 'capture' it because Spring will proxy the class.
The point of Spring AOP is to be able to 'intercept' method calls. You may not see a real use for it, but it is extremely useful. I would beg to differ on the last sentence, when using Spring AOP, I want to be able to examine what is going into my method, or what is coming out.
EDIT:
You are correct, the log call can be removed, and taken care of by the aspect. The thing that must be noted is that the only opportunities for the log method to be called by the aspect are either before or after the actual method invocation.
I am having some strange problems using spring and Load-Time-Weaving using AspectJ.
In one of my Apsects, I wanted to react on invocations of the "doAuthentication" Method of the class org.springframework.flex.security3.SpringSecurityLoginCommand. Therefore I created a method:
#Around("execution(* org.springframework.flex.security3.SpringSecurityLoginCommand.doAuthentication(..))")
public Object aroundDoAuthentication(ProceedingJoinPoint pjp) throws Throwable {
...
This aspect is woven correctly if I use the aspectj-weaver agent, but is ignored if I use the spring-weaver. Unfortunately I have to use the spring-weaver, if I want correct aspect-spring integration. The only way I found out to get my aspect woven is to weave it around every method of the target class and to programatically filter the aspect calls:
#Around("execution(* org.springframework.flex.security3.SpringSecurityLoginCommand.*(..))")
public Object aroundDoAuthentication(ProceedingJoinPoint pjp) throws Throwable {
final String methodName = pjp.getSignature().getName();
if("doAuthentication".equals(methodName)) {
...
Using the above code, I managed to weave everythgin correctly, but I am not sattisfied with this as it seems to be a big hack to me.
Could anyone please explain why using the Spring-Weaver I am not able to weave the same as with the aspectj-weaver?
Chris
I don't know the code, but this seams to be the same old question.
Spring AOP is per default proxy based.
This means only invocations of methods that come from outside of the bean go though the proxy. Therefore only this invocation can trigger the AOP advice.