Skip to content
This repository has been archived by the owner on Sep 4, 2019. It is now read-only.

Commit

Permalink
Merge 8c2445b into e64292f
Browse files Browse the repository at this point in the history
  • Loading branch information
jamadden committed Oct 16, 2018
2 parents e64292f + 8c2445b commit 8fae176
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 40 deletions.
3 changes: 2 additions & 1 deletion CHANGES.rst
Expand Up @@ -6,7 +6,8 @@
0.0.2 (unreleased)
==================

- Nothing changed yet.
- Metric values are now always native strings. See `issue 2
<https://github.com/NextThought/nti.fakestatsd/issues/2>`_.


0.0.1 (2018-10-12)
Expand Down
21 changes: 13 additions & 8 deletions src/nti/fakestatsd/__init__.py
Expand Up @@ -34,10 +34,10 @@ def __init__(self, name, value, sampling_rate, kind):
self.kind = kind

METRIC_TYPES = {
b'g': Gauge,
b'c': Counter,
b's': Timer,
b'ms': Timer
'g': Gauge,
'c': Counter,
's': Timer,
'ms': Timer
}

def _as_metrics(data):
Expand All @@ -49,25 +49,25 @@ def _as_metrics(data):
metrics = []

# Start by splitting newlines. this may be a multi-metric packet
for metric_data in data.split(b'\n'):
for metric_data in data.split('\n'):
sampling = None
name = None
value = None
kind = None

# Metrics take the form of <name>:<value>|<type>(|@<sampling_rate>)
parts = metric_data.split(b'|')
parts = metric_data.split('|')
if len(parts) < 2 or len(parts) > 3:
raise ValueError('Unexpected metric data %s. Wrong number of parts' % metric_data)

if len(parts) == 3:
sampling_data = parts.pop(-1)
if not sampling_data.startswith(b'@'):
if not sampling_data.startswith('@'):
raise ValueError('Expected "@" in sampling data. %s' % metric_data)
sampling = float(sampling_data[1:])

kind = parts[1]
name, value = parts[0].split(b':')
name, value = parts[0].split(':')

metrics.append(METRIC_TYPES[kind](name, value, sampling, kind))
return metrics
Expand All @@ -91,6 +91,11 @@ def __init__(self, prefix=''):

class DummySocket(object):
def sendto(self, data, addr):
# The client encoded to bytes
assert isinstance(data, bytes)
# We always want native strings here, that's what the
# user specified when calling the StatsdClient methods.
data = data.decode('utf-8') if bytes is not str else data
_raw.append((data, addr,))
for m in _as_metrics(data):
_metrics.append((m, addr,))
Expand Down
62 changes: 31 additions & 31 deletions src/nti/fakestatsd/tests/test_fakestatsd.py
Expand Up @@ -32,84 +32,84 @@
class TestStatsDParsing(unittest.TestCase):

def test_invalid_packet(self):
packet = b'junk'
packet = 'junk'
assert_that(calling(functools.partial(_as_metrics, packet)),
raises(ValueError))

packet = b'foo|bar|baz|junk'
packet = 'foo|bar|baz|junk'
assert_that(calling(functools.partial(_as_metrics, packet)),
raises(ValueError))

packet = b'gorets:1|c|0.1'
packet = 'gorets:1|c|0.1'
assert_that(calling(functools.partial(_as_metrics, packet)),
raises(ValueError))

def test_counter(self):
packet = b'gorets:1|c'
packet = 'gorets:1|c'
metric = _as_metrics(packet)

assert_that(metric, has_length(1))
metric = metric[0]

assert_that(metric, instance_of(Counter))
assert_that(metric.name, is_(b'gorets'))
assert_that(metric.value, is_(b'1'))
assert_that(metric.name, is_('gorets'))
assert_that(metric.value, is_('1'))
assert_that(metric.sampling_rate, is_(none()))

