mirror of
https://github.com/sprockets/sprockets-statsd.git
synced 2024-11-14 19:29:30 +00:00
Make timeout parameters configurable.
This commit is contained in:
parent
65b5bacbee
commit
28e369c122
3 changed files with 70 additions and 15 deletions
|
@ -13,13 +13,11 @@ class Application(web.Application):
|
|||
This mix-in is configured by the ``statsd`` settings key. The
|
||||
value should be a dictionary with the following keys.
|
||||
|
||||
+--------+---------------------------------------------+
|
||||
| host | the statsd host to send metrics to |
|
||||
+--------+---------------------------------------------+
|
||||
| port | TCP port number that statsd is listening on |
|
||||
+--------+---------------------------------------------+
|
||||
| prefix | segment to prefix to metrics |
|
||||
+--------+---------------------------------------------+
|
||||
+-------------------+---------------------------------------------+
|
||||
| host | the statsd host to send metrics to |
|
||||
+-------------------+---------------------------------------------+
|
||||
| port | TCP port number that statsd is listening on |
|
||||
+-------------------+---------------------------------------------+
|
||||
|
||||
*host* defaults to the :envvar:`STATSD_HOST` environment variable.
|
||||
If this value is not set, then the statsd connector **WILL NOT**
|
||||
|
@ -29,10 +27,30 @@ class Application(web.Application):
|
|||
with a back up default of 8125 if the environment variable is not
|
||||
set.
|
||||
|
||||
The following keys MAY also be specified to fine tune the statsd
|
||||
connection.
|
||||
|
||||
+-------------------+---------------------------------------------+
|
||||
| prefix | segment to prefix to metrics. |
|
||||
+-------------------+---------------------------------------------+
|
||||
| reconnect_timeout | number of seconds to sleep after a statsd |
|
||||
| | connection attempt fails |
|
||||
+-------------------+---------------------------------------------+
|
||||
| wait_timeout | number of seconds to wait for a metric to |
|
||||
| | arrive on the queue before verifying the |
|
||||
| | connection |
|
||||
+-------------------+---------------------------------------------+
|
||||
|
||||
*prefix* defaults to ``applications.<service>.<environment>`` where
|
||||
*<service>* and *<environment>* are replaced with the keys from
|
||||
`settings` if they are present.
|
||||
|
||||
*reconnect_timeout* defaults to 1.0 seconds which limits the
|
||||
aggressiveness of creating new TCP connections.
|
||||
|
||||
*wait_timeout* defaults to 0.1 seconds which ensures that the
|
||||
processor quickly responds to connection faults.
|
||||
|
||||
"""
|
||||
def __init__(self, *args, **settings):
|
||||
statsd_settings = settings.setdefault('statsd', {})
|
||||
|
@ -63,8 +81,15 @@ class Application(web.Application):
|
|||
"""
|
||||
statsd_settings = self.settings['statsd']
|
||||
if statsd_settings.get('_connector') is None:
|
||||
connector = statsd.Connector(host=statsd_settings['host'],
|
||||
port=statsd_settings['port'])
|
||||
kwargs = {
|
||||
'host': statsd_settings['host'],
|
||||
'port': statsd_settings['port'],
|
||||
}
|
||||
if 'reconnect_sleep' in statsd_settings:
|
||||
kwargs['reconnect_sleep'] = statsd_settings['reconnect_sleep']
|
||||
if 'wait_timeout' in statsd_settings:
|
||||
kwargs['wait_timeout'] = statsd_settings['wait_timeout']
|
||||
connector = statsd.Connector(**kwargs)
|
||||
await connector.start()
|
||||
self.settings['statsd']['_connector'] = connector
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ class Connector:
|
|||
|
||||
:param host: statsd server to send metrics to
|
||||
:param port: TCP port that the server is listening on
|
||||
:param kwargs: additional keyword parameters are passed
|
||||
to the :class:`.Processor` initializer
|
||||
|
||||
This class maintains a TCP connection to a statsd server and
|
||||
sends metric lines to it asynchronously. You must call the
|
||||
|
@ -29,8 +31,8 @@ class Connector:
|
|||
sends the metric payloads.
|
||||
|
||||
"""
|
||||
def __init__(self, host: str, port: int = 8125):
|
||||
self.processor = Processor(host=host, port=port)
|
||||
def __init__(self, host: str, port: int = 8125, **kwargs):
|
||||
self.processor = Processor(host=host, port=port, **kwargs)
|
||||
self._processor_task = None
|
||||
|
||||
async def start(self):
|
||||
|
@ -75,6 +77,10 @@ class Processor(asyncio.Protocol):
|
|||
|
||||
:param host: statsd server to send metrics to
|
||||
:param port: TCP port that the server is listening on
|
||||
:param reconnect_sleep: number of seconds to sleep after socket
|
||||
error occurs when connecting
|
||||
:param wait_timeout: number os seconds to wait for a message to
|
||||
arrive on the queue
|
||||
|
||||
This class implements :class:`~asyncio.Protocol` for the statsd
|
||||
TCP connection. The :meth:`.run` method is run as a background
|
||||
|
@ -126,7 +132,12 @@ class Processor(asyncio.Protocol):
|
|||
until the task stops.
|
||||
|
||||
"""
|
||||
def __init__(self, *, host, port: int = 8125):
|
||||
def __init__(self,
|
||||
*,
|
||||
host,
|
||||
port: int = 8125,
|
||||
reconnect_sleep: float = 1.0,
|
||||
wait_timeout: float = 0.1):
|
||||
super().__init__()
|
||||
if not host:
|
||||
raise RuntimeError('host must be set')
|
||||
|
@ -135,6 +146,8 @@ class Processor(asyncio.Protocol):
|
|||
|
||||
self.host = host
|
||||
self.port = port
|
||||
self._reconnect_sleep = reconnect_sleep
|
||||
self._wait_timeout = wait_timeout
|
||||
|
||||
self.running = asyncio.Event()
|
||||
self.stopped = asyncio.Event()
|
||||
|
@ -205,9 +218,9 @@ class Processor(asyncio.Protocol):
|
|||
self.logger.warning('statsd server connection lost')
|
||||
self.connected.clear()
|
||||
|
||||
async def _connect_if_necessary(self, wait_time: float = 0.1):
|
||||
async def _connect_if_necessary(self):
|
||||
try:
|
||||
await asyncio.wait_for(self.connected.wait(), wait_time)
|
||||
await asyncio.wait_for(self.connected.wait(), self._wait_timeout)
|
||||
except asyncio.TimeoutError:
|
||||
try:
|
||||
self.logger.debug('starting connection to %s:%s', self.host,
|
||||
|
@ -219,12 +232,14 @@ class Processor(asyncio.Protocol):
|
|||
except IOError as error:
|
||||
self.logger.warning('connection to %s:%s failed: %s',
|
||||
self.host, self.port, error)
|
||||
await asyncio.sleep(self._reconnect_sleep)
|
||||
|
||||
async def _process_metric(self):
|
||||
processing_failed_send = False
|
||||
if not self._failed_sends:
|
||||
try:
|
||||
metric = await asyncio.wait_for(self.queue.get(), 0.1)
|
||||
metric = await asyncio.wait_for(self.queue.get(),
|
||||
self._wait_timeout)
|
||||
self.logger.debug('received %r from queue', metric)
|
||||
self.queue.task_done()
|
||||
except asyncio.TimeoutError:
|
||||
|
|
|
@ -115,6 +115,21 @@ class ApplicationTests(testing.AsyncTestCase):
|
|||
})
|
||||
self.io_loop.run_sync(app.stop_statsd)
|
||||
|
||||
def test_optional_parameters(self):
|
||||
app = sprockets_statsd.mixins.Application(
|
||||
statsd={
|
||||
'host': 'localhost',
|
||||
'port': '8125',
|
||||
'reconnect_sleep': 0.5,
|
||||
'wait_timeout': 0.25,
|
||||
})
|
||||
self.io_loop.run_sync(app.start_statsd)
|
||||
|
||||
processor = app.settings['statsd']['_connector'].processor
|
||||
self.assertEqual(0.5, processor._reconnect_sleep)
|
||||
self.assertEqual(0.25, processor._wait_timeout)
|
||||
self.io_loop.run_sync(app.stop_statsd)
|
||||
|
||||
|
||||
class RequestHandlerTests(testing.AsyncHTTPTestCase):
|
||||
def setUp(self):
|
||||
|
|
Loading…
Reference in a new issue