Rework application prefix configuration.

Use a default of `None` instead of `applications` if the neither service
nor environment keys are set.
This commit is contained in:
Dave Shawley 2021-03-23 07:08:34 -04:00
parent 63dc44fd22
commit 69dfb51bf8
No known key found for this signature in database
GPG key ID: 44A9C9992CCFAB82
2 changed files with 46 additions and 41 deletions

View file

@ -11,25 +11,12 @@ class Application(web.Application):
"""Mix this into your application to add a statsd connection. """Mix this into your application to add a statsd connection.
This mix-in is configured by the ``statsd`` settings key. The This mix-in is configured by the ``statsd`` settings key. The
value should be a dictionary with the following keys. value is a dictionary with the following keys.
+-------------------+---------------------------------------------+ +-------------------+---------------------------------------------+
| host | the statsd host to send metrics to | | host | the statsd host to send metrics to |
+-------------------+---------------------------------------------+ +-------------------+---------------------------------------------+
| port | TCP port number that statsd is listening on | | port | 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**
be enabled.
*port* defaults to the :envvar:`STATSD_PORT` environment variable
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. | | prefix | segment to prefix to metrics. |
+-------------------+---------------------------------------------+ +-------------------+---------------------------------------------+
@ -41,14 +28,27 @@ class Application(web.Application):
| | connection | | | connection |
+-------------------+---------------------------------------------+ +-------------------+---------------------------------------------+
*prefix* defaults to ``applications.<service>.<environment>`` where **host** defaults to the :envvar:`STATSD_HOST` environment variable.
*<service>* and *<environment>* are replaced with the keys from If this value is not set, then the statsd connector *WILL NOT* be
`settings` if they are present. enabled.
*reconnect_timeout* defaults to 1.0 seconds which limits the **port** defaults to the :envvar:`STATSD_PORT` environment variable
with a back up default of 8125 if the environment variable is not
set.
**prefix** is prefixed to all metric paths. This provides a
namespace for metrics so that each applications metrics are maintained
in separate buckets.
If the *service* and *environment* keys are set in ``settings``,
then the default prefix is ``applications.<service>.<environment>``.
This is a convenient way to maintain consistent metric paths when
you are managing a larger number of services.
**reconnect_timeout** defaults to 1.0 seconds which limits the
aggressiveness of creating new TCP connections. aggressiveness of creating new TCP connections.
*wait_timeout* defaults to 0.1 seconds which ensures that the **wait_timeout** defaults to 0.1 seconds which ensures that the
processor quickly responds to connection faults. processor quickly responds to connection faults.
""" """
@ -58,12 +58,15 @@ class Application(web.Application):
statsd_settings.setdefault('port', statsd_settings.setdefault('port',
os.environ.get('STATSD_PORT', '8125')) os.environ.get('STATSD_PORT', '8125'))
prefix = ['applications'] try:
if 'service' in settings: prefix = '.'.join([
prefix.append(settings['service']) 'applications',
if 'environment' in settings: settings['service'],
prefix.append(settings['environment']) settings['environment'],
statsd_settings.setdefault('prefix', '.'.join(prefix)) ])
except KeyError:
prefix = None
statsd_settings.setdefault('prefix', prefix)
super().__init__(*args, **settings) super().__init__(*args, **settings)

View file

