graphite-dev team mailing list archive
-
graphite-dev team
-
Mailing list archive
-
Message #02139
[Merge] lp:~kenshi/graphite/moving_median into lp:graphite
Ken has proposed merging lp:~kenshi/graphite/moving_median into lp:graphite.
Requested reviews:
graphite-dev (graphite-dev)
For more details, see:
https://code.launchpad.net/~kenshi/graphite/moving_median/+merge/93164
Added a moving median function to the list of available render functions. This is useful for data that are susceptible to outliers.
--
https://code.launchpad.net/~kenshi/graphite/moving_median/+merge/93164
Your team graphite-dev is requested to review the proposed merge of lp:~kenshi/graphite/moving_median into lp:graphite.
=== modified file 'webapp/content/js/composer_widgets.js'
--- webapp/content/js/composer_widgets.js 2012-02-13 06:55:34 +0000
+++ webapp/content/js/composer_widgets.js 2012-02-15 09:47:18 +0000
@@ -908,6 +908,7 @@
{text: 'Holt-Winters Forecast', handler: this.applyFuncToEach('holtWintersForecast')},
{text: 'Holt-Winters Confidence Bands', handler: this.applyFuncToEach('holtWintersConfidenceBands')},
{text: 'Holt-Winters Aberration', handler: this.applyFuncToEach('holtWintersAberration')},
+ {text: 'Moving Median', handler: applyFuncToEachWithInput('movingMedian', 'Moving median for the last ___ data points')},
{text: 'As Percent', handler: applyFuncToEachWithInput('asPercent', 'Please enter the value that corresponds to 100%')},
{text: 'Difference (of 2 series)', handler: applyFuncToAll('diffSeries')},
{text: 'Ratio (of 2 series)', handler: applyFuncToAll('divideSeries')}
=== modified file 'webapp/graphite/render/functions.py'
--- webapp/graphite/render/functions.py 2012-02-08 23:00:15 +0000
+++ webapp/graphite/render/functions.py 2012-02-15 09:47:18 +0000
@@ -281,7 +281,7 @@
Example:
.. code-block:: none
-
+
&target=rangeOfSeries(Server*.connections.total)
"""
@@ -378,6 +378,41 @@
step = reduce(lcm,[s.step for s in bothSeries])
for s in bothSeries:
+def movingMedian(requestContext, seriesList, windowSize):
+ """
+ Takes one metric or a wildcard seriesList followed by a number N of datapoints and graphs
+ the median of N previous datapoints. N-1 datapoints are set to None at the
+ beginning of the graph.
+
+ .. code-block:: none
+
+ &target=movingMedian(Server.instance01.threads.busy,10)
+
+ """
+ for seriesIndex, series in enumerate(seriesList):
+ newName = "movingMedian(%s,%.1f)" % (series.name, float(windowSize))
+ newSeries = TimeSeries(newName, series.start, series.end, series.step, [])
+ newSeries.pathExpression = newName
+
+ windowIndex = windowSize - 1
+
+ for i in range( len(series) ):
+ if i < windowIndex: # Pad the beginning with None's since we don't have enough data
+ newSeries.append( None )
+
+ else:
+ window = series[i - windowIndex : i + 1]
+ nonNull = [ v for v in window if v is not None ]
+ if nonNull:
+ m_index = len(nonNull) / 2
+ newSeries.append(sorted(nonNull)[m_index])
+ else:
+ newSeries.append(None)
+
+ seriesList[ seriesIndex ] = newSeries
+
+ return seriesList
+
s.consolidate( step / s.step )
start = min([s.start for s in bothSeries])
@@ -2099,6 +2134,7 @@
# Calculate functions
'movingAverage' : movingAverage,
+ 'movingMedian' : movingMedian,
'stdev' : stdev,
'holtWintersForecast': holtWintersForecast,
'holtWintersConfidenceBands': holtWintersConfidenceBands,