Requirements
Create a CMR component that will be able to aggregate TimerData objects that are coming from the Agent (both in and outside an invocation) and persists only aggregated data to the database. The aggregation period should be specified in the configuration.
Approach
The Aggregator should hold limited number of aggregation objects, where every aggregation object is created as a copy of original TimerData object and a modified time stamp. If the aggregation period is for example 10s, for each method ident, a aggregation objects should have the time stamps like 12:50:10, 12:50:20, etc, so in the 10 seconds difference. When the new TimerData comes to the Aggregator, the Aggregator checks if the aggregation object for the arriving TimerData is already created. If yes, it simply adds the information from incoming TimerData to the aggregation objects, otherwise, it creates a new aggregation object as described above.
The persistence of objects is done in two ways. First is when the number of aggregation objects is higher than Aggregator's limit, by creating a persistence list from oldest objects and persisting set of "old" objects at the same time. Second is when there is no activity for a specified time period, thus assuming that there is no data coming from the agent any more, Aggregator should persist all aggregation objects that are currently present.
Realization
The implementation is done in class info.novatec.inspectit.cmr.dao.impl.TimerDataAggregator. This class is initialized by Spring with three property values:
Property | Description |
---|---|
aggregationPeriod | Time in milliseconds that defines the aggregation period. |
maxElements | Maximum of aggregated objects that should be kept by Aggregator. |
cacheCleanSleepingPeriod | Time in milliseconds that thread that is cleaning the Aggregator's cache should sleep. |
The Aggregator has three concurrent collections:
1. ConcurrentHashMap for caching the aggregation objects by time stamp and method ident hash combination, and it's fast retrieval.
2. ConcurrentLinkedQueue to keep FIFO order of aggregation objects, so when the number of elements reaches maximum, First In object can be drooped out from both cache map and this list.
3. ConcurrentLinkedQueue (2) for keeping the aggregation objects that are drooped out from Aggregator and are ready for persistence.
The persistence is done by a inner Thread class CacheCleaner. This thread runs occasionally (sleep is defined by cacheCleanSleepingPeriod property) and checks if there was some activity in Aggregator (if new TimerData objects where coming for aggregation). If not, it will persist all the objects in the Aggregator. Furthermore, in every run it will anyway persist all objects that are in persist list.
Testing
Testing of Aggregator is performed in class info.novatec.inspectit.cmr.dao.test.TimerDataAggregatorTest with following tests:
Test | Description |
---|---|
testAggregation | Tests for the validity of aggregation. |
testNoSetterInteractions | Verifies the zero interactions with setters of TimerData object passed to the Aggregator. |