/** * Create a list with histogram results that would be serialized to JSON like this * * <p>[{ x: -1893456000, y: 92228531 }, { x: -1577923200, y: 106021568 }] */ protected List<Map<String, Long>> formatHistogramResults( DateHistogramResult histogram, int maxDataPoints, boolean allQuery) { final List<Map<String, Long>> points = Lists.newArrayList(); final Map<String, Long> histogramResults = histogram.getResults(); DateTime from; if (allQuery) { String firstTimestamp = histogramResults.entrySet().iterator().next().getKey(); from = new DateTime(Long.parseLong(firstTimestamp) * 1000, DateTimeZone.UTC); } else { from = DateTime.parse(histogram.getHistogramBoundaries().getFrom()); } final DateTime to = DateTime.parse(histogram.getHistogramBoundaries().getTo()); final MutableDateTime currentTime = new MutableDateTime(from); final Duration step = estimateIntervalStep(histogram.getInterval()); final int dataPoints = (int) ((to.getMillis() - from.getMillis()) / step.getMillis()); // using the absolute value guarantees, that there will always be enough values for the given // resolution final int factor = (maxDataPoints != -1 && dataPoints > maxDataPoints) ? dataPoints / maxDataPoints : 1; int index = 0; floorToBeginningOfInterval(histogram.getInterval(), currentTime); while (currentTime.isBefore(to) || currentTime.isEqual(to)) { if (index % factor == 0) { String timestamp = Long.toString(currentTime.getMillis() / 1000); Long result = histogramResults.get(timestamp); Map<String, Long> point = Maps.newHashMap(); point.put("x", Long.parseLong(timestamp)); point.put("y", result != null ? result : 0); points.add(point); } index++; nextStep(histogram.getInterval(), currentTime); } return points; }
public Result histogram( String q, String rangeType, int relative, String from, String to, String keyword, String interval, String streamId, int maxDataPoints) { if (q == null || q.isEmpty()) { q = "*"; } // Interval. if (interval == null || interval.isEmpty() || !SearchTools.isAllowedDateHistogramInterval(interval)) { interval = "minute"; } // Determine timerange type. TimeRange timerange; try { timerange = TimeRange.factory(rangeType, relative, from, to, keyword); } catch (InvalidRangeParametersException e2) { return status( 400, views.html.errors.error.render("Invalid range parameters provided.", e2, request())); } catch (IllegalArgumentException e1) { return status( 400, views.html.errors.error.render("Invalid range type provided.", e1, request())); } String filter = null; if (streamId != null && !streamId.isEmpty()) { filter = "streams:" + streamId; } try { UniversalSearch search = searchFactory.queryWithRangeAndFilter(q, timerange, filter); DateHistogramResult histogram = search.dateHistogram(interval); List<Map<String, Long>> results = formatHistogramResults(histogram, maxDataPoints, relative == 0); Map<String, Object> result = Maps.newHashMap(); AbsoluteRange boundaries = histogram.getHistogramBoundaries(); result.put("time", histogram.getTookMs()); result.put("interval", histogram.getInterval()); result.put("values", results); result.put("from", boundaries.getFrom()); result.put("to", boundaries.getTo()); return ok(Json.toJson(result)); } catch (IOException e) { return internalServerError("io exception"); } catch (APIException e) { if (e.getHttpCode() == 400) { // This usually means the field does not have a numeric type. Pass through! return badRequest(); } return internalServerError("api exception " + e); } }