From cd77825a80594bed178484ba8556fd4ad9842d07 Mon Sep 17 00:00:00 2001 From: Xavier Vello Date: Tue, 16 May 2017 10:23:18 +0200 Subject: [PATCH 1/5] add use_unix_socket option to enable unix socket traffic to dogstatsd6 --- datadog/dogstatsd/base.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/datadog/dogstatsd/base.py b/datadog/dogstatsd/base.py index 247f183e6..a9bc5f3ba 100644 --- a/datadog/dogstatsd/base.py +++ b/datadog/dogstatsd/base.py @@ -24,7 +24,8 @@ class DogStatsd(object): OK, WARNING, CRITICAL, UNKNOWN = (0, 1, 2, 3) def __init__(self, host='localhost', port=8125, max_buffer_size=50, namespace=None, - constant_tags=None, use_ms=False, use_default_route=False): + constant_tags=None, use_ms=False, use_default_route=False, + use_unix_socket=None): """ Initialize a DogStatsd object. @@ -56,10 +57,20 @@ def __init__(self, host='localhost', port=8125, max_buffer_size=50, namespace=No (Useful when running the client in a container) (Linux only) :type use_default_route: boolean + :param use_unix_socket: Communicate with dogstatsd through a UNIX socket instead of + UDP. If set, disables UDP transmission (Linux only) + :type use_unix_socket: string """ + # Connection - self.host = self.resolve_host(host, use_default_route) - self.port = int(port) + if use_unix_socket is not None: + self.socket_path = use_unix_socket + self.host = None + self.port = None + else: + self.socket_path = None + self.host = self.resolve_host(host, use_default_route) + self.port = int(port) # Socket self.socket = None @@ -105,9 +116,15 @@ def get_socket(self): avoid bad thread race conditions. """ if not self.socket: - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - sock.connect((self.host, self.port)) - self.socket = sock + if self.socket_path is not None: + sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) + sock.connect(self.socket_path) + sock.setblocking(0) + self.socket = sock + else: + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.connect((self.host, self.port)) + self.socket = sock return self.socket From 344e1708ab1200d3aabf0be1e9e63862fd486764 Mon Sep 17 00:00:00 2001 From: Xavier Vello Date: Wed, 17 May 2017 11:53:23 +0200 Subject: [PATCH 2/5] s/use_unix_socket/socket_path/ --- datadog/dogstatsd/base.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/datadog/dogstatsd/base.py b/datadog/dogstatsd/base.py index a9bc5f3ba..1d39b5b99 100644 --- a/datadog/dogstatsd/base.py +++ b/datadog/dogstatsd/base.py @@ -25,7 +25,7 @@ class DogStatsd(object): def __init__(self, host='localhost', port=8125, max_buffer_size=50, namespace=None, constant_tags=None, use_ms=False, use_default_route=False, - use_unix_socket=None): + socket_path=None): """ Initialize a DogStatsd object. @@ -57,14 +57,14 @@ def __init__(self, host='localhost', port=8125, max_buffer_size=50, namespace=No (Useful when running the client in a container) (Linux only) :type use_default_route: boolean - :param use_unix_socket: Communicate with dogstatsd through a UNIX socket instead of + :param socket_path: Communicate with dogstatsd through a UNIX socket instead of UDP. If set, disables UDP transmission (Linux only) - :type use_unix_socket: string + :type socket_path: string """ # Connection - if use_unix_socket is not None: - self.socket_path = use_unix_socket + if socket_path is not None: + self.socket_path = socket_path self.host = None self.port = None else: From b06997af5947d9cf185b6f49a5733e02b8e5c451 Mon Sep 17 00:00:00 2001 From: Xavier Vello Date: Wed, 17 May 2017 12:04:32 +0200 Subject: [PATCH 3/5] silently drop packets on socket timeout this mimics UDP behaviour for unix socket implementation --- datadog/dogstatsd/base.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/datadog/dogstatsd/base.py b/datadog/dogstatsd/base.py index 1d39b5b99..8c72e089b 100644 --- a/datadog/dogstatsd/base.py +++ b/datadog/dogstatsd/base.py @@ -282,6 +282,9 @@ def _send_to_server(self, packet): try: # If set, use socket directly (self.socket or self.get_socket()).send(packet.encode(self.encoding)) + except socket.timeout: + # dogstatsd is overflowing, drop the packets (mimicks the UDP behaviour) + return except socket.error: log.info("Error submitting packet, will try refreshing the socket") From 32eee8a3ee2df5fa52f5120b65e236496c1c6c79 Mon Sep 17 00:00:00 2001 From: Xavier Vello Date: Wed, 31 May 2017 15:10:53 +0200 Subject: [PATCH 4/5] skip packet re-sending on error, drop instead --- datadog/dogstatsd/base.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/datadog/dogstatsd/base.py b/datadog/dogstatsd/base.py index 8c72e089b..3658a4d20 100644 --- a/datadog/dogstatsd/base.py +++ b/datadog/dogstatsd/base.py @@ -286,17 +286,9 @@ def _send_to_server(self, packet): # dogstatsd is overflowing, drop the packets (mimicks the UDP behaviour) return except socket.error: - log.info("Error submitting packet, will try refreshing the socket") - + log.info("Error submitting packet, dropping the packet and closing the socket") self.close_socket() - try: - self.get_socket().send(packet.encode(self.encoding)) - except socket.error: - self.close_socket() - - log.exception("Failed to send packet with a newly bound socket") - def _send_to_buffer(self, packet): self.buffer.append(packet) if len(self.buffer) >= self.max_buffer_size: From 35431e733ba7622e4e2f92df78bf3aa29e25767d Mon Sep 17 00:00:00 2001 From: Xavier Vello Date: Tue, 6 Jun 2017 15:12:34 +0200 Subject: [PATCH 5/5] update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38689b7ce..665589d7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ CHANGELOG ========= +# 0.17.0 / unreleased +* [FEATURE] DogStatsD: add socket_path option to enable unix socket traffic to dogstatsd6 [199][] + # 0.16.0 / 2017-04-26 * [FEATURE] Dogshell: Add filtering options to the `monitor show_all` command, [#194][]