Skip to content

Commit 0a3b559

Browse files
author
Emanuele Palazzetti
authored
Merge pull request #443 from palazzem/global-config
[core] add a global configuration system
2 parents 4b72ad0 + f34941b commit 0a3b559

File tree

3 files changed

+93
-1
lines changed

3 files changed

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

tests/test_configuration.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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+
experimental = {
26+
'request_enqueuing': True,
27+
}
28+
settings = {
29+
'distributed_tracing': True,
30+
'experimental': experimental,
31+
}
32+
self.config._add('requests', settings)
33+
34+
settings['distributed_tracing'] = False
35+
experimental['request_enqueuing'] = False
36+
ok_(self.config.requests['distributed_tracing'] is True)
37+
ok_(self.config.requests['experimental']['request_enqueuing'] is True)
38+
39+
def test_missing_integration(self):
40+
# ensure a meaningful exception is raised when an integration
41+
# that is not available is retrieved in the configuration
42+
# object
43+
with assert_raises(ConfigException) as e:
44+
self.config.new_integration['some_key']
45+
46+
ok_(isinstance(e.exception, ConfigException))
47+
48+
def test_global_configuration(self):
49+
# ensure a global configuration is available in the `ddtrace` module
50+
ok_(isinstance(global_config, Config))

0 commit comments

Comments
 (0)