Merge "Handle driver initialization errors to avoid service crash"

This commit is contained in:
Zuul 2019-11-18 17:24:16 +00:00 committed by Gerrit Code Review
commit e022fdaa8e
6 changed files with 45 additions and 21 deletions

View File

@ -36,9 +36,9 @@ class ElasticsearchDriver(base.Driver):
from elasticsearch import Elasticsearch
except ImportError:
raise exc.CommandError(
"To use this command, you should install "
"'elasticsearch' manually. Use command:\n "
"'pip install elasticsearch'.")
"To use OSProfiler with ElasticSearch driver, "
"please install `elasticsearch` library. "
"To install with pip:\n `pip install elasticsearch`.")
client_url = parser.urlunparse(parser.urlparse(self.connection_str)
._replace(scheme="http"))

View File

@ -40,8 +40,8 @@ class Jaeger(base.Driver):
except ImportError:
raise exc.CommandError(
"To use OSProfiler with Uber Jaeger tracer, "
"you have to install `jaeger-client` manually. "
"Install with pip:\n `pip install jaeger-client`."
"please install `jaeger-client` library. "
"To install with pip:\n `pip install jaeger-client`."
)
parsed_url = parser.urlparse(connection_str)

View File

@ -28,9 +28,9 @@ class MongoDB(base.Driver):
from pymongo import MongoClient
except ImportError:
raise exc.CommandError(
"To use this command, you should install "
"'pymongo' manually. Use command:\n "
"'pip install pymongo'.")
"To use OSProfiler with MongoDB driver, "
"please install `pymongo` library. "
"To install with pip:\n `pip install pymongo`.")
client = MongoClient(self.connection_str, connect=False)
self.db = client[db_name]

View File

@ -40,9 +40,9 @@ class Redis(base.Driver):
from redis import StrictRedis
except ImportError:
raise exc.CommandError(
"To use this command, you should install "
"'redis' manually. Use command:\n "
"'pip install redis'.")
"To use OSProfiler with Redis driver, "
"please install `redis` library. "
"To install with pip:\n `pip install redis`.")
# only connection over network is supported with schema
# redis://[:password]@host[:port][/db]

View File

@ -13,16 +13,21 @@
# License for the specific language governing permissions and limitations
# under the License.
import logging
from osprofiler.drivers import base
LOG = logging.getLogger(__name__)
def _noop_notifier(info, context=None):
"""Do nothing on notify()."""
# NOTE(boris-42): By default we are using noop notifier.
__notifier = _noop_notifier
__driver_cache = {}
__notifier_cache = {} # map: connection-string -> notifier
def notify(info):
@ -54,14 +59,24 @@ def create(connection_string, *args, **kwargs):
:param connection_string: connection string which specifies the storage
driver for notifier
:param *args: args that will be passed to the driver's __init__ method
:param **kwargs: kwargs that will be passed to the driver's __init__ method
:param args: args that will be passed to the driver's __init__ method
:param kwargs: kwargs that will be passed to the driver's __init__ method
:returns: Callable notifier method
:raises TypeError: In case of invalid name of plugin raises TypeError
"""
global __driver_cache
if connection_string not in __driver_cache:
__driver_cache[connection_string] = base.get_driver(connection_string,
*args,
**kwargs).notify
return __driver_cache[connection_string]
global __notifier_cache
if connection_string not in __notifier_cache:
try:
driver = base.get_driver(connection_string, *args, **kwargs)
__notifier_cache[connection_string] = driver.notify
LOG.info("osprofiler is enabled with connection string: %s",
connection_string)
except Exception:
LOG.exception("Could not initialize driver for connection string "
"%s, osprofiler is disabled", connection_string)
__notifier_cache[connection_string] = _noop_notifier
return __notifier_cache[connection_string]
def clear_notifier_cache():
__notifier_cache.clear()

View File

@ -23,6 +23,7 @@ class NotifierTestCase(test.TestCase):
def tearDown(self):
notifier.set(notifier._noop_notifier) # restore defaults
notifier.clear_notifier_cache()
super(NotifierTestCase, self).tearDown()
def test_set(self):
@ -49,3 +50,11 @@ class NotifierTestCase(test.TestCase):
result = notifier.create("test", 10, b=20)
mock_factory.assert_called_once_with("test", 10, b=20)
self.assertEqual(mock_factory.return_value.notify, result)
@mock.patch("osprofiler.notifier.base.get_driver")
def test_create_driver_init_failure(self, mock_get_driver):
mock_get_driver.side_effect = Exception()
result = notifier.create("test", 10, b=20)
mock_get_driver.assert_called_once_with("test", 10, b=20)
self.assertEqual(notifier._noop_notifier, result)