diff --git a/webapp/graphite/render/views.py b/webapp/graphite/render/views.py index 186232ed7..8f17aaa64 100644 --- a/webapp/graphite/render/views.py +++ b/webapp/graphite/render/views.py @@ -12,6 +12,7 @@ See the License for the specific language governing permissions and limitations under the License.""" import csv +import math from datetime import datetime from time import time from random import shuffle @@ -128,10 +129,34 @@ def renderView(request): if format == 'json': series_data = [] - for series in data: - timestamps = range(series.start, series.end, series.step) - datapoints = zip(series, timestamps) - series_data.append( dict(target=series.name, datapoints=datapoints) ) + if 'maxDataPoints' in requestOptions and any(data): + startTime = min([series.start for series in data]) + endTime = max([series.end for series in data]) + timeRange = endTime - startTime + maxDataPoints = requestOptions['maxDataPoints'] + for series in data: + numberOfDataPoints = timeRange/series.step + if maxDataPoints < numberOfDataPoints: + valuesPerPoint = math.ceil(float(numberOfDataPoints) / float(maxDataPoints)) + secondsPerPoint = int(valuesPerPoint * series.step) + # Nudge start over a little bit so that the consolidation bands align with each call + # removing 'jitter' seen when refreshing. + nudge = secondsPerPoint + (series.start % series.step) - (series.start % secondsPerPoint) + series.start = series.start + nudge + valuesToLose = int(nudge/series.step) + for r in range(1, valuesToLose): + del series[0] + series.consolidate(valuesPerPoint) + timestamps = range(series.start, series.end, secondsPerPoint) + else: + timestamps = range(series.start, series.end, series.step) + datapoints = zip(series, timestamps) + series_data.append(dict(target=series.name, datapoints=datapoints)) + else: + for series in data: + timestamps = range(series.start, series.end, series.step) + datapoints = zip(series, timestamps) + series_data.append( dict(target=series.name, datapoints=datapoints) ) if 'jsonp' in requestOptions: response = HttpResponse( @@ -230,6 +255,8 @@ def parseOptions(request): requestOptions['jsonp'] = queryParams['jsonp'] if 'noCache' in queryParams: requestOptions['noCache'] = True + if 'maxDataPoints' in queryParams and queryParams['maxDataPoints'].isdigit(): + requestOptions['maxDataPoints'] = int(queryParams['maxDataPoints']) requestOptions['localOnly'] = queryParams.get('local') == '1'