From 1bc4fe891a359c626ebc8049403d4d72a75b6be7 Mon Sep 17 00:00:00 2001 From: John Dickinson <me@not.mn> Date: Sun, 10 Aug 2014 23:50:17 -0700 Subject: [PATCH] Catch permissions errors when writing StatsD packets Closes-Bug: #1183152 Change-Id: I4b2c6e947241c987779a385fdff270d037470a57 --- swift/common/utils.py | 13 ++++++++++--- test/unit/common/test_utils.py | 18 +++++++++++++++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/swift/common/utils.py b/swift/common/utils.py index 7c9f7a93c7..37fbeaea00 100644 --- a/swift/common/utils.py +++ b/swift/common/utils.py @@ -933,7 +933,7 @@ class LoggerFileObject(object): class StatsdClient(object): def __init__(self, host, port, base_prefix='', tail_prefix='', - default_sample_rate=1, sample_rate_factor=1): + default_sample_rate=1, sample_rate_factor=1, logger=None): self._host = host self._port = port self._base_prefix = base_prefix @@ -942,6 +942,7 @@ class StatsdClient(object): self._sample_rate_factor = sample_rate_factor self._target = (self._host, self._port) self.random = random + self.logger = logger def set_prefix(self, new_prefix): if new_prefix and self._base_prefix: @@ -966,7 +967,13 @@ class StatsdClient(object): # Ideally, we'd cache a sending socket in self, but that # results in a socket getting shared by multiple green threads. with closing(self._open_socket()) as sock: - return sock.sendto('|'.join(parts), self._target) + try: + return sock.sendto('|'.join(parts), self._target) + except IOError as err: + if self.logger: + self.logger.warn( + 'Error sending UDP message to %r: %s', + self._target, err) def _open_socket(self): return socket.socket(socket.AF_INET, socket.SOCK_DGRAM) @@ -1332,7 +1339,7 @@ def get_logger(conf, name=None, log_to_console=False, log_route=None, 'log_statsd_sample_rate_factor', 1)) statsd_client = StatsdClient(statsd_host, statsd_port, base_prefix, name, default_sample_rate, - sample_rate_factor) + sample_rate_factor, logger=logger) logger.statsd_client = statsd_client else: logger.statsd_client = None diff --git a/test/unit/common/test_utils.py b/test/unit/common/test_utils.py index a7733f8c25..43a1954d97 100644 --- a/test/unit/common/test_utils.py +++ b/test/unit/common/test_utils.py @@ -110,10 +110,14 @@ class MockOs(object): class MockUdpSocket(object): - def __init__(self): + def __init__(self, sendto_errno=None): self.sent = [] + self.sendto_errno = sendto_errno def sendto(self, data, target): + if self.sendto_errno: + raise socket.error(self.sendto_errno, + 'test errno %s' % self.sendto_errno) self.sent.append((data, target)) def close(self): @@ -3037,6 +3041,18 @@ class TestStatsdLogging(unittest.TestCase): self.assertEqual(logger.logger.statsd_client._sample_rate_factor, 0.81) + def test_no_exception_when_cant_send_udp_packet(self): + logger = utils.get_logger({'log_statsd_host': 'some.host.com'}) + statsd_client = logger.logger.statsd_client + fl = FakeLogger() + statsd_client.logger = fl + mock_socket = MockUdpSocket(sendto_errno=errno.EPERM) + statsd_client._open_socket = lambda *_: mock_socket + logger.increment('tunafish') + expected = ["Error sending UDP message to ('some.host.com', 8125): " + "[Errno 1] test errno 1"] + self.assertEqual(fl.get_lines_for_level('warning'), expected) + def test_sample_rates(self): logger = utils.get_logger({'log_statsd_host': 'some.host.com'})