in ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/aggregators/AggregatorUtils.java [139:219]
private static Map<Long, Double> interpolateMissingPeriods(TreeMap<Long, Double> metricValues,
List<Long[]> timeSlices,
Map<Long, Double> timeSliceValueMap, String type) {
Map<Long, Double> resultClusterMetricMap = new HashMap<>();
if (StringUtils.isNotEmpty(type) && "COUNTER".equalsIgnoreCase(type)) {
//For Counter Based metrics, ok to do interpolation and extrapolation
List<Long> requiredTimestamps = new ArrayList<>();
for (Long[] timeSlice : timeSlices) {
if (!timeSliceValueMap.containsKey(timeSlice[1])) {
requiredTimestamps.add(timeSlice[1]);
}
}
Map<Long, Double> interpolatedValuesMap = PostProcessingUtil.interpolate(metricValues, requiredTimestamps);
if (interpolatedValuesMap != null) {
for (Map.Entry<Long, Double> entry : interpolatedValuesMap.entrySet()) {
Double interpolatedValue = entry.getValue();
if (interpolatedValue != null) {
resultClusterMetricMap.put( entry.getKey(), interpolatedValue);
} else {
LOG.debug("Cannot compute interpolated value, hence skipping.");
}
}
}
} else {
//For other metrics, ok to do only interpolation
Double defaultNextSeenValue = null;
if (MapUtils.isEmpty(timeSliceValueMap) && MapUtils.isNotEmpty(metricValues)) {
//If no value was found within the start_time based slices, but the metric has value in the server_time range,
// use that.
Map.Entry<Long,Double> firstEntry = metricValues.firstEntry();
defaultNextSeenValue = firstEntry.getValue();
LOG.debug("Found a data point outside timeslice range: " + new Date(firstEntry.getKey()) + ": " + defaultNextSeenValue);
}
for (int sliceNum = 0; sliceNum < timeSlices.size(); sliceNum++) {
Long[] timeSlice = timeSlices.get(sliceNum);
if (!timeSliceValueMap.containsKey(timeSlice[1])) {
LOG.debug("Found an empty slice : " + new Date(timeSlice[0]) + ", " + new Date(timeSlice[1]));
Double lastSeenValue = null;
int index = sliceNum - 1;
Long[] prevTimeSlice = null;
while (lastSeenValue == null && index >= 0) {
prevTimeSlice = timeSlices.get(index--);
lastSeenValue = timeSliceValueMap.get(prevTimeSlice[1]);
}
Double nextSeenValue = null;
index = sliceNum + 1;
Long[] nextTimeSlice = null;
while (nextSeenValue == null && index < timeSlices.size()) {
nextTimeSlice = timeSlices.get(index++);
nextSeenValue = timeSliceValueMap.get(nextTimeSlice[1]);
}
if (nextSeenValue == null) {
nextSeenValue = defaultNextSeenValue;
}
Double interpolatedValue = PostProcessingUtil.interpolate(timeSlice[1],
(prevTimeSlice != null ? prevTimeSlice[1] : null), lastSeenValue,
(nextTimeSlice != null ? nextTimeSlice[1] : null), nextSeenValue);
if (interpolatedValue != null) {
LOG.debug("Interpolated value : " + interpolatedValue);
resultClusterMetricMap.put(timeSlice[1], interpolatedValue);
} else {
LOG.debug("Cannot compute interpolated value, hence skipping.");
}
}
}
}
return resultClusterMetricMap;
}