def test_sampled_counter(self):
packet = b'gorets:1|c|@0.1'
packet = 'gorets:1|c|@0.1'
metric = _as_metrics(packet)

assert_that(metric, has_length(1))
metric = metric[0]

assert_that(metric, instance_of(Counter))
assert_that(metric.name, is_(b'gorets'))
assert_that(metric.value, is_(b'1'))
assert_that(metric.name, is_('gorets'))
assert_that(metric.value, is_('1'))
assert_that(metric.sampling_rate, is_(0.1))

def test_timer(self):
packet = b'glork:320|ms'
packet = 'glork:320|ms'
metric = _as_metrics(packet)

assert_that(metric, has_length(1))
metric = metric[0]

assert_that(metric, instance_of(Timer))
assert_that(metric.name, is_(b'glork'))
assert_that(metric.value, is_(b'320'))
assert_that(metric, has_property('kind', is_(b'ms')))
assert_that(metric.name, is_('glork'))
assert_that(metric.value, is_('320'))
assert_that(metric, has_property('kind', is_('ms')))
assert_that(metric.sampling_rate, is_(none()))

def test_timer_seconds(self):
packet = b'glork:3|s'
packet = 'glork:3|s'
metric = _as_metrics(packet)

assert_that(metric, has_length(1))
metric = metric[0]

assert_that(metric, instance_of(Timer))
assert_that(metric.name, is_(b'glork'))
assert_that(metric.value, is_(b'3'))
assert_that(metric, has_property('kind', is_(b's')))
assert_that(metric.name, is_('glork'))
assert_that(metric.value, is_('3'))
assert_that(metric, has_property('kind', is_('s')))
# type is BWC
assert_that(metric, has_property('type', is_(b's')))
assert_that(metric, has_property('type', is_('s')))
assert_that(metric.sampling_rate, is_(none()))

def test_guage(self):
packet = b'gaugor:+333|g'
packet = 'gaugor:+333|g'
metric = _as_metrics(packet)

assert_that(metric, has_length(1))
metric = metric[0]

assert_that(metric, instance_of(Gauge))
assert_that(metric.name, is_(b'gaugor'))
assert_that(metric.value, is_(b'+333'))
assert_that(metric.name, is_('gaugor'))
assert_that(metric.value, is_('+333'))
assert_that(metric.sampling_rate, is_(none()))

def test_multi_metric(self):
packet = b'gorets:1|c\nglork:320|ms\ngaugor:333|g\nuniques:765|s'
packet = 'gorets:1|c\nglork:320|ms\ngaugor:333|g\nuniques:765|s'
metrics = _as_metrics(packet)
assert_that(metrics, contains(instance_of(Counter),
instance_of(Timer),
Expand All @@ -132,19 +132,19 @@ def test_tracks_metrics(self):
counter, gauge, timer = self.client.metrics

assert_that(counter, instance_of(Counter))
assert_that(counter, has_properties('name', b'mycounter',
'value', b'1'))
assert_that(counter, has_properties('name', 'mycounter',
'value', '1'))

assert_that(gauge, instance_of(Gauge))
assert_that(gauge, has_properties('name', b'mygauge',
'value', b'5'))
assert_that(gauge, has_properties('name', 'mygauge',
'value', '5'))

assert_that(timer, instance_of(Timer))
assert_that(timer, has_properties(
'name', b'mytimer',
'value', b'3003',
'type', b'ms', # bwc
'kind', b'ms',
'name', 'mytimer',
'value', '3003',
'type', 'ms', # bwc
'kind', 'ms',
))

def test_clear(self):
Expand All @@ -160,7 +160,7 @@ def test_tracks_multimetrics(self):
self.client._send(packet)

assert_that(self.client, has_length(4))
assert_that(self.client.packets, contains(packet.encode('ascii')))
assert_that(self.client.packets, contains(packet))

assert_that(self.client.metrics, contains(instance_of(Counter),
instance_of(Timer),
Expand Down

0 comments on commit 8fae176

Please sign in to comment.