summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/source/reference/helpers.rst17
-rw-r--r--oslo_config/cfg.py39
-rw-r--r--oslo_config/tests/test_get_location.py18
3 files changed, 48 insertions, 26 deletions
diff --git a/doc/source/reference/helpers.rst b/doc/source/reference/helpers.rst
index e2d5cb4..4a36dc8 100644
--- a/doc/source/reference/helpers.rst
+++ b/doc/source/reference/helpers.rst
@@ -6,3 +6,20 @@ Helper Functions
.. autofunction:: find_config_files
.. autofunction:: set_defaults
+
+Showing detailed locations for configuration settings
+-----------------------------------------------------
+
+``oslo.config`` can track the location in application and library code
+where an option is defined, defaults are set, or values are
+overridden. This feature is disabled by default because it is
+expensive and incurs a significant performance penalty, but it can be
+useful for developers tracing down issues with configuration option
+definitions.
+
+To turn on detailed location tracking, set the environment variable
+``OSLO_CONFIG_SHOW_CODE_LOCATIONS`` to any non-empty value (for
+example, ``"1"`` or ``"yes, please"``) before starting the
+application, test suite, or script. Then use
+:func:`ConfigOpts.get_location` to access the location data for the
+option.
diff --git a/oslo_config/cfg.py b/oslo_config/cfg.py
index 183e0b6..53cd2a3 100644
--- a/oslo_config/cfg.py
+++ b/oslo_config/cfg.py
@@ -489,7 +489,7 @@ import copy
import errno
import functools
import glob
-# import inspect
+import inspect
import itertools
import logging
import os
@@ -804,6 +804,10 @@ def _is_opt_registered(opts, opt):
return False
+_show_caller_details = bool(os.environ.get(
+ 'OSLO_CONFIG_SHOW_CODE_LOCATIONS'))
+
+
def _get_caller_detail(n=2):
"""Return a string describing where this is being called from.
@@ -811,23 +815,22 @@ def _get_caller_detail(n=2):
:type n: int
:returns: str
"""
- return None
- # FIXME(dhellmann): We need to look at the performance issues with
- # doing this for every Opt instance.
- # s = inspect.stack()[:n + 1]
- # try:
- # frame = s[n]
- # try:
- # return frame[1]
- # # WARNING(dhellmann): Using frame.lineno to include the
- # # line number in the return value causes some sort of
- # # memory or stack corruption that manifests in values not
- # # being cleaned up in the cfgfilter tests.
- # # return '%s:%s' % (frame[1], frame[2])
- # finally:
- # del frame
- # finally:
- # del s
+ if not _show_caller_details:
+ return None
+ s = inspect.stack()[:n + 1]
+ try:
+ frame = s[n]
+ try:
+ return frame[1]
+ # WARNING(dhellmann): Using frame.lineno to include the
+ # line number in the return value causes some sort of
+ # memory or stack corruption that manifests in values not
+ # being cleaned up in the cfgfilter tests.
+ # return '%s:%s' % (frame[1], frame[2])
+ finally:
+ del frame
+ finally:
+ del s
def set_defaults(opts, **kwargs):
diff --git a/oslo_config/tests/test_get_location.py b/oslo_config/tests/test_get_location.py
index d5974b2..d8aef48 100644
--- a/oslo_config/tests/test_get_location.py
+++ b/oslo_config/tests/test_get_location.py
@@ -51,6 +51,12 @@ class GetLocationTestCase(base.BaseTestCase):
def setUp(self):
super(GetLocationTestCase, self).setUp()
+
+ def _clear():
+ cfg._show_caller_details = False
+ self.addCleanup(_clear)
+ cfg._show_caller_details = True
+
self.conf = TestConfigOpts()
self.normal_opt = cfg.StrOpt(
'normal_opt',
@@ -70,8 +76,7 @@ class GetLocationTestCase(base.BaseTestCase):
cfg.Locations.opt_default,
loc.location,
)
- self.assertIsNone(loc.detail)
- # self.assertIn('test_get_location.py', loc.detail)
+ self.assertIn('test_get_location.py', loc.detail)
def test_set_default_on_config_opt(self):
self.conf.set_default('normal_opt', self.id())
@@ -81,8 +86,7 @@ class GetLocationTestCase(base.BaseTestCase):
cfg.Locations.set_default,
loc.location,
)
- self.assertIsNone(loc.detail)
- # self.assertIn('test_get_location.py', loc.detail)
+ self.assertIn('test_get_location.py', loc.detail)
def test_set_defaults_func(self):
cfg.set_defaults([self.normal_opt], normal_opt=self.id())
@@ -92,8 +96,7 @@ class GetLocationTestCase(base.BaseTestCase):
cfg.Locations.set_default,
loc.location,
)
- self.assertIsNone(loc.detail)
- # self.assertIn('test_get_location.py', loc.detail)
+ self.assertIn('test_get_location.py', loc.detail)
def test_set_override(self):
self.conf.set_override('normal_opt', self.id())
@@ -103,8 +106,7 @@ class GetLocationTestCase(base.BaseTestCase):
cfg.Locations.set_override,
loc.location,
)
- self.assertIsNone(loc.detail)
- # self.assertIn('test_get_location.py', loc.detail)
+ self.assertIn('test_get_location.py', loc.detail)
def test_user_cli(self):
filename = self._write_opt_to_tmp_file(