I did something similar once. If I remember well, I had something like
public class StatisticsFilter implements ...
{
public static Statistics stats;
public class PeriodicDumpStat extends Thread
{
...
}
public void doFilter(ServletRequest request, ...()
{
long start = System.currentTimeMillis();
chain.doFilter(request, response);
long stop = System.currentTimeMillis();
stats.add( stop - start );
}
public void init()
{
Thread t = new PeriodicDumpStat();
t.setDaemon( true );
t.start();
}
}
(That's only a sketch)
Make sure that the Statistics
object is correctly synchronize, as it will be accessed concurrently.
I had a background DumpStatistics
thread that was periodically dumping the stats in an XML file, to be processed later. For better encapsulation, I had the thread as an inner class. You can of course use Runnable
as well. As @Trevor Tippins pointed out, it's also good to flag the thread as daemon thread.
I also used Google Chart and had actually another ShowStatisticsServlet
that would rad the XML file and turn the data into a nice Chart. The servlet would not depends on the filter, but only on the XML file, so both were actually decoupled. The XML file can be created as a temporary file with File.createTempFile
. (Another variant would be of course to keep all data in memory, but storing the data was handy for us to backup the results of perf. tests and analyze them later)
Some colleague claimed that the synchronization in the Statistics
object would "kill" the app performance, but in practice it was really neglectable. The overhead to dump the file as well, given that it was done each 10 sec or so.
Hope it helps, or give you some ideas.
PS: And as @William Louth commented, you should write such infrastructure code only if you can't solve your issue with an existing solution. In my case, I was also benchmarking the internal time of my code, not only the complete request processing time.