11

I have this very basic example of Spring Job.

@Scheduled(fixedRate = 90000)
    public void myScheduler() throws Exception {

        // Print here execution time into console and save into DB
    }

I have to do some very heavy calculations. Is there a way to calculate total execution time? There is a solution with listener, but I would like to do it inside the job because I want to do it in the Job implementation code.

royalghost
  • 2,773
  • 5
  • 23
  • 29
Peter Penzov
  • 1,126
  • 134
  • 430
  • 808

4 Answers4

9

Can be nicely done using @Aspect

First, add to your pom.xml:

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Second, make sure that your class has @Component and @EnableScheduling.

Finally, create an Aspect class for Spring's Scheduled annotation

@Aspect
@Component
public class TimeScheduler {

    @Around("@annotation(org.springframework.scheduling.annotation.Scheduled)")
    public void timeScheduledMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("starting stopwatch");
        Object result = null;
        StopWatch watch = new StopWatch();
        try {
            watch.start();
            result = joinPoint.proceed();
        } finally {
            watch.stop();
            long executionTime = watch.getLastTaskTimeMillis();
            String className = joinPoint.getTarget().getClass().getSimpleName();
            String methodName = joinPoint.getSignature().getName();

            // print to log/console all the details you need: Time took, 
            // method name, class name etc...
            System.out.println("Time took: [" + executionTime + "] ms");
            System.out.println("Class: " + className);
            System.out.println("Method: " + methodName);

           // db.save(executionTime)
        }
    }
} 

Notice that in this way the executionTime time needs to be persisted from the Aspect class, as a method with @Scheduled can not get any arguments to be later saved.

Stempler
  • 1,309
  • 13
  • 25
  • Thanks but is there a way to use this code insight my method because I need to print the result into the same method? – Peter Penzov Apr 23 '19 at 09:19
  • What do you mean print the result into the same method? Do you mean into the log? Its possible to edit the code and print the method and class names from the Aspect class. – Stempler Apr 23 '19 at 17:10
4

If your project/app is light, you can just put some:

long startTime = System.getCurrentTimeInMillis();
// whatever long processing here
long endTime = System.getCurrentTimeInMillis();
long processingTime = endTime - startTime;
// do print 
// do store to DB

However, if your project/app is big (i.e. lots of Schedulers), you may want to inject before/after aspects (also called point-cuts) to them.

Refer to this Stackoverflow answer.

Edward Aung
  • 3,014
  • 1
  • 12
  • 15
3
Instant begin = Instant.now();
// do whatever...    
Instant end= Instant.now();
long delta = Duration.between(begin, end).toMillis();

Instant class requires Java8

Rao Pathangi
  • 504
  • 3
  • 11
2

You can use Spring Framework's StopWatch to calculate the execution time. For multiple tasks also you can use stopwatch.

    StopWatch stopWatch = new StopWatch("StopWatchDemo");
    StopWatchDemo stopWatchDemo = new StopWatchDemo();

    stopWatch.start("StopWatchTask1");
       stopWatchDemo.performTask1();
    stopWatch.stop();

    stopWatch.start("StopWatchTask2");
        stopWatchDemo.performTask2();
    stopWatch.stop();

To get total execution time for all tasks(here task1 and task2)

    System.out.println("StopWatchDemo tasks took total: " + stopWatch.getTotalTimeSeconds() + " seconds");

To get task wise execution time

for(TaskInfo taskInfo :stopWatch.getTaskInfo()) {
    System.out.println(taskInfo.getTaskName()+"-"+taskInfo.getTimeSeconds()+" secs");
}
gprasadr8
  • 789
  • 1
  • 8
  • 12