*) 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 serivce Set's olso.messaging notifer instance (to send notifications to Ceilometer) *) Fix fake notifier NOTE to test this: You should put to localrc: RECLONE=no CEILOMETER_NOTIFICATION_TOPICS=notifications,profiler ENABLED_SERVICES+=,ceilometer-acompute,ceilometer-acentral,ceilometer-anotification,ceilometer-collector ENABLED_SERVICES+=,ceilometer-alarm-evaluator,ceilometer-alarm-notifier ENABLED_SERVICES+=,ceilometer-api You should use python-cinderclient with this patch: https://review.openstack.org/#/c/103359/ Run any command with --profile SECRET_KEY $ cinder --profile SECRET_KEY create 1 # it will print <Trace ID> Get pretty HTML with traces: $ osprofiler trace show --html <Profile ID> note that osprofiler should be run from admin user name & tenant. Change-Id: Ic3ce587946eaa7e6b19cf35a2cc905ae5de29dd3
		
			
				
	
	
		
			167 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			167 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Copyright 2013 Red Hat, Inc.
 | 
						|
#
 | 
						|
#    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.
 | 
						|
 | 
						|
__all__ = [
 | 
						|
    'init',
 | 
						|
    'cleanup',
 | 
						|
    'set_defaults',
 | 
						|
    'add_extra_exmods',
 | 
						|
    'clear_extra_exmods',
 | 
						|
    'get_allowed_exmods',
 | 
						|
    'RequestContextSerializer',
 | 
						|
    'get_client',
 | 
						|
    'get_server',
 | 
						|
    'get_notifier',
 | 
						|
    'TRANSPORT_ALIASES',
 | 
						|
]
 | 
						|
 | 
						|
from oslo.config import cfg
 | 
						|
from oslo import messaging
 | 
						|
from osprofiler import profiler
 | 
						|
 | 
						|
import cinder.context
 | 
						|
import cinder.exception
 | 
						|
from cinder.openstack.common import jsonutils
 | 
						|
 | 
						|
CONF = cfg.CONF
 | 
						|
TRANSPORT = None
 | 
						|
NOTIFIER = None
 | 
						|
 | 
						|
ALLOWED_EXMODS = [
 | 
						|
    cinder.exception.__name__,
 | 
						|
]
 | 
						|
EXTRA_EXMODS = []
 | 
						|
 | 
						|
# NOTE(flaper87): The cinder.openstack.common.rpc entries are
 | 
						|
# for backwards compat with Havana rpc_backend configuration
 | 
						|
# values. The cinder.rpc entries are for compat with Folsom values.
 | 
						|
