Integrate OSprofiler with Zaqar
*) Add osprofiler wsgi middleware This middleware is used for 2 things: 1) It checks that person who want to trace is trusted and knows secret HMAC key. 2) It start tracing in case of proper trace headers and add first wsgi trace point, with info about HTTP request. *) Add initialization of osprofiler at start of server Initialize and set an oslo.messaging based notifier instance to osprofiler which be used to send notifications to Ceilometer. *) Enable profile on existing useful storage backends Change controller creation logic of data and control panel for mongodb, redis and sqlalchemy storage backends, as well as an aggregative pooling driver. *) Add options to allow operator control profiles separately NOTE to test this: 1) You have to enable necessary profiler option(s) base on your needed. 2) You need to enable follow services in localrc for devstack: CEILOMETER_NOTIFICATION_TOPICS=notifications,profiler ENABLED_SERVICES+=,ceilometer-acompute,ceilometer-acentral ENABLED_SERVICES+=,ceilometer-anotification,ceilometer-collector ENABLED_SERVICES+=,ceilometer-alarm-evaluator,ceilometer-alarm-notifier ENABLED_SERVICES+=,ceilometer-api 3) You should use python-zaqarclient with this change: I880c003511e9e4ef99806ba5b19d0ef6996be80b Run any command with --os-profile <SECRET_KEY> $ openstack --os-profile <SECRET_KEY> queue list # it will print <Trace ID> Get pretty HTML with traces: $ osprofiler trace show --html <Trace ID> note that osprofiler should be run from admin user name & tenant. DocImpact Partially-implements BP: osprofiler Change-Id: I32565de6c447cd5e95a0ef54a9fbd4e571c2d820 Co-Authored-By: wangxiyuan <wangxiyuan@huawei.com>
This commit is contained in:
parent
cd3adce177
commit
47324171d4
@ -13,3 +13,5 @@ namespace = zaqar.transport.base
|
||||
namespace = zaqar.transport.validation
|
||||
namespace = keystonemiddleware.auth_token
|
||||
namespace = oslo.cache
|
||||
namespace = oslo.messaging
|
||||
namespace = osprofiler
|
||||
|
@ -18,9 +18,11 @@ oslo.config!=3.18.0,>=3.14.0 # Apache-2.0
|
||||
oslo.context>=2.9.0 # Apache-2.0
|
||||
oslo.i18n>=2.1.0 # Apache-2.0
|
||||
oslo.log>=3.11.0 # Apache-2.0
|
||||
oslo.messaging>=5.2.0 # Apache-2.0
|
||||
oslo.serialization>=1.10.0 # Apache-2.0
|
||||
oslo.utils>=3.18.0 # Apache-2.0
|
||||
oslo.policy>=1.15.0 # Apache-2.0
|
||||
osprofiler>=1.4.0 # Apache-2.0
|
||||
SQLAlchemy<1.1.0,>=1.0.10 # MIT
|
||||
enum34;python_version=='2.7' or python_version=='2.6' or python_version=='3.3' # BSD
|
||||
trollius>=1.0 # Apache-2.0
|
||||
|
@ -30,3 +30,6 @@ os-api-ref>=1.0.0 # Apache-2.0
|
||||
|
||||
# Tempest
|
||||
tempest>=12.1.0 # Apache-2.0
|
||||
|
||||
#OSprofiler
|
||||
osprofiler>=1.4.0 # Apache-2.0
|
||||
|
@ -13,7 +13,11 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import socket
|
||||
|
||||
from oslo_log import log
|
||||
from osprofiler import opts as profiler_opts
|
||||
from osprofiler import profiler
|
||||
from stevedore import driver
|
||||
|
||||
from zaqar.api import handler
|
||||
@ -22,6 +26,7 @@ from zaqar.common import configs
|
||||
from zaqar.common import consts
|
||||
from zaqar.common import decorators
|
||||
from zaqar.common import errors
|
||||
from zaqar import profile
|
||||
from zaqar.storage import pipeline
|
||||
from zaqar.storage import pooling
|
||||
from zaqar.storage import utils as storage_utils
|
||||
@ -45,6 +50,11 @@ class Bootstrap(object):
|
||||
|
||||
for group, opts in configs._config_options():
|
||||
self.conf.register_opts(opts, group=group)
|
||||
profiler_opts.set_defaults(self.conf)
|
||||
|
||||
# TODO(wangxiyuan): Now the OSprofiler feature in Zaqar only support
|
||||
# wsgi. Websockt part will be added in the future.
|
||||
profile.setup(self.conf, 'Zaqar-server', socket.gethostname())
|
||||
|
||||
self.driver_conf = self.conf[configs._DRIVER_GROUP]
|
||||
|
||||
@ -62,6 +72,9 @@ class Bootstrap(object):
|
||||
LOG.debug(u'Storage pooling enabled')
|
||||
storage_driver = pooling.DataDriver(self.conf, self.cache,
|
||||
self.control)
|
||||
if self.conf.profiler.enabled:
|
||||
storage_driver = profiler.trace_cls("pooling_data_"
|
||||
"driver")(storage_driver)
|
||||
else:
|
||||
storage_driver = storage_utils.load_storage_driver(
|
||||
self.conf, self.cache, control_driver=self.control)
|
||||
|
@ -71,9 +71,22 @@ _NOTIFICATION_OPTIONS = (
|
||||
|
||||
_NOTIFICATION_GROUP = 'notification'
|
||||
|
||||
_PROFILER_OPTIONS = [
|
||||
cfg.BoolOpt("trace_wsgi_transport", default=False,
|
||||
help="If False doesn't trace any transport requests."
|
||||
"Please note that it doesn't work for websocket now."),
|
||||
cfg.BoolOpt("trace_message_store", default=False,
|
||||
help="If False doesn't trace any message store requests."),
|
||||
cfg.BoolOpt("trace_management_store", default=False,
|
||||
help="If False doesn't trace any management store requests.")
|
||||
]
|
||||
|
||||
_PROFILER_GROUP = "profiler"
|
||||
|
||||
|
||||
def _config_options():
|
||||
return [(None, _GENERAL_OPTIONS),
|
||||
(_DRIVER_GROUP, _DRIVER_OPTIONS),
|
||||
(_SIGNED_URL_GROUP, _SIGNED_URL_OPTIONS),
|
||||
(_NOTIFICATION_GROUP, _NOTIFICATION_OPTIONS)]
|
||||
(_NOTIFICATION_GROUP, _NOTIFICATION_OPTIONS),
|
||||
(_PROFILER_GROUP, _PROFILER_OPTIONS)]
|
||||
|
116
zaqar/profile.py
Normal file
116
zaqar/profile.py
Normal file
@ -0,0 +1,116 @@
|
||||
# Copyright 2016 OpenStack, Inc.
|
||||
# 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.
|
||||
|
||||
import six
|
||||
import six.moves.urllib.parse as urlparse
|
||||
import webob
|
||||
|
||||
from oslo_log import log
|
||||
from osprofiler import _utils as utils
|
||||
from osprofiler import notifier
|
||||
from osprofiler import profiler
|
||||
from osprofiler import web
|
||||
from zaqar.i18n import _LW
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
def setup(conf, binary, host):
|
||||
if conf.profiler.enabled:
|
||||
|
||||
# Note(wangxiyuan): OSprofiler now support some kind of backends, such
|
||||
# as Ceilometer, ElasticSearch, Messaging and MongoDB.
|
||||
# 1. Ceilometer is only used for data collection, and Messaging is only
|
||||
# used for data transfer. So Ceilometer only works when Messaging is
|
||||
# enabled.
|
||||
# 2. ElasticSearch and MongoDB support both data collection and
|
||||
# transfer. So they can be used standalone.
|
||||
# 3. Choose which backend depends on the config option
|
||||
# "connection_string" , and the default value is "messaging://".
|
||||
backend_uri = conf.profiler.connection_string
|
||||
if "://" not in backend_uri:
|
||||
backend_uri += "://"
|
||||
parsed_connection = urlparse.urlparse(backend_uri)
|
||||
backend_type = parsed_connection.scheme
|
||||
if backend_type == "messaging":
|
||||
import oslo_messaging
|
||||
_notifier = notifier.create(backend_uri, oslo_messaging, {},
|
||||
oslo_messaging.get_transport(conf),
|
||||
"Zaqar", binary, host)
|
||||
else:
|
||||
_notifier = notifier.create(backend_uri, project="Zaqar",
|
||||
service=binary, host=host)
|
||||
notifier.set(_notifier)
|
||||
LOG.warning(_LW("OSProfiler is enabled.\nIt means that person who "
|
||||
"knows any of hmac_keys that are specified in "
|
||||
"/etc/zaqar/zaqar.conf can trace his requests. \n In "
|
||||
"real life only operator can read this file so there "
|
||||
"is no security issue. Note that even if person can "
|
||||
"trigger profiler, only admin user can retrieve trace "
|
||||
"information.\n"
|
||||
"To disable OSprofiler set in zaqar.conf:\n"
|
||||
"[profiler]\nenabled=false"))
|
||||
web.enable(conf.profiler.hmac_keys)
|
||||
else:
|
||||
web.disable()
|
||||
|
||||
|
||||
class ProfileWSGIMiddleware(object):
|
||||
|
||||
def __init__(self, application, hmac_keys=None, enabled=False):
|
||||
self.application = application
|
||||
self.name = "wsgi"
|
||||
self.enabled = enabled
|
||||
self.hmac_keys = utils.split(hmac_keys or "")
|
||||
|
||||
def _trace_is_valid(self, trace_info):
|
||||
if not isinstance(trace_info, dict):
|
||||
return False
|
||||
trace_keys = set(six.iterkeys(trace_info))
|
||||
if not all(k in trace_keys for k in web._REQUIRED_KEYS):
|
||||
return False
|
||||
if trace_keys.difference(web._REQUIRED_KEYS + web._OPTIONAL_KEYS):
|
||||
return False
|
||||
return True
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
request = webob.Request(environ)
|
||||
trace_info = utils.signed_unpack(request.headers.get(web.X_TRACE_INFO),
|
||||
request.headers.get(web.X_TRACE_HMAC),
|
||||
self.hmac_keys)
|
||||
|
||||
if not self._trace_is_valid(trace_info):
|
||||
return self.application(environ, start_response)
|
||||
|
||||
profiler.init(**trace_info)
|
||||
info = {
|
||||
"request": {
|
||||
"path": request.path,
|
||||
"query": request.query_string,
|
||||
"method": request.method,
|
||||
"scheme": request.scheme
|
||||
}
|
||||
}
|
||||
with profiler.Trace(self.name, info=info):
|
||||
return self.application(environ, start_response)
|
||||
|
||||
|
||||
def install_wsgi_tracer(app, conf):
|
||||
enabled = conf.profiler.enabled and conf.profiler.trace_wsgi_transport
|
||||
|
||||
if enabled:
|
||||
LOG.debug(u'Installing osprofiler\'s wsgi tracer')
|
||||
|
||||
return ProfileWSGIMiddleware(app, conf.profiler.hmac_keys, enabled=enabled)
|
@ -17,6 +17,7 @@
|
||||
|
||||
import ssl
|
||||
|
||||
from osprofiler import profiler
|
||||
import pymongo
|
||||
import pymongo.errors
|
||||
|
||||
@ -184,15 +185,31 @@ class DataDriver(storage.DataDriverBase):
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def message_controller(self):
|
||||
return controllers.MessageController(self)
|
||||
controller = controllers.MessageController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
self.conf.profiler.trace_message_store):
|
||||
return profiler.trace_cls("mongodb_message_controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def claim_controller(self):
|
||||
return controllers.ClaimController(self)
|
||||
controller = controllers.ClaimController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
self.conf.profiler.trace_message_store):
|
||||
return profiler.trace_cls("mongodb_claim_controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def subscription_controller(self):
|
||||
return controllers.SubscriptionController(self)
|
||||
controller = controllers.SubscriptionController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
self.conf.profiler.trace_message_store):
|
||||
return profiler.trace_cls("mongodb_subscription_"
|
||||
"controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
|
||||
class FIFODataDriver(DataDriver):
|
||||
@ -206,7 +223,12 @@ class FIFODataDriver(DataDriver):
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def message_controller(self):
|
||||
return controllers.FIFOMessageController(self)
|
||||
controller = controllers.FIFOMessageController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
self.conf.profiler.trace_message_store):
|
||||
return profiler.trace_cls("mongodb_message_controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
|
||||
class ControlDriver(storage.ControlDriverBase):
|
||||
@ -245,16 +267,38 @@ class ControlDriver(storage.ControlDriverBase):
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def queue_controller(self):
|
||||
return controllers.QueueController(self)
|
||||
controller = controllers.QueueController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
(self.conf.profiler.trace_message_store or
|
||||
self.conf.profiler.trace_management_store)):
|
||||
return profiler.trace_cls("mongodb_queues_controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
@property
|
||||
def pools_controller(self):
|
||||
return controllers.PoolsController(self)
|
||||
controller = controllers.PoolsController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
self.conf.profiler.trace_management_store):
|
||||
return profiler.trace_cls("mongodb_pools_controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
@property
|
||||
def catalogue_controller(self):
|
||||
return controllers.CatalogueController(self)
|
||||
controller = controllers.CatalogueController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
self.conf.profiler.trace_management_store):
|
||||
return profiler.trace_cls("mongodb_catalogue_"
|
||||
"controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
@property
|
||||
def flavors_controller(self):
|
||||
return controllers.FlavorsController(self)
|
||||
controller = controllers.FlavorsController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
self.conf.profiler.trace_management_store):
|
||||
return profiler.trace_cls("mongodb_flavors_controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from osprofiler import profiler
|
||||
from stevedore import driver
|
||||
from stevedore import extension
|
||||
|
||||
@ -85,7 +86,7 @@ def _get_storage_pipeline(resource_name, conf, *args, **kwargs):
|
||||
return pipeline
|
||||
|
||||
|
||||
def _get_builtin_entry_points(resource_name, storage, control_driver):
|
||||
def _get_builtin_entry_points(resource_name, storage, control_driver, conf):
|
||||
# Load builtin stages
|
||||
builtin_entry_points = []
|
||||
|
||||
@ -104,7 +105,9 @@ def _get_builtin_entry_points(resource_name, storage, control_driver):
|
||||
|
||||
for ext in extensions.extensions:
|
||||
builtin_entry_points.append(ext.obj)
|
||||
|
||||
if conf.profiler.enabled and conf.profiler.trace_message_store:
|
||||
return (profiler.trace_cls("stages_controller")
|
||||
(builtin_entry_points))
|
||||
return builtin_entry_points
|
||||
|
||||
|
||||
@ -138,7 +141,7 @@ class DataDriver(base.DataDriverBase):
|
||||
@decorators.lazy_property(write=False)
|
||||
def queue_controller(self):
|
||||
stages = _get_builtin_entry_points('queue', self._storage,
|
||||
self.control_driver)
|
||||
self.control_driver, self.conf)
|
||||
stages.extend(_get_storage_pipeline('queue', self.conf))
|
||||
stages.append(self._storage.queue_controller)
|
||||
return common.Pipeline(stages)
|
||||
@ -146,7 +149,7 @@ class DataDriver(base.DataDriverBase):
|
||||
@decorators.lazy_property(write=False)
|
||||
def message_controller(self):
|
||||
stages = _get_builtin_entry_points('message', self._storage,
|
||||
self.control_driver)
|
||||
self.control_driver, self.conf)
|
||||
kwargs = {'subscription_controller':
|
||||
self._storage.subscription_controller,
|
||||
'max_notifier_workers':
|
||||
@ -160,7 +163,7 @@ class DataDriver(base.DataDriverBase):
|
||||
@decorators.lazy_property(write=False)
|
||||
def claim_controller(self):
|
||||
stages = _get_builtin_entry_points('claim', self._storage,
|
||||
self.control_driver)
|
||||
self.control_driver, self.conf)
|
||||
stages.extend(_get_storage_pipeline('claim', self.conf))
|
||||
stages.append(self._storage.claim_controller)
|
||||
return common.Pipeline(stages)
|
||||
@ -168,7 +171,7 @@ class DataDriver(base.DataDriverBase):
|
||||
@decorators.lazy_property(write=False)
|
||||
def subscription_controller(self):
|
||||
stages = _get_builtin_entry_points('subscription', self._storage,
|
||||
self.control_driver)
|
||||
self.control_driver, self.conf)
|
||||
stages.extend(_get_storage_pipeline('subscription', self.conf))
|
||||
stages.append(self._storage.subscription_controller)
|
||||
return common.Pipeline(stages)
|
||||
|
@ -18,6 +18,7 @@ import itertools
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
from osprofiler import profiler
|
||||
|
||||
from zaqar.common import decorators
|
||||
from zaqar.common import errors as cerrors
|
||||
@ -74,7 +75,11 @@ class DataDriver(storage.DataDriverBase):
|
||||
|
||||
def __init__(self, conf, cache, control, control_driver=None):
|
||||
super(DataDriver, self).__init__(conf, cache, control_driver)
|
||||
self._pool_catalog = Catalog(conf, cache, control)
|
||||
catalog = Catalog(conf, cache, control)
|
||||
if self.conf.profiler.enabled:
|
||||
catalog = profiler.trace_cls("pooling_catalogue_"
|
||||
"controller")(catalog)
|
||||
self._pool_catalog = catalog
|
||||
|
||||
@property
|
||||
def capabilities(self):
|
||||
@ -121,19 +126,36 @@ class DataDriver(storage.DataDriverBase):
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def queue_controller(self):
|
||||
return QueueController(self._pool_catalog)
|
||||
controller = QueueController(self._pool_catalog)
|
||||
if self.conf.profiler.enabled:
|
||||
return profiler.trace_cls("pooling_queue_controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def message_controller(self):
|
||||
return MessageController(self._pool_catalog)
|
||||
controller = MessageController(self._pool_catalog)
|
||||
if self.conf.profiler.enabled:
|
||||
return profiler.trace_cls("pooling_message_controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def claim_controller(self):
|
||||
return ClaimController(self._pool_catalog)
|
||||
controller = ClaimController(self._pool_catalog)
|
||||
if self.conf.profiler.enabled:
|
||||
return profiler.trace_cls("pooling_claim_controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def subscription_controller(self):
|
||||
return SubscriptionController(self._pool_catalog)
|
||||
controller = SubscriptionController(self._pool_catalog)
|
||||
if self.conf.profiler.enabled:
|
||||
return (profiler.trace_cls("pooling_subscription_controller")
|
||||
(controller))
|
||||
else:
|
||||
return controller
|
||||
|
||||
|
||||
class QueueController(storage.Queue):
|
||||
|
@ -12,6 +12,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from osprofiler import profiler
|
||||
import redis
|
||||
import redis.sentinel
|
||||
from six.moves import urllib
|
||||
@ -198,15 +199,31 @@ class DataDriver(storage.DataDriverBase):
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def message_controller(self):
|
||||
return controllers.MessageController(self)
|
||||
controller = controllers.MessageController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
self.conf.profiler.trace_message_store):
|
||||
return profiler.trace_cls("redis_message_controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def claim_controller(self):
|
||||
return controllers.ClaimController(self)
|
||||
controller = controllers.ClaimController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
self.conf.profiler.trace_message_store):
|
||||
return profiler.trace_cls("redis_claim_controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def subscription_controller(self):
|
||||
return controllers.SubscriptionController(self)
|
||||
controller = controllers.SubscriptionController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
self.conf.profiler.trace_message_store):
|
||||
return profiler.trace_cls("mongodb_subscription_"
|
||||
"controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
|
||||
class ControlDriver(storage.ControlDriverBase):
|
||||
@ -229,7 +246,13 @@ class ControlDriver(storage.ControlDriverBase):
|
||||
|
||||
@decorators.lazy_property(write=False)
|
||||
def queue_controller(self):
|
||||
return controllers.QueueController(self)
|
||||
controller = controllers.QueueController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
(self.conf.profiler.trace_message_store or
|
||||
self.conf.profiler.trace_management_store)):
|
||||
return profiler.trace_cls("redis_queue_controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
@property
|
||||
def pools_controller(self):
|
||||
|
@ -13,6 +13,8 @@
|
||||
# License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
|
||||
from osprofiler import profiler
|
||||
from osprofiler import sqlalchemy as sa_tracer
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.orm import scoped_session
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
@ -60,6 +62,11 @@ class ControlDriver(storage.ControlDriverBase):
|
||||
self._mysql_on_connect)
|
||||
|
||||
tables.metadata.create_all(engine, checkfirst=True)
|
||||
|
||||
if (self.conf.profiler.enabled and
|
||||
self.conf.profiler.trace_message_store):
|
||||
sa_tracer.add_tracing(sa, engine, "db")
|
||||
|
||||
return engine
|
||||
|
||||
# TODO(cpp-cabrera): expose connect/close as a context manager
|
||||
@ -81,20 +88,41 @@ class ControlDriver(storage.ControlDriverBase):
|
||||
|
||||
@property
|
||||
def pools_controller(self):
|
||||
return controllers.PoolsController(self)
|
||||
controller = controllers.PoolsController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
self.conf.profiler.trace_management_store):
|
||||
return profiler.trace_cls("sqlalchemy_pools_"
|
||||
"controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
@property
|
||||
def queue_controller(self):
|
||||
return controllers.QueueController(self)
|
||||
controller = controllers.QueueController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
(self.conf.profiler.trace_message_store or
|
||||
self.conf.profiler.trace_management_store)):
|
||||
return profiler.trace_cls("sqlalchemy_queue_"
|
||||
"controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
@property
|
||||
def catalogue_controller(self):
|
||||
return controllers.CatalogueController(self)
|
||||
controller = controllers.CatalogueController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
self.conf.profiler.trace_management_store):
|
||||
return profiler.trace_cls("sqlalchemy_catalogue_"
|
||||
"controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
||||
@property
|
||||
def flavors_controller(self):
|
||||
return controllers.FlavorsController(self)
|
||||
|
||||
@property
|
||||
def subscriptions_controller(self):
|
||||
pass
|
||||
controller = controllers.FlavorsController(self)
|
||||
if (self.conf.profiler.enabled and
|
||||
self.conf.profiler.trace_management_store):
|
||||
return profiler.trace_cls("sqlalchemy_flavors_"
|
||||
"controller")(controller)
|
||||
else:
|
||||
return controller
|
||||
|
@ -16,6 +16,7 @@ import copy
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
from osprofiler import profiler
|
||||
import six
|
||||
from stevedore import driver
|
||||
|
||||
@ -139,7 +140,14 @@ def load_storage_driver(conf, cache, storage_type=None,
|
||||
invoke_on_load=True,
|
||||
invoke_args=_invoke_args)
|
||||
|
||||
return mgr.driver
|
||||
if conf.profiler.enabled:
|
||||
if ((mode == "control" and conf.profiler.trace_management_store) or
|
||||
(mode == "data" and conf.profiler.trace_message_store)):
|
||||
trace_name = '{0}_{1}_driver'.format(storage_type, mode)
|
||||
return profiler.trace_cls(trace_name,
|
||||
trace_private=True)(mgr.driver)
|
||||
else:
|
||||
return mgr.driver
|
||||
|
||||
except Exception as exc:
|
||||
LOG.error(_LE('Failed to load "{}" driver for "{}"').format(
|
||||
|
@ -18,6 +18,7 @@ import os
|
||||
import fixtures
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
from osprofiler import opts
|
||||
import testtools
|
||||
|
||||
from zaqar.common import configs
|
||||
@ -62,6 +63,9 @@ class TestBase(testtools.TestCase):
|
||||
group=configs._NOTIFICATION_GROUP)
|
||||
self.conf.register_opts(configs._SIGNED_URL_OPTIONS,
|
||||
group=configs._SIGNED_URL_GROUP)
|
||||
opts.set_defaults(self.conf)
|
||||
self.conf.register_opts(configs._PROFILER_OPTIONS,
|
||||
group=configs._PROFILER_GROUP)
|
||||
|
||||
self.mongodb_url = os.environ.get('ZAQAR_TEST_MONGODB_URL',
|
||||
'mongodb://127.0.0.1:27017')
|
||||
|
@ -35,11 +35,14 @@ class TestUtils(testing.TestBase):
|
||||
|
||||
@testing.requires_redis
|
||||
def test_can_connect_succeeds_if_good_uri_redis(self):
|
||||
self.assertTrue(utils.can_connect('redis://localhost'))
|
||||
self.assertTrue(utils.can_connect('redis://localhost:6379'))
|
||||
self.assertTrue(utils.can_connect('redis://localhost',
|
||||
conf=self.conf))
|
||||
self.assertTrue(utils.can_connect('redis://localhost:6379',
|
||||
conf=self.conf))
|
||||
|
||||
def test_can_connect_fails_if_bad_uri_missing_schema(self):
|
||||
self.assertFalse(utils.can_connect('localhost:27017'))
|
||||
self.assertFalse(utils.can_connect('localhost:27017',
|
||||
conf=self.conf))
|
||||
|
||||
@testing.requires_mongodb
|
||||
def test_can_connect_fails_if_bad_uri_mongodb(self):
|
||||
@ -53,5 +56,7 @@ class TestUtils(testing.TestBase):
|
||||
|
||||
@testing.requires_redis
|
||||
def test_can_connect_fails_if_bad_uri_redis(self):
|
||||
self.assertFalse(utils.can_connect('redis://localhost:8080'))
|
||||
self.assertFalse(utils.can_connect('redis://example.com:6379'))
|
||||
self.assertFalse(utils.can_connect('redis://localhost:8080',
|
||||
conf=self.conf))
|
||||
self.assertFalse(utils.can_connect('redis://example.com:6379',
|
||||
conf=self.conf))
|
||||
|
@ -26,6 +26,7 @@ import socket
|
||||
from zaqar.common import decorators
|
||||
from zaqar.common.transport.wsgi import helpers
|
||||
from zaqar.i18n import _
|
||||
from zaqar import profile
|
||||
from zaqar import transport
|
||||
from zaqar.transport import acl
|
||||
from zaqar.transport import auth
|
||||
@ -138,8 +139,12 @@ class Driver(transport.DriverBase):
|
||||
def _init_middleware(self):
|
||||
"""Initialize WSGI middlewarez."""
|
||||
|
||||
auth_app = self.app
|
||||
# NOTE(zhiyan): Install Profiler
|
||||
if (self._conf.profiler.enabled and
|
||||
self._conf.profiler.trace_wsgi_transport):
|
||||
self.app = profile.install_wsgi_tracer(self.app, self._conf)
|
||||
|
||||
auth_app = self.app
|
||||
# NOTE(flaper87): Install Auth
|
||||
if self._conf.auth_strategy:
|
||||
strategy = auth.strategy(self._conf.auth_strategy)
|
||||
|
Loading…
x
Reference in New Issue
Block a user