Implements a moving average function windowed on either the number of data points or a unit of time. @since 2.3
| 35 | * @since 2.3 |
| 36 | */ |
| 37 | public class MovingAverage implements Expression { |
| 38 | |
| 39 | @Override |
| 40 | public DataPoints[] evaluate(final TSQuery data_query, |
| 41 | final List<DataPoints[]> query_results, final List<String> params) { |
| 42 | if (data_query == null) { |
| 43 | throw new IllegalArgumentException("Missing time series query"); |
| 44 | } |
| 45 | if (query_results == null || query_results.isEmpty()) { |
| 46 | return new DataPoints[]{}; |
| 47 | } |
| 48 | if (params == null || params.isEmpty()) { |
| 49 | throw new IllegalArgumentException("Missing moving average window size"); |
| 50 | } |
| 51 | |
| 52 | String param = params.get(0); |
| 53 | if (param == null || param.isEmpty()) { |
| 54 | throw new IllegalArgumentException("Missing moving average window size"); |
| 55 | } |
| 56 | param = param.trim(); |
| 57 | |
| 58 | long condition = -1; |
| 59 | boolean is_time_unit = false; |
| 60 | if (param.matches("^[0-9]+$")) { |
| 61 | try { |
| 62 | condition = Integer.parseInt(param); |
| 63 | } catch (NumberFormatException nfe) { |
| 64 | throw new IllegalArgumentException( |
| 65 | "Invalid parameter, must be an integer", nfe); |
| 66 | } |
| 67 | } else if (param.startsWith("'") && param.endsWith("'")) { |
| 68 | condition = parseParam(param); |
| 69 | is_time_unit = true; |
| 70 | } else { |
| 71 | throw new IllegalArgumentException("Unparseable window size: " + param); |
| 72 | } |
| 73 | if (condition <= 0) { |
| 74 | throw new IllegalArgumentException("Moving average window must be an " |
| 75 | + "integer greater than zero"); |
| 76 | } |
| 77 | |
| 78 | int num_results = 0; |
| 79 | for (final DataPoints[] results : query_results) { |
| 80 | num_results += results.length; |
| 81 | } |
| 82 | |
| 83 | final PostAggregatedDataPoints[] post_agg_results = |
| 84 | new PostAggregatedDataPoints[num_results]; |
| 85 | int ix = 0; |
| 86 | // one or more queries (m=...&m=...&m=...) |
| 87 | for (final DataPoints[] sub_query_result : query_results) { |
| 88 | // group bys (m=sum:foo{host=*}) |
| 89 | for (final DataPoints dps: sub_query_result) { |
| 90 | // TODO(cl) - Avoid iterating and copying if we can help it. We should |
| 91 | // be able to pass the original DataPoints object to the seekable view |
| 92 | // and then iterate through it. |
| 93 | final List<DataPoint> mutable_points = new ArrayList<DataPoint>(); |
| 94 | for (final DataPoint point: dps) { |
nothing calls this directly
no outgoing calls
no test coverage detected
searching dependent graphs…