TRANSPORT_ALIASES = {
 | 
						|
    'cinder.openstack.common.rpc.impl_kombu': 'rabbit',
 | 
						|
    'cinder.openstack.common.rpc.impl_qpid': 'qpid',
 | 
						|
    'cinder.openstack.common.rpc.impl_zmq': 'zmq',
 | 
						|
    'cinder.rpc.impl_kombu': 'rabbit',
 | 
						|
    'cinder.rpc.impl_qpid': 'qpid',
 | 
						|
    'cinder.rpc.impl_zmq': 'zmq',
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
def init(conf):
 | 
						|
    global TRANSPORT, NOTIFIER
 | 
						|
    exmods = get_allowed_exmods()
 | 
						|
    TRANSPORT = messaging.get_transport(conf,
 | 
						|
                                        allowed_remote_exmods=exmods,
 | 
						|
                                        aliases=TRANSPORT_ALIASES)
 | 
						|
 | 
						|
    serializer = RequestContextSerializer(JsonPayloadSerializer())
 | 
						|
    NOTIFIER = messaging.Notifier(TRANSPORT, serializer=serializer)
 | 
						|
 | 
						|
 | 
						|
def initialized():
 | 
						|
    return None not in [TRANSPORT, NOTIFIER]
 | 
						|
 | 
						|
 | 
						|
def cleanup():
 | 
						|
    global TRANSPORT, NOTIFIER
 | 
						|
    assert TRANSPORT is not None
 | 
						|
    assert NOTIFIER is not None
 | 
						|
    TRANSPORT.cleanup()
 | 
						|
    TRANSPORT = NOTIFIER = None
 | 
						|
 | 
						|
 | 
						|
def set_defaults(control_exchange):
 | 
						|
    messaging.set_transport_defaults(control_exchange)
 | 
						|
 | 
						|
 | 
						|
def add_extra_exmods(*args):
 | 
						|
    EXTRA_EXMODS.extend(args)
 | 
						|
 | 
						|
 | 
						|
def clear_extra_exmods():
 | 
						|
    del EXTRA_EXMODS[:]
 | 
						|
 | 
						|
 | 
						|
def get_allowed_exmods():
 | 
						|
    return ALLOWED_EXMODS + EXTRA_EXMODS
 | 
						|
 | 
						|
 | 
						|
class JsonPayloadSerializer(messaging.NoOpSerializer):
 | 
						|
    @staticmethod
 | 
						|
    def serialize_entity(context, entity):
 | 
						|
        return jsonutils.to_primitive(entity, convert_instances=True)
 | 
						|
 | 
						|
 | 
						|
class RequestContextSerializer(messaging.Serializer):
 | 
						|
 | 
						|
    def __init__(self, base):
 | 
						|
        self._base = base
 | 
						|
 | 
						|
    def serialize_entity(self, context, entity):
 | 
						|
        if not self._base:
 | 
						|
            return entity
 | 
						|
        return self._base.serialize_entity(context, entity)
 | 
						|
 | 
						|
    def deserialize_entity(self, context, entity):
 | 
						|
        if not self._base:
 | 
						|
            return entity
 | 
						|
        return self._base.deserialize_entity(context, entity)
 | 
						|
 | 
						|
    def serialize_context(self, context):
 | 
						|
        _context = context.to_dict()
 | 
						|
        prof = profiler.get()
 | 
						|
        if prof:
 | 
						|
            trace_info = {
 | 
						|
                "hmac_key": prof.hmac_key,
 | 
						|
                "base_id": prof.get_base_id(),
 | 
						|
                "parent_id": prof.get_id()
 | 
						|
            }
 | 
						|
            _context.update({"trace_info": trace_info})
 | 
						|
        return _context
 | 
						|
 | 
						|
    def deserialize_context(self, context):
 | 
						|
        trace_info = context.pop("trace_info", None)
 | 
						|
        if trace_info:
 | 
						|
            profiler.init(**trace_info)
 | 
						|
 | 
						|
        return cinder.context.RequestContext.from_dict(context)
 | 
						|
 | 
						|
 | 
						|
def get_transport_url(url_str=None):
 | 
						|
    return messaging.TransportURL.parse(CONF, url_str, TRANSPORT_ALIASES)
 | 
						|
 | 
						|
 | 
						|
def get_client(target, version_cap=None, serializer=None):
 | 
						|
    assert TRANSPORT is not None
 | 
						|
    serializer = RequestContextSerializer(serializer)
 | 
						|
    return messaging.RPCClient(TRANSPORT,
 | 
						|
                               target,
 | 
						|
                               version_cap=version_cap,
 | 
						|
                               serializer=serializer)
 | 
						|
 | 
						|
 | 
						|
def get_server(target, endpoints, serializer=None):
 | 
						|
    assert TRANSPORT is not None
 | 
						|
    serializer = RequestContextSerializer(serializer)
 | 
						|
    return messaging.get_rpc_server(TRANSPORT,
 | 
						|
                                    target,
 | 
						|
                                    endpoints,
 | 
						|
                                    executor='eventlet',
 | 
						|
                                    serializer=serializer)
 | 
						|
 | 
						|
 | 
						|
def get_notifier(service=None, host=None, publisher_id=None):
 | 
						|
    assert NOTIFIER is not None
 | 
						|
    if not publisher_id:
 | 
						|
        publisher_id = "%s.%s" % (service, host or CONF.host)
 | 
						|
    return NOTIFIER.prepare(publisher_id=publisher_id)
 |