summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2019-11-18 17:24:16 +0000
committerGerrit Code Review <review@openstack.org>2019-11-18 17:24:16 +0000
commite022fdaa8e6c69d4b43ebba96d70936bea18db77 (patch)
tree074786c90e34ad06d0be8b581bc2c8a0a85bfab9
parent29144ca8fd900e16c28bc133e449c6b6d84c6a03 (diff)
parent34ca7ab4b5f5c04986bc97e13cf411a1e8d7334e (diff)
downloadosprofiler-e022fdaa8e6c69d4b43ebba96d70936bea18db77.tar.gz
Merge "Handle driver initialization errors to avoid service crash"2.9.0
-rw-r--r--osprofiler/drivers/elasticsearch_driver.py6
-rw-r--r--osprofiler/drivers/jaeger.py4
-rw-r--r--osprofiler/drivers/mongodb.py6
-rw-r--r--osprofiler/drivers/redis_driver.py6
-rw-r--r--osprofiler/notifier.py35
-rw-r--r--osprofiler/tests/unit/test_notifier.py9
6 files changed, 45 insertions, 21 deletions
diff --git a/osprofiler/drivers/elasticsearch_driver.py b/osprofiler/drivers/elasticsearch_driver.py
index 85bab74..c24eb60 100644
--- a/osprofiler/drivers/elasticsearch_driver.py
+++ b/osprofiler/drivers/elasticsearch_driver.py
@@ -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"))
diff --git a/osprofiler/drivers/jaeger.py b/osprofiler/drivers/jaeger.py
index 669aa13..82b7a23 100644
--- a/osprofiler/drivers/jaeger.py
+++ b/osprofiler/drivers/jaeger.py
@@ -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)
diff --git a/osprofiler/drivers/mongodb.py b/osprofiler/drivers/mongodb.py
index 7713baf..86119e4 100644
--- a/osprofiler/drivers/mongodb.py
+++ b/osprofiler/drivers/mongodb.py
@@ -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]
diff --git a/osprofiler/drivers/redis_driver.py b/osprofiler/drivers/redis_driver.py
index b8101de..c54b37b 100644
--- a/osprofiler/drivers/redis_driver.py
+++ b/osprofiler/drivers/redis_driver.py
@@ -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]
diff --git a/osprofiler/notifier.py b/osprofiler/notifier.py
index 3bd4412..8b909f0 100644
--- a/osprofiler/notifier.py
+++ b/osprofiler/notifier.py
@@ -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()
diff --git a/osprofiler/tests/unit/test_notifier.py b/osprofiler/tests/unit/test_notifier.py
index 7cccdad..8e658fe 100644
--- a/osprofiler/tests/unit/test_notifier.py
+++ b/osprofiler/tests/unit/test_notifier.py
@@ -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)