Skip to content
This repository has been archived by the owner on May 16, 2024. It is now read-only.

Commit

Permalink
Merge pull request #33 from DataDog/yann/0.5.6
Browse files Browse the repository at this point in the history
0.5.6
  • Loading branch information
yannmh committed Mar 20, 2015
2 parents a30d373 + 8bb73ca commit 8c67512
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 68 deletions.
22 changes: 0 additions & 22 deletions CONTRIBUTING.md

This file was deleted.

2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ Change Log
----------
- [DEPRECATED]
- Date: 2015.03.17
- 0.5.6
- Revert to 0.5.3 due to backward incompatibilities.
- 0.5.5
- Revert usage of Python property for socket introduced in 0.5.4, to avoid backward incompatibilities, and performance degradation
- 0.5.4
Expand Down
5 changes: 2 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@

setup(
name = "dogstatsd-python",
version = "0.5.5",
version = "0.5.6",
author = "Datadog, Inc.",
author_email = "[email protected]",
description = "Python bindings to Datadog's API and a user-facing command line tool.",
py_modules=['statsd'],
license = "BSD",
keywords = "datadog data statsd metrics",
url = "http://www.datadoghq.com",
test_suite = "nose.collector"
url = "http://www.datadoghq.com"
)
58 changes: 35 additions & 23 deletions statsd.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python
"""
DogStatsd is a Python client for DogStatsd, a Statsd fork for Datadog.
"""
Expand All @@ -21,7 +20,7 @@
class DogStatsd(object):
OK, WARNING, CRITICAL, UNKNOWN = (0, 1, 2, 3)

def __init__(self, host='localhost', port=8125, max_buffer_size=50):
def __init__(self, host='localhost', port=8125, max_buffer_size = 50):
"""
Initialize a DogStatsd object.
Expand All @@ -31,30 +30,29 @@ def __init__(self, host='localhost', port=8125, max_buffer_size=50):
:param port: the port of the DogStatsd server.
:param max_buffer_size: Maximum number of metric to buffer before sending to the server if sending metrics in batch
"""
self._host = host
self._port = int(port)
self._host = None
self._port = None
self.socket = None
self.max_buffer_size = max_buffer_size
self._send = self._send_to_server

self.connect(host, port)
self.encoding = 'utf-8'

def __enter__(self):
self.open_buffer(self.max_buffer_size)
return self

def __exit__(self, type, value, traceback):
self.close_buffer()

def get_socket(self):
'''
Return a connected socket
'''
if not self.socket:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.socket.connect((self._host, self._port))
self.connect(self._host, self._port)
return self.socket

def __enter__(self):
self.open_buffer(self.max_buffer_size)
return self

def __exit__(self, type, value, traceback):
self.close_buffer()

def open_buffer(self, max_buffer_size=50):
'''
Open a buffer to send a batch of metrics in one packet
Expand All @@ -67,7 +65,7 @@ def open_buffer(self, max_buffer_size=50):
'''
self.max_buffer_size = max_buffer_size
self.buffer = []
self.buffer= []
self._send = self._send_to_buffer

def close_buffer(self):
Expand All @@ -77,6 +75,15 @@ def close_buffer(self):
self._send = self._send_to_server
self._flush_buffer()

def connect(self, host, port):
"""
Connect to the statsd server on the given host and port.
"""
self._host = host
self._port = int(port)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.socket.connect((self._host, self._port))

def gauge(self, metric, value, tags=None, sample_rate=1):
"""
Record the value of a gauge, optionally setting a list of tags and a
Expand Down Expand Up @@ -176,13 +183,12 @@ def _report(self, metric, metric_type, value, tags, sample_rate):

def _send_to_server(self, packet):
try:
# If set, use socket directly
(self.socket or self.get_socket()).send(packet.encode(self.encoding))
self.socket.send(packet.encode(self.encoding))
except socket.error:
log.info("Error submitting packet, will try refreshing the socket")
self.socket = None
log.info("Error submitting metric, will try refreshing the socket")
self.connect(self._host, self._port)
try:
self.get_socket().send(packet.encode(self.encoding))
self.socket.send(packet.encode(self.encoding))
except socket.error:
log.exception("Failed to send packet with a newly binded socket")

Expand All @@ -193,7 +199,7 @@ def _send_to_buffer(self, packet):

def _flush_buffer(self):
self._send_to_server("\n".join(self.buffer))
self.buffer = []
self.buffer=[]

def _escape_event_content(self, string):
return string.replace('\n', '\\n')
Expand Down Expand Up @@ -233,7 +239,10 @@ def event(self, title, text, alert_type=None, aggregation_key=None,
raise Exception(u'Event "%s" payload is too big (more that 8KB), '
'event discarded' % title)

self._send(string)
try:
self.socket.send(string.encode(self.encoding))
except Exception:
log.exception(u'Error submitting event "%s"' % title)

def service_check(self, check_name, status, tags=None, timestamp=None,
hostname=None, message=None):
Expand All @@ -255,7 +264,10 @@ def service_check(self, check_name, status, tags=None, timestamp=None,
if message:
string = u'{0}|m:{1}'.format(string, message)

self._send(string)
try:
self.socket.send(string.encode(self.encoding))
except Exception:
log.exception(u'Error submitting service check "{0}"'.format(check_name))


statsd = DogStatsd()
22 changes: 2 additions & 20 deletions tests/test_statsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def setUp(self):
self.statsd.socket = FakeSocket()

def recv(self):
return self.statsd.get_socket().recv()
return self.statsd.socket.recv()

def test_set(self):
self.statsd.set('set', 123)
Expand Down Expand Up @@ -89,7 +89,7 @@ def test_sample_rate(self):
assert not self.recv()
for i in range(10000):
self.statsd.increment('sampled_counter', sample_rate=0.3)
self.assert_almost_equal(3000, len(self.statsd.get_socket().payloads), 150)
self.assert_almost_equal(3000, len(self.statsd.socket.payloads), 150)
t.assert_equal('sampled_counter:1|c|@0.3', self.recv())

def test_tags_and_samples(self):
Expand Down Expand Up @@ -182,24 +182,6 @@ def test_batched_buffer_autoflush(self):
def test_module_level_instance(self):
t.assert_true(isinstance(statsd.statsd, statsd.DogStatsd))

def test_instantiating_does_not_connect(self):
dogpound = DogStatsd()
t.assert_equal(None, dogpound.socket)

def test_accessing_socket_opens_socket(self):
dogpound = DogStatsd()
try:
t.assert_not_equal(None, dogpound.get_socket())
finally:
dogpound.get_socket().close()

def test_accessing_socket_multiple_times_returns_same_socket(self):
dogpound = DogStatsd()
fresh_socket = FakeSocket()
dogpound.socket = fresh_socket
t.assert_equal(fresh_socket, dogpound.get_socket())
t.assert_not_equal(FakeSocket(), dogpound.get_socket())


if __name__ == '__main__':
statsd = statsd
Expand Down

0 comments on commit 8c67512

Please sign in to comment.