Skip to content

Commit a7c388b

Browse files
author
Emanuele Palazzetti
committed
[core] add a global configuration system
1 parent 4b72ad0 commit a7c388b

File tree

3 files changed

+85
-1
lines changed

3 files changed

+85
-1
lines changed

ddtrace/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
from .pin import Pin
33
from .span import Span
44
from .tracer import Tracer
5+
from .configuration import Config
56

67
__version__ = '0.11.0'
78

8-
# a global tracer instance
9+
# a global tracer instance with integration settings
910
tracer = Tracer()
11+
config = Config()
1012

1113
__all__ = [
1214
'patch',
@@ -15,4 +17,5 @@
1517
'Span',
1618
'tracer',
1719
'Tracer',
20+
'config',
1821
]

ddtrace/configuration.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
class ConfigException(Exception):
2+
"""Configuration exception when an integration that is not available
3+
is called in the `Config` object.
4+
"""
5+
pass
6+
7+
8+
class Config(object):
9+
"""Configuration object that exposes an API to set and retrieve
10+
global settings for each integration. All integrations must use
11+
this instance to register their defaults, so that they're public
12+
available and can be updated by users.
13+
"""
14+
def __init__(self):
15+
# use a dict as underlying storing mechanism
16+
self._config = {}
17+
18+
def __getattr__(self, name):
19+
try:
20+
return self._config[name]
21+
except KeyError as e:
22+
raise ConfigException(
23+
'Integration "{}" is not registered in this configuration'.format(e.message)
24+
)
25+
26+
def _add(self, integration, settings):
27+
"""Internal API that registers an integration with given default
28+
settings.
29+
30+
:param str integration: The integration name (i.e. `requests`)
31+
:param dict settings: A dictionary that contains integration settings;
32+
to preserve immutability of these values, the dictionary is copied
33+
since it contains integration defaults.
34+
"""
35+
36+
self._config[integration] = settings.copy()

tests/test_configuration.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from unittest import TestCase
2+
3+
from nose.tools import eq_, ok_, assert_raises
4+
5+
from ddtrace import config as global_config
6+
from ddtrace.configuration import Config, ConfigException
7+
8+
9+
class ConfigTestCase(TestCase):
10+
"""Test the `Configuration` class that stores integration settings"""
11+
def setUp(self):
12+
self.config = Config()
13+
14+
def test_registration(self):
15+
# ensure an integration can register a new list of settings
16+
settings = {
17+
'distributed_tracing': True,
18+
}
19+
self.config._add('requests', settings)
20+
ok_(self.config.requests['distributed_tracing'] is True)
21+
22+
def test_settings_copy(self):
23+
# ensure that once an integration is registered, a copy
24+
# of the settings is stored to avoid side-effects
25+
settings = {
26+
'distributed_tracing': True,
27+
}
28+
self.config._add('requests', settings)
29+
30+
settings['distributed_tracing'] = False
31+
ok_(self.config.requests['distributed_tracing'] is True)
32+
33+
def test_missing_integration(self):
34+
# ensure a meaningful exception is raised when an integration
35+
# that is not available is retrieved in the configuration
36+
# object
37+
with assert_raises(ConfigException) as e:
38+
self.config.new_integration['some_key']
39+
40+
ok_(isinstance(e.exception, ConfigException))
41+
eq_(e.exception.message, 'Integration "new_integration" is not registered in this configuration')
42+
43+
def test_global_configuration(self):
44+
# ensure a global configuration is available in the `ddtrace` module
45+
ok_(isinstance(global_config, Config))

0 commit comments

Comments
 (0)