@ -45,7 +45,7 @@ class ApplicationTests(testing.AsyncTestCase):
self.assertIsNone(app.settings['statsd']['host'], self.assertIsNone(app.settings['statsd']['host'],
'default host value should be None') 'default host value should be None')
self.assertEqual(8125, app.settings['statsd']['port']) self.assertEqual(8125, app.settings['statsd']['port'])
self.assertEqual('applications', app.settings['statsd']['prefix']) self.assertEqual(None, app.settings['statsd']['prefix'])
def test_that_statsd_settings_read_from_environment(self): def test_that_statsd_settings_read_from_environment(self):
self.setenv('STATSD_HOST', 'statsd') self.setenv('STATSD_HOST', 'statsd')
@ -56,22 +56,21 @@ class ApplicationTests(testing.AsyncTestCase):
self.assertEqual('statsd', app.settings['statsd']['host']) self.assertEqual('statsd', app.settings['statsd']['host'])
self.assertEqual(5218, app.settings['statsd']['port']) self.assertEqual(5218, app.settings['statsd']['port'])
def test_that_service_included_in_prefix_if_set(self): def test_prefix_when_only_service_is_set(self):
app = sprockets_statsd.mixins.Application(service='blah') app = sprockets_statsd.mixins.Application(service='blah')
self.assertIn('statsd', app.settings) self.assertIn('statsd', app.settings)
self.assertEqual('applications.blah', app.settings['statsd']['prefix']) self.assertEqual(None, app.settings['statsd']['prefix'])
def test_that_environment_included_in_prefix_if_set(self): def test_prefix_when_only_environment_is_set(self):
app = sprockets_statsd.mixins.Application(environment='whatever') app = sprockets_statsd.mixins.Application(environment='whatever')
self.assertIn('statsd', app.settings) self.assertIn('statsd', app.settings)
self.assertEqual('applications.whatever', self.assertEqual(None, app.settings['statsd']['prefix'])
app.settings['statsd']['prefix'])
def test_fully_specified_prefix(self): def test_prefix_default_when_service_and_environment_are_set(self):
app = sprockets_statsd.mixins.Application(environment='whatever', app = sprockets_statsd.mixins.Application(environment='development',
service='blah') service='my-service')
self.assertIn('statsd', app.settings) self.assertIn('statsd', app.settings)
self.assertEqual('applications.blah.whatever', self.assertEqual('applications.my-service.development',
app.settings['statsd']['prefix']) app.settings['statsd']['prefix'])
def test_overridden_settings(self): def test_overridden_settings(self):
@ -138,8 +137,11 @@ class RequestHandlerTests(testing.AsyncHTTPTestCase):
self.io_loop.spawn_callback(self.statsd_server.run) self.io_loop.spawn_callback(self.statsd_server.run)
self.io_loop.run_sync(self.statsd_server.wait_running) self.io_loop.run_sync(self.statsd_server.wait_running)
self.app.settings['statsd']['host'] = self.statsd_server.host self.app.settings['statsd'].update({
self.app.settings['statsd']['port'] = self.statsd_server.port 'host': self.statsd_server.host,
'port': self.statsd_server.port,
'prefix': 'applications.service',
})
self.io_loop.run_sync(self.app.start_statsd) self.io_loop.run_sync(self.app.start_statsd)
def tearDown(self): def tearDown(self):
@ -183,7 +185,7 @@ class RequestHandlerTests(testing.AsyncHTTPTestCase):
self.wait_for_metrics() self.wait_for_metrics()
path, _, type_code = self.find_metric('Handler.GET.200') path, _, type_code = self.find_metric('Handler.GET.200')
self.assertEqual(path, 'applications.timers.Handler.GET.200') self.assertEqual(path, 'applications.service.timers.Handler.GET.200')
self.assertEqual('ms', type_code) self.assertEqual('ms', type_code)
def test_execution_timer(self): def test_execution_timer(self):
@ -192,7 +194,7 @@ class RequestHandlerTests(testing.AsyncHTTPTestCase):
self.wait_for_metrics() self.wait_for_metrics()
path, _, type_code = self.find_metric('execution-timer') path, _, type_code = self.find_metric('execution-timer')
self.assertEqual('applications.timers.execution-timer', path) self.assertEqual('applications.service.timers.execution-timer', path)
self.assertEqual('ms', type_code) self.assertEqual('ms', type_code)
def test_counter(self): def test_counter(self):
@ -201,7 +203,7 @@ class RequestHandlerTests(testing.AsyncHTTPTestCase):
self.wait_for_metrics() self.wait_for_metrics()
path, value, type_code = self.find_metric('request-count') path, value, type_code = self.find_metric('request-count')
self.assertEqual('applications.counters.request-count', path) self.assertEqual('applications.service.counters.request-count', path)
self.assertEqual(1.0, value) self.assertEqual(1.0, value)
self.assertEqual('c', type_code) self.assertEqual('c', type_code)