Skip to content

Instantly share code, notes, and snippets.

@mleinart
Created February 28, 2012 16:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mleinart/1933383 to your computer and use it in GitHub Desktop.
Save mleinart/1933383 to your computer and use it in GitHub Desktop.
asPercent patch for graphite 0.9.9
=== modified file 'webapp/graphite/render/functions.py'
--- webapp/graphite/render/functions.py 2011-10-04 21:06:09 +0000
+++ webapp/graphite/render/functions.py 2012-02-28 16:05:35 +0000
@@ -225,44 +225,49 @@
series[i] = value
return seriesList
-def asPercent(requestContext, seriesList1, seriesList2orNumber):
+def asPercent(requestContext, seriesList, total=None):
"""
- Takes exactly two metrics, or a metric and a constant.
- Draws the first metric as a percent of the second.
+
+ Calculates a percentage of the total of a wildcard series. If `total` is specified,
+ each series will be calculated as a percentage of that total. If `total` is not specified,
+ the sum of all points in the wildcard series will be used instead.
+
+ The `total` parameter may be a single series or a numeric value.
Example:
.. code-block:: none
- &target=asPercent(Server01.connections.failed,Server01.connections,total)
+ &target=asPercent(Server01.connections.{failed,succeeded}, Server01.connections.attempted)
&target=asPercent(apache01.threads.busy,1500)
+ &target=asPercent(Server01.cpu.*.jiffies)
"""
- assert len(seriesList1) == 1, "asPercent series arguments must reference *exactly* 1 series"
- series1 = seriesList1[0]
- if type(seriesList2orNumber) is list:
- assert len(seriesList2orNumber) == 1, "asPercent series arguments must reference *exactly* 1 series"
- series2 = seriesList2orNumber[0]
- name = "asPercent(%s,%s)" % (series1.name,series2.name)
- series = (series1,series2)
- step = reduce(lcm,[s.step for s in series])
- for s in series:
- s.consolidate( step / s.step )
- start = min([s.start for s in series])
- end = max([s.end for s in series])
- end -= (end - start) % step
- values = ( safeMul( safeDiv(v1,v2), 100.0 ) for v1,v2 in izip(*series) )
+
+ normalize([seriesList])
+
+ if total is None:
+ totalValues = [ safeSum(row) for row in izip(*seriesList) ]
+ totalText = None # series.pathExpression
+ elif type(total) is list:
+ if len(total) != 1:
+ raise ValueError("asPercent second argument must reference exactly 1 series")
+ normalize([seriesList, total])
+ totalValues = total[0]
+ totalText = totalValues.name
else:
- number = float(seriesList2orNumber)
- name = "asPercent(%s,%.1f)" % (series1.name,number)
- step = series1.step
- start = series1.start
- end = series1.end
- values = ( safeMul( safeDiv(v,number), 100.0 ) for v in series1 )
- series = TimeSeries(name,start,end,step,values)
- series.pathExpression = name
- return [series]
-
+ totalValues = [total] * len(seriesList[0])
+ totalText = str(total)
+
+ resultList = []
+ for series in seriesList:
+ resultValues = [ safeMul(safeDiv(val, totalVal), 100.0) for val,totalVal in izip(series,totalValues) ]
+
+ name = "asPercent(%s, %s)" % (series.name, totalText or series.pathExpression)
+ resultSeries = TimeSeries(name,series.start,series.end,series.step,resultValues)
+ resultList.append(resultSeries)
+
+ return resultList
def divideSeries(requestContext, dividendSeriesList, divisorSeriesList):
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment