summaryrefslogtreecommitdiff
path: root/osprofiler/drivers
diff options
context:
space:
mode:
authorBENJAMIN VANHAVERMAET <bvanhav@us.ibm.com>2016-09-01 11:11:49 -0500
committerBENJAMIN VANHAVERMAET <bvanhav@us.ibm.com>2016-11-07 06:35:52 -0600
commit1c6f8b60b279b053f75c63f1a66158108cdf4456 (patch)
tree13738ed066aefbe1a478aa5f1c0962140919621b /osprofiler/drivers
parent2a3db90cfb65fc569c4d3a9d9a19c046fc56aacf (diff)
downloadosprofiler-1c6f8b60b279b053f75c63f1a66158108cdf4456.tar.gz
Add a redis driver
Change-Id: I64768e282d5f3f32d9d79d15f59413d42df95037
Diffstat (limited to 'osprofiler/drivers')
-rw-r--r--osprofiler/drivers/__init__.py1
-rw-r--r--osprofiler/drivers/redis_driver.py137
2 files changed, 138 insertions, 0 deletions
diff --git a/osprofiler/drivers/__init__.py b/osprofiler/drivers/__init__.py
index c120b7e..f208582 100644
--- a/osprofiler/drivers/__init__.py
+++ b/osprofiler/drivers/__init__.py
@@ -3,3 +3,4 @@ from osprofiler.drivers import ceilometer # noqa
from osprofiler.drivers import elasticsearch_driver # noqa
from osprofiler.drivers import messaging # noqa
from osprofiler.drivers import mongodb # noqa
+from osprofiler.drivers import redis_driver # noqa
diff --git a/osprofiler/drivers/redis_driver.py b/osprofiler/drivers/redis_driver.py
new file mode 100644
index 0000000..f3f5812
--- /dev/null
+++ b/osprofiler/drivers/redis_driver.py
@@ -0,0 +1,137 @@
+# Copyright 2016 Mirantis Inc.
+# Copyright 2016 IBM Corporation.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from oslo_config import cfg
+from oslo_serialization import jsonutils
+import six.moves.urllib.parse as parser
+
+from osprofiler.drivers import base
+from osprofiler import exc
+
+
+class Redis(base.Driver):
+ def __init__(self, connection_str, db=0, project=None,
+ service=None, host=None, **kwargs):
+ """Redis driver for OSProfiler."""
+
+ super(Redis, self).__init__(connection_str, project=project,
+ service=service, host=host)
+ try:
+ from redis import StrictRedis
+ except ImportError:
+ raise exc.CommandError(
+ "To use this command, you should install "
+ "'redis' manually. Use command:\n "
+ "'pip install redis'.")
+
+ parsed_url = parser.urlparse(self.connection_str)
+ self.db = StrictRedis(host=parsed_url.hostname,
+ port=parsed_url.port,
+ db=db)
+ self.namespace = "osprofiler:"
+
+ @classmethod
+ def get_name(cls):
+ return "redis"
+
+ def notify(self, info):
+ """Send notifications to Redis.
+
+ :param info: Contains information about trace element.
+ In payload dict there are always 3 ids:
+ "base_id" - uuid that is common for all notifications
+ related to one trace. Used to simplify
+ retrieving of all trace elements from
+ Redis.
+ "parent_id" - uuid of parent element in trace
+ "trace_id" - uuid of current element in trace
+
+ With parent_id and trace_id it's quite simple to build
+ tree of trace elements, which simplify analyze of trace.
+
+ """
+ data = info.copy()
+ data["project"] = self.project
+ data["service"] = self.service
+ key = self.namespace + data["base_id"] + "_" + data["trace_id"] + "_" + \
+ data["timestamp"]
+ self.db.set(key, jsonutils.dumps(data))
+
+ def list_traces(self, query="*", fields=[]):
+ """Returns array of all base_id fields that match the given criteria
+
+ :param query: string that specifies the query criteria
+ :param fields: iterable of strings that specifies the output fields
+ """
+ for base_field in ["base_id", "timestamp"]:
+ if base_field not in fields:
+ fields.append(base_field)
+ ids = self.db.scan_iter(match=self.namespace + query)
+ traces = [jsonutils.loads(self.db.get(i)) for i in ids]
+ result = []
+ for trace in traces:
+ result.append({key: value for key, value in trace.iteritems()
+ if key in fields})
+ return result
+
+ def get_report(self, base_id):
+ """Retrieves and parses notification from Redis.
+
+ :param base_id: Base id of trace elements.
+ """
+ for key in self.db.scan_iter(match=self.namespace + base_id + "*"):
+ data = self.db.get(key)
+ n = jsonutils.loads(data)
+ trace_id = n["trace_id"]
+ parent_id = n["parent_id"]
+ name = n["name"]
+ project = n["project"]
+ service = n["service"]
+ host = n["info"]["host"]
+ timestamp = n["timestamp"]
+
+ self._append_results(trace_id, parent_id, name, project, service,
+ host, timestamp, n)
+
+ return self._parse_results()
+
+
+class RedisSentinel(Redis, base.Driver):
+ def __init__(self, connection_str, db=0, project=None,
+ service=None, host=None, conf=cfg.CONF, **kwargs):
+ """Redis driver for OSProfiler."""
+
+ super(RedisSentinel, self).__init__(connection_str, project=project,
+ service=service, host=host)
+ try:
+ from redis.sentinel import Sentinel
+ except ImportError:
+ raise exc.CommandError(
+ "To use this command, you should install "
+ "'redis' manually. Use command:\n "
+ "'pip install redis'.")
+
+ self.conf = conf
+ socket_timeout = self.conf.profiler.socket_timeout
+ parsed_url = parser.urlparse(self.connection_str)
+ sentinel = Sentinel([(parsed_url.hostname, int(parsed_url.port))],
+ socket_timeout=socket_timeout)
+ self.db = sentinel.master_for(self.conf.profiler.sentinel_service_name,
+ socket_timeout=socket_timeout)
+
+ @classmethod
+ def get_name(cls):
+ return "redissentinel"