use of net.opentsdb.query.expression.HighestMax.TopNSortingEntry in project opentsdb by OpenTSDB.
the class HighestCurrent method evaluate.
@Override
public DataPoints[] evaluate(final TSQuery data_query, final List<DataPoints[]> query_results, final List<String> params) {
if (data_query == null) {
throw new IllegalArgumentException("Missing time series query");
}
if (query_results == null || query_results.isEmpty()) {
return new DataPoints[] {};
}
// TODO(cl) - allow for empty top-n maybe? Just sort the results by max?
if (params == null || params.isEmpty()) {
throw new IllegalArgumentException("Need aggregation window for moving average");
}
String param = params.get(0);
if (param == null || param.length() == 0) {
throw new IllegalArgumentException("Missing top n value " + "(number of series to return)");
}
int topn = 0;
if (param.matches("^[0-9]+$")) {
try {
topn = Integer.parseInt(param);
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException("Invalid parameter, must be an integer", nfe);
}
} else {
throw new IllegalArgumentException("Unparseable top n value: " + param);
}
if (topn < 1) {
throw new IllegalArgumentException("Top n value must be greater " + "than zero: " + topn);
}
int num_results = 0;
for (DataPoints[] results : query_results) {
num_results += results.length;
}
final PostAggregatedDataPoints[] post_agg_results = new PostAggregatedDataPoints[num_results];
int ix = 0;
// one or more sub queries (m=...&m=...&m=...)
for (final DataPoints[] sub_query_result : query_results) {
// group bys (m=sum:foo{host=*})
for (final DataPoints dps : sub_query_result) {
// TODO(cl) - Avoid iterating and copying if we can help it. We should
// be able to pass the original DataPoints object to the seekable view
// and then iterate through it.
final List<DataPoint> mutable_points = new ArrayList<DataPoint>();
for (final DataPoint point : dps) {
mutable_points.add(point.isInteger() ? MutableDataPoint.ofLongValue(point.timestamp(), point.longValue()) : MutableDataPoint.ofDoubleValue(point.timestamp(), point.doubleValue()));
}
post_agg_results[ix++] = new PostAggregatedDataPoints(dps, mutable_points.toArray(new DataPoint[mutable_points.size()]));
}
}
final SeekableView[] views = new SeekableView[num_results];
for (int i = 0; i < num_results; i++) {
views[i] = post_agg_results[i].iterator();
}
final MaxLatestAggregator aggregator = new MaxLatestAggregator(Aggregators.Interpolation.LERP, "maxLatest", num_results, data_query.startTime(), data_query.endTime());
final SeekableView view = (new AggregationIterator(views, data_query.startTime(), data_query.endTime(), aggregator, Aggregators.Interpolation.LERP, false));
// slurp all the points even though we aren't using them at this stage
while (view.hasNext()) {
final DataPoint mdp = view.next();
@SuppressWarnings("unused") final Object o = mdp.isInteger() ? mdp.longValue() : mdp.doubleValue();
}
final long[] max_longs = aggregator.getLongMaxes();
final double[] max_doubles = aggregator.getDoubleMaxes();
final TopNSortingEntry[] max_by_ts = new TopNSortingEntry[num_results];
if (aggregator.hasDoubles() && aggregator.hasLongs()) {
for (int i = 0; i < num_results; i++) {
max_by_ts[i] = new TopNSortingEntry(Math.max((double) max_longs[i], max_doubles[i]), i);
}
} else if (aggregator.hasLongs() && !aggregator.hasDoubles()) {
for (int i = 0; i < num_results; i++) {
max_by_ts[i] = new TopNSortingEntry((double) max_longs[i], i);
}
} else if (aggregator.hasDoubles() && !aggregator.hasLongs()) {
for (int i = 0; i < num_results; i++) {
max_by_ts[i] = new TopNSortingEntry(max_doubles[i], i);
}
}
Arrays.sort(max_by_ts);
final int result_count = Math.min(topn, num_results);
final DataPoints[] results = new DataPoints[result_count];
for (int i = 0; i < result_count; i++) {
results[i] = post_agg_results[max_by_ts[i].pos];
}
return results;
}
Aggregations