How to trace a Method in a spring aop? - java

I want to log a message in the format MethodName invoked at date-time in the console whenever the method successfully completes.
I have defined a custom performance intwerceptor by extending the AbstarctMonitoringInterceptor. Then I am confused what to do next? I mean how to include it in xml or in my aspect class, so that it executes?
Here is my code:
public class MyPerformanceMonitorInterceptor extends AbstractMonitoringInterceptor {
public MyPerformanceMonitorInterceptor() {
}
public MyPerformanceMonitorInterceptor(boolean useDynamicLogger) {
setUseDynamicLogger(useDynamicLogger);
}
#Override
protected Object invokeUnderTrace(MethodInvocation mi, Log log) throws Throwable {
// TODO Auto-generated method stub
String name = createInvocationTraceName(mi);
long start = System.currentTimeMillis();
log.info("Method " + name + " execution started at:" + new Date());
try {
return mi.proceed();
}
finally {
long end = System.currentTimeMillis();
long time = end - start;
log.info("Method "+name+" execution lasted:"+time+" ms");
log.info("Method "+name+" execution ended at:"+new Date());
}
}
Logging is my aspect class. How to add this custom to my aspect class and get the invocation time?

Related

How to create a timing watchdog for method execution count protection

I want to code something that would notify a listener if a count of method call have been exceeded a max value with a specified time laps.
Let's say that I would want to know if a method is called a little bit too fast within a period of sliding 30 seconds.
In this method I would notify this watchdog that it must increment the counter.
And I want to be able to track more than 100 call within the configured time laps.
So the watchdog would be instantiated like this : new Watchdog(100, 30, TimeUnit.SECONDS, theListener);
I don't really know how to start the coding if this kind of thing. Any hints would be appreciated.
If I have well understood, you need one or several WatchDogs which tracks if a maximumNumber has been reached within a timeLapse?
I guess this fits well the Observer pattern, in which a Subject (e.g. a program) sends notifications to Observers (e.g. a WatchDog observing how the program behaves).
Here would be the program or subject being observed by Watchdogs:
public class Subject {
private List<WatchDog> watchDogs = new ArrayList<>();
public void add(WatchDog watchDog) {
watchDogs.add(watchDog);
}
public void execute() {
for (WatchDog watchDog : watchDogs) {
watchDog.update();
}
}
}
Here would be the WatchDog definition:
// Verifies that maxCalls is not reached between lastTimeUpdateWasCalled and
// lastTimeUpdateWasCalled + periodInSeconds
public class WatchDog {
private Date lastTimeUpdateWasCalled = null;
private int currentNumberOfCalls = 0;
private int maxCalls;
private int periodInSeconds;
public WatchDog(int maxCalls, int periodInSeconds) {
this.maxCalls = maxCalls;
this.periodInSeconds = periodInSeconds;
}
public void update() {
this.currentNumberOfCalls = this.currentNumberOfCalls + 1;
Date now = new Date();
if (lastTimeUpdateWasCalled == null) {
this.lastTimeUpdateWasCalled = now;
this.currentNumberOfCalls = 1;
return;
}
long endOfPeriodMillis = lastTimeUpdateWasCalled.getTime() + this.periodInSeconds * 1000L;
Date endOfPeriod = new Date(endOfPeriodMillis);
if (now.before(endOfPeriod)) {
this.currentNumberOfCalls = this.currentNumberOfCalls + 1;
if (this.currentNumberOfCalls >= this.maxCalls) {
System.out.println("Watchdog has detected that " + this.currentNumberOfCalls + " have been done within "
+ this.periodInSeconds + " seconds");
}
} else {
// reinitialization
this.currentNumberOfCalls = 1;
this.lastTimeUpdateWasCalled = now;
}
}
}
Here is how you could put the whole together:
public class Main {
public static void main(String[] args) throws Exception {
Subject s1 = new Subject();
WatchDog w = new WatchDog(2, 2);
s1.add(w);
s1.execute();
//Thread.sleep(2000);
s1.execute();
}
}
More information about the observer pattern here: https://sourcemaking.com/design_patterns/observer

How can I start and stop a timer in different classes?

I want to measure the time from the start of an incoming HTTP request and the application getting to a certain point. Both those points in time are located in different classes. How would I start and stop a timer from these different classes. I don't see a way to use 'named' timers from the MeterRegistry.
How would I go about this?
You can use AOP as below :
#Aspect
#Component
public class ControllerMonitor {
protected static final Logger LOGGER = LoggerFactory.getLogger(ControllerMonitor.class);
#Before("execution(public * com.demo.controller.*Controller.*(..))")
public void logBeforeAccess(JoinPoint joinPoint) {
if(joinPoint!=null){
String packageName = joinPoint.getSignature()!=null?joinPoint.getSignature().getDeclaringTypeName():"LOG-404";
LOGGER.info(". . .A request initiated from controller [" + packageName + "."+ getMethodSignature(joinPoint) + "]. . .");
}
}
#After("execution(public * com.demo.controller.*Controller.*(..))")
public void logAfterAccess(JoinPoint joinPoint) {
if(joinPoint!=null){
String packageName = joinPoint.getSignature()!=null?joinPoint.getSignature().getDeclaringTypeName():"LOG-404";
LOGGER.info(". . .Request from controller [" + packageName + "."+ getMethodSignature(joinPoint) + "] completed. . .");
}
}
#AfterThrowing(pointcut = "execution(public * com.demo.controller.*Controller.*(..))",throwing="exception")
public void logAfterThrowing(Exception exception){
LOGGER.error("Exception caught:"+ exception.getMessage());
}
private String getMethodSignature(JoinPoint joinPoint){
if(joinPoint!=null){
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
StringBuilder sb=new StringBuilder();
if(arguments!=null){
for (Object param: arguments) {
sb.append(param).append(",");
}
sb =(sb.length()>1)?sb.deleteCharAt(sb.length()-1):sb;
}
methodName = methodName+"("+new String(sb)+")";
return methodName;
}else{
return "LOG-405";
}
}
}
Use AOP …...No need to do changes on each class level. It will be one place config..

Java Is it possible to send a httpServletRequest to a function?

i got a function that looks like this:
#GET
#Path("/execute/{scriptId}")
public String execute(#Context HttpServletRequest req, #PathParam("scriptId") Long scriptId) {
/* ... */
engine.eval(getSrc(req.getServletContext().getRealPath("js/boot.js")));
if (scriptId == 1L)
engine.eval(getSrc(req.getServletContext().getRealPath("js/test.js")));
else
engine.eval(getSrc(req.getServletContext().getRealPath("js/test2.js")));
/* that above, its the only place i need the req */
}
i call it from a html page...
execute 1
and it works fine...
now...i made a timer....and in the timer i need to call that function, but i have no idea how to get the httpservletrequest parameter for the function...
here is the code:
#Timeout
public void execute(Timer timer) {
Long scriptId = Long.parseLong(timer.getInfo().toString());
execute(/*here i need something*/, scriptId);
System.out.println("Timer Service : " + scriptId);
System.out.println("Current Time : " + new Date());
System.out.println("Next Timeout : " + timer.getNextTimeout());
System.out.println("Time Remaining : " + timer.getTimeRemaining());
System.out.println("____________________________________________");
}
so, basically, i need to call that function with the timer...
any ideas?
If your function doesn't need the HttpServletRequest (i.e. it doesn't need to call methods on the HttpServletRequest) then you can extract your existing code into an implementation method that does not depend on an HttpServletRequest and in your execute method call that implementation:
#GET
#Path("/execute/{scriptId}")
public String execute(#Context HttpServletRequest req, #PathParam("scriptId") Long scriptId) {
return executeImpl(scriptId);
}
public String executeImpl(Long scriptId) {
...// your current implementation
}
And then your timer can also call that method:
#Timeout
public void execute(Timer timer) {
Long scriptId = Long.parseLong(timer.getInfo().toString());
executeImpl(scriptId);
System.out.println("Timer Service : " + scriptId);
System.out.println("Current Time : " + new Date());
System.out.println("Next Timeout : " + timer.getNextTimeout());
System.out.println("Time Remaining : " + timer.getTimeRemaining());
System.out.println("____________________________________________");
}
Sure, it's just an interface which you can implement.
Of course implementing it to do something useful may not be trivial, depending on what you're doing with the request in the other method.
Getting a ready implementation of an HttpServletRequest from some 3rd party library that implements the JEE standard might help, but may well be overkill.

