Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
add derive instrument
  • Loading branch information
cyberdelia committed Oct 23, 2012
1 parent ae17368 commit cbde378
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 1 deletion.
7 changes: 7 additions & 0 deletions docs/instruments.rst
Expand Up @@ -17,6 +17,13 @@ Counters
.. automodule:: metrology.instruments.counter
:members:

Derive
======

.. automodule:: metrology.instruments.derive
:members:


Meters
======

Expand Down
4 changes: 4 additions & 0 deletions metrology/__init__.py
Expand Up @@ -10,6 +10,10 @@ def get(cls, name):
def counter(cls, name):
return registry.counter(name)

@classmethod
def derive(cls, name):
return registry.derive(name)

@classmethod
def meter(cls, name):
return registry.meter(name)
Expand Down
1 change: 1 addition & 0 deletions metrology/instruments/__init__.py
@@ -1,5 +1,6 @@
# -*- flake8: noqa -*-
from metrology.instruments.counter import Counter
from metrology.instruments.derive import Derive
from metrology.instruments.gauge import Gauge
from metrology.instruments.histogram import Histogram, HistogramUniform, HistogramExponentiallyDecaying
from metrology.instruments.meter import Meter
Expand Down
28 changes: 28 additions & 0 deletions metrology/instruments/derive.py
@@ -0,0 +1,28 @@
from atomic import Atomic

from metrology.instruments.meter import Meter
from metrology.stats import EWMA


class Derive(Meter):
"""
A derive is like a meter but accepts an absolute counter as input.
derive = Metrology.derive('network.io')
derive.mark()
derive.count
"""
def __init__(self, average_class=EWMA):
self.last = Atomic(0)
super(Derive, self).__init__(average_class)

def mark(self, value=1):
"""Record an event with the derive.
:param value: counter value to record
"""
last = self.last.get_and_set(value)
if last <= value:
value = value - last
super(Derive, self).mark(value)
5 changes: 4 additions & 1 deletion metrology/registry.py
Expand Up @@ -3,7 +3,7 @@
from threading import RLock

from metrology.exceptions import RegistryException
from metrology.instruments import Counter, Profiler, Meter, Timer, UtilizationTimer, HistogramUniform
from metrology.instruments import Counter, Derive, Profiler, Meter, Timer, UtilizationTimer, HistogramUniform


class Registry(object):
Expand Down Expand Up @@ -41,6 +41,9 @@ def histogram(self, name, klass=None):
klass = HistogramUniform
return self.add_or_get(name, klass)

def derive(self, name):
return self.add_or_get(name, Derive)

def profiler(self, name):
return self.add_or_get(name, Profiler)

Expand Down
28 changes: 28 additions & 0 deletions tests/instruments/test_derive.py
@@ -0,0 +1,28 @@
from unittest import TestCase

from metrology.instruments.derive import Derive


class DeriveTest(TestCase):
def setUp(self):
self.derive = Derive()

def test_derive(self):
self.derive.mark()
self.assertEqual(1, self.derive.count)

def test_blank_derive(self):
self.assertEqual(0, self.derive.count)
self.assertEqual(0.0, self.derive.mean_rate)

def test_derive_value(self):
self.derive.mark(3)
self.assertEqual(3, self.derive.count)

def test_one_minute_rate(self):
self.derive.mark(1000)
self.derive.tick()
self.assertEqual(200, self.derive.one_minute_rate)

def tearDown(self):
self.derive.stop()

0 comments on commit cbde378

Please sign in to comment.