long to,
Granularity g) {
final Timer.Context ctx = metricsFetchTimer.time();
final Locator locator = Locator.createLocatorFromPathComponents(tenantId, metricName);
final MetricData metricData = AstyanaxReader.getInstance().getDatapointsForRange(
locator,
new Range(g.snapMillis(from), to),
g);
boolean isRollable = metricData.getType().equals(MetricData.Type.NUMBER.toString())
|| metricData.getType().equals(MetricData.Type.HISTOGRAM.toString());
// if Granularity is FULL, we are missing raw data - can't generate that
if (ROLLUP_REPAIR && isRollable && g != Granularity.FULL && metricData != null) {
final Timer.Context rollupsCalcCtx = rollupsCalcOnReadTimer.time();
if (metricData.getData().isEmpty()) { // data completely missing for range. complete repair.
rollupsRepairEntireRange.mark();
List<Points.Point> repairedPoints = repairRollupsOnRead(locator, g, from, to);
for (Points.Point repairedPoint : repairedPoints) {
metricData.getData().add(repairedPoint);
}
if (repairedPoints.isEmpty()) {
rollupsRepairEntireRangeEmpty.mark();
}
} else {
long actualStart = minTime(metricData.getData());
long actualEnd = maxTime(metricData.getData());
// If the returned start is greater than 'from', we are missing a portion of data.
if (actualStart > from) {
rollupsRepairedLeft.mark();
List<Points.Point> repairedLeft = repairRollupsOnRead(locator, g, from, actualStart);
for (Points.Point repairedPoint : repairedLeft) {
metricData.getData().add(repairedPoint);
}
if (repairedLeft.isEmpty()) {
rollupsRepairedLeftEmpty.mark();
}
}
// If the returned end timestamp is less than 'to', we are missing a portion of data.
if (actualEnd + g.milliseconds() <= to) {
rollupsRepairedRight.mark();
List<Points.Point> repairedRight = repairRollupsOnRead(locator, g, actualEnd + g.milliseconds(), to);
for (Points.Point repairedPoint : repairedRight) {
metricData.getData().add(repairedPoint);
}
if (repairedRight.isEmpty()) {
rollupsRepairedRightEmpty.mark();
}
}
}
rollupsCalcCtx.stop();
}
ctx.stop();
if (g == Granularity.FULL) {
numFullPointsReturned.update(metricData.getData().getPoints().size());
} else {
numRollupPointsReturned.update(metricData.getData().getPoints().size());
}
return metricData;
}