Get input value to ejb 3.1 throw interceptor

Do you know if there is any way to log, throw an interceptor, the input values of the called method?
my actual interceptor is
public class Interceptor {
#AroundInvoke
public Object interceptor(InvocationContext invocationcontext) throws Exception{
//Stampa prima del metodo
long startTime = System.currentTimeMillis();
log.debug("Invoked method: "+invocationcontext.getMethod().getName());
//here I would like to log also parameters.
try{
return invocationcontext.proceed();
} finally{
log.debug("End of method: " + invocationcontext.getMethod().getName());
log.debug(" duration: " + (System.currentTimeMillis() - startTime));
}
}
}
The bean is
#Interceptors({Interceptor.class})
#Stateless
public class MrBean implements MrBeanRemote, MrBeanLocal {
/**
* Default constructor.
*/
public MrBean() {
}
public void print(String in){
System.out.println("Print: " + in);
}
}
So if i call the print method with in = "print that" the interceptor should log "print that". Is it possible?
Thanks in advance
You want to log the parameters of your method, so you can use the getParameters() method on the InvocationContext :
http://docs.oracle.com/javaee/6/api/javax/interceptor/InvocationContext.html#getParameters()

Hystrix async methods within javanica not running inside spring-boot java application

I am using spring-cloud-starter (ie.. spring boot with all the microservices features). When I create hystrix method in a component annotated using the javanica #HystrixCommand, follow the directions on the javanica github site (https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica) to make that method run async, regardless of whether I use their 'Future<>' or Reactive execution 'Observable<>', nothing runs/executes and I get
java.lang.ClassCastException: springbootdemo.EricComponent$1 cannot be cast to springbootdemo.Eric whenever I attempt to pull the result (in the case of Future<>) or get a callback (in case of Reactive Execution .. and println's dont trigger so it really didnt run).
public class Application { ...
}
#RestController
#RequestMapping(value = "/makebunchofcalls/{num}")
class EricController { ..
#RequestMapping(method={RequestMethod.POST})
ArrayList<Eric> doCalls(#PathVariable Integer num) throws IOException {
ArrayList<Eric> ale = new ArrayList<Eric>(num);
for (int i =0; i<num; i++) {
rx.Observable<Eric> oe = this.ericComponent.doRestTemplateCallAsync(i);
oe.subscribe(new Action1<Eric>() {
#Override
public void call(Eric e) { // AT RUNTIME, ClassCastException
ale.add(e);
}
});
}
return ale;
}
#Component
class EricComponent { ...
// async version =========== using reactive execution via rx library from netflix ==============
#HystrixCommand(fallbackMethod = "defaultRestTemplateCallAsync", commandKey = "dogeAsync")
public rx.Observable<Eric> doRestTemplateCallAsync(int callNum) {
return new ObservableResult<Eric>() {
#Override
public Eric invoke() { // NEVER CALLED
try {
ResponseEntity<String> result = restTemplate.getForEntity("http://doges/doges/24232/photos", String.class); // actually make a call
System.out.println("*************** call successfull: " + new Integer(callNum).toString() + " *************");
} catch (Exception ex) {
System.out.println("=============== call " + new Integer(callNum).toString() + " not successfull: " + ex.getMessage() + " =============");
}
return new Eric(new Integer(callNum).toString(), "ok");
}
};
}
public rx.Observable<Eric> defaultRestTemplateCallAsync(int callNum) {
return new ObservableResult<Eric>() {
#Override
public Eric invoke() {
System.out.println("!!!!!!!!!!!!! call bombed " + new Integer(callNum).toString() + "!!!!!!!!!!!!!");
return new Eric(new Integer(callNum).toString(), "bomb");
}
};
}
}
Why would I be getting back an EricComponent$1 instead of a Eric? btw, Eric is just a simple class with 2 strings... its ommitted.
I am figuring that I must have to explicitly execute, but that alludes me because: 1) Doing it with Future<> the queue() method is not available as the documentation claims and 2) doing it with Observable<> there really isn't a way to execute it that I get.
Do you have the #EnableHystrix annotation on you application class?
The subscribe method is asynchronous and you are trying to populate a list in a synchronous controller method so there may be a problem there. Can you change the subscribe to toBlockingObservable().forEach() and see if that helps?
Update #1
I was able to duplicate. Your default method should not return an Observable<Eric>, just an Eric.
public Eric defaultRestTemplateCallAsync(final int callNum) {
System.out.println("!!!!!!!!!!!!! call bombed " + new Integer(callNum) + "!!!!!!!!!!!!!");
return new Eric(new Integer(callNum).toString(), "bomb");
}
Update #2
See my code here https://github.com/spencergibb/communityanswers/tree/so26372319
Update #3
When I commented out the fallbackMethod attribute, it complained that it couldn't find a public version of EricComponent for AOP. I made EricComponent public static and it worked. A top level class in its own file would work to. My code, linked above, works (assuming the restTemplate call works) and returns n OK.

Categories

Resources