spring aop performance monitoring

Noboby instruments code better than Spring AOP. Generating execution times for methods is made easy with the AbstractMonitoringInterceptor.

Spring AOP configuration:

@Component
@EnableAspectJAutoProxy
@Aspect
public class FileIntAopConfiguration {

	@Pointcut("execution(* com.test.FlatFileProcessor.*(..))")
	public void monitor() {
	}

	@Bean
	public FileIntPerformanceMonitorInterceptor performanceMonitorInterceptor() {
		return new FileIntPerformanceMonitorInterceptor(true);
	}

	@Bean
	public Advisor performanceMonitorAdvisor() {
		AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
		pointcut.setExpression("execution(* com.test.FlatFileProcessor.*(..))");
		return new DefaultPointcutAdvisor(pointcut, performanceMonitorInterceptor());
	}
}
  • Pointcuts are methods to be intercepted by AOP and Advisors link pointcuts to interceptor implementations:
public class FileIntPerformanceMonitorInterceptor extends AbstractMonitoringInterceptor {
    
    /**
	 * 
	 */
	private static final long serialVersionUID = 8725998668272240895L;

	public FileIntPerformanceMonitorInterceptor() {
    }
 
    public FileIntPerformanceMonitorInterceptor(boolean useDynamicLogger) {
            setUseDynamicLogger(useDynamicLogger);
    }
 
    @Override
    protected Object invokeUnderTrace(MethodInvocation invocation, Log log) 
      throws Throwable {
        String name = createInvocationTraceName(invocation);
        long start = System.currentTimeMillis();
        log.info("Method " + name + " execution started at:" + new Date());
        try {
            return invocation.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());
             
            if (time > 10){
                log.warn("Method execution longer than 10 ms!");
            }            
        }
    }
}

Make sure to use correct aspectj versions in your pom:

	<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>1.7.0</version>
		</dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.7.0</version>
		</dependency>
  • Log4j Logging level has to be at TRACE for the logs to show up.

resettable timer pattern

Recently I undertook the task of refactoring batch processing at work. The jobs followed a similar pattern of records get staged, messages are sent and the stage status is updated for each message. This causes numerous DB connections to be opened up for every message and doing updates in separate threads seemed like a waste of time to me.

This made me think about batch updates and a pattern where a single thread does all the updates when the process finishes. The important point here is knowing when the process has finished. For me that was when no message has been sent for an arbitrary amount of time. Implementing the below interface did the trick for me:

Spring AOP configuration:

public abstract class ResettableTimer implements Runnable {

    protected Object lock = new Object();
    private long timeout_ms;
    private long last;
    volatile boolean shutdown = false;

    public ResettableTimer(long timeout_ms) {
        this.timeout_ms = timeout_ms;
    }

    public void reset() {
        synchronized (lock) {
            last = System.currentTimeMillis();
            lock.notify();
        }
    }

    @Override
    public void run() {
        try {
            synchronized (lock) {
                while(true) {
                    lock.wait(timeout_ms);
                    long delta = System.currentTimeMillis() - last;
                    if (delta >= timeout_ms) {
                        timeout();
                        lock.notify();
                    }
                }
            }
        } catch (InterruptedException e) {
        }
    }

    protected abstract void timeout();
}

Jenkins delete builds

I recently ran into a situation where Jenkins upstream jobs screwed up and my downstream jobs started building every branch in Git. I had to fix the issue and then try to clear up the builds. Thankfully the Jenkins community is aware of these issues and they provided a CLI to play with the jenkins environment:

Access the CLI at:

<jenkins url>/jnlpJars/jenkins-cli.jar

Then run the below command:

PS C:\Users\kkrishnan\Downloads> java -jar jenkins-cli.jar -s <jenkins url> delete-builds <job name> 418-454 --
username xxxxx --password xxxxxx

There is a bug with the above where it throws the ‘no job found error'. To fix this we have to give the anonymous user discover and read access for jobs under Jenkins Global security configuration.

git split commits

We have all made commits which included “experimental” stuff. Suppose you run into this situation and want to split your commit into multiple commits:

git rebase -i HEAD~<as far back as the commit is, for most recent commit :1>
mark commit as edit in the rebase screen
git add + commit to create different commits
git rebase --continue

git reorder commits

Say you committed some code, then committed some experimental stuff on top of that and went back to the original commit and changed some stuff. Totally normal situation. Now you want to submit a merge request, but only for the completely baked code. One solution is to re-order commits and squash the commits you want to merge into your cherry picked commit:

Below is my JPA repository:

git rebase -i HEAD~<as many commits back as you need to go>
in the interactive screen, re-order the picks
git push origin --force