When running Spring Batch in production it’s always good to keep an eye on performance. And in pre-production it’s helpful to have a tool that points to the weak spots. One option you have is to use Application Performance Management (APM) tools, and one of them is AppDynamics. In this post I describe how you need to configure AppDynamics to efficiently monitor Spring Batch jobs.
AppDynamics has the concept of business transactions that you monitor. Business transactions have an entry point, and everything that happens afterwards belongs to the transaction, in our case it’s a call graph of Java objects, some SQL communication with a database and optionally other resources that may be accessed.
There are different possibilities to define entry points for a transaction, one very common entry point is a Servlet for web applications. AppDynamics is able to autodetect different business transactions for different types of entry points.
For each business transaction type AppDynamics collects data depending on your configuration. In general it counts the number of calls and measures the time needed for it. If there are some calls that are very slow it starts a diagnostic session and records call graphs for the calls. And even without slow calls AppDynamics records a call graph here and there. You can even see the SQL statements made during the call.
A business transaction for Spring Batch
So, what is a good business transaction in batch processing? If our batch program is started by a web request, we could define this request as the entry point of our business transaction. Is that a good choice? A call would then span the whole batch job execution, and that’s a bad idea. Just think of the possible call graph, it would be really really big if AppDynamics wouldn’t cut it anyway. And we cannot compare performance if we just get one call per week (or how often your batch job runs).
A better choice is having the execution of a tasklet as a business transaction. Implementations of the interface
org.springframework.batch.core.step.tasklet.Tasklet are responsible for processings inside a step. Its method execute is called as long as it returns
RepeatStatus.CONTINUABLE, and each call is done in its own transaction. If you’re now asking yourself what the
Tasklet has to do with your batch job, because you’re only using chunk based processing: There’s the implementation
ChunkOrientedTasklet, which is used whenever you do chunk based processing, so even then the interface
Tasklet is an adequate entry point for monitoring.
One more thing to think about: if we configure a business transaction for the interface
Tasklet we cannot tell for which kind of batch job the tasklet was run. We need to find a way to distinguish between different jobs. And we will, as you can see in the next paragraph.
How to configure the business transaction
We will configure a POJO business transaction. Click Configure -> Instrumentation and select your application. If you’re not on the tab ‘Transaction Detection’, switch to it. Scroll down to ‘Custom Rules’ and hit the ‘+’ button to add a custom match rule.
Choose ‘POJO’ as the Entry Point type, then choose a name for the transaction. In the tab ‘Transaction Match Criteria’ choose ‘Match Classes that implements an Interface which Equals
org.springframework.batch.core.step. tasklet.Tasklet‘. As ‘Method Name’ type in ‘
If we would leave the transaction definition like that, we could not tell which call is for which job. We definitely want different transaction definitions for different jobs. We can accomplish this via ‘Transaction Splitting’, so switch to the tab with the same name. Check ‘Split POJO Transactions using one of the following mechanisms…’, then check ‘Use a method parameter to name Transactions’. The second parameter of the
execute method is the
ChunkContext, and if we call
getStepContext().getJobName() on it, we get the job name, which would be a perfect discriminator for our business transaction. So we choose ‘1’ as ‘Parameter Index’ and ‘
getStepContext().getJobName()‘ as ‘Getter Chain to run on method parameter’.
Then click on the ‘Save’ button and restart the batch server.
An even better choice?
If you’re using
Tasklet‘s execute method as the entry point to your business transaction, you don’t catch all processings that are done in one chunk. You are missing the update-methods of all
ItemStreams, you are missing the updates on Spring Batch’s meta data tables, and you are missing the actual commit of the transaction. If that’s important for you, you can choose the following ‘Transaction Match Criteria’ in your POJO configuration:
‘Match Classes that extends a Super Class that Equals
‘Method Name Equals
Since the second parameter of the
doInChunkContext method is the
ChunkContext, the ‘Transaction Splitting’ settings can stay the same as above.
Monitoring Spring Batch with AppDynamics is a good way to keep an eye on the performance of your batch jobs. I described the instrumentation you need for monitoring Spring Batch jobs, try it out!