I am using DescriptiveStatistics to track the moving average of some metrics. I have a thread that submits the metric value every minute, and I track the 10 minute moving average of the metric by using the setWindowSize(10)
method on DescriptiveStatistics.
This works fine for tracking a single moving average but I actually need to track multiple moving averages, i.e. the 1 minute average, the 5 minute average, and the 10 minute average.
Currently I have the following options:
Have 3 different DescriptiveStatistics instances with 3 different windows. However, this means we store the raw metrics multiple times which is not ideal.
Have 1 instance of DescriptiveStatistics and do something like the following when querying for a moving average:
int minutes = <set from parameter>; DescriptiveStatistics stats = <class variable>; if (minutes == stats.getN()) return stats.getMean(); SummaryStatistics subsetStats = new SummaryStatistics(); for (int i = 0; i < minutes; i++) { subsetStats.addValue(stats.getElement((int)stats.getN() - i - 1)); } return subsetStats.getMean();
However, option 2 means that I have to re-compute a bunch of averages every time I query for a moving average whose window is smaller than the DescriptiveStats window size.
Is there a way to do this better? I want to store 1 copy of the metrics data and continually calculate N moving averages of it with different intervals. This might be getting into the land of Codahale Metrics or Netflix Servo, but I don't want to have to use a heavyweight library just for this.
You could use
StatUtils
utility class and manage the array when adding new values. One alternative is to useCircularFifoQueue
of Apache Commons with a size of 10 and Apache Utils to simplify the conversion to array of primitive values.You can find an example of
StatUtils
in the User Guide, the following would be something similar to your use case.