deb-zaqar/zaqar/profile.py
Zhi Yan Liu 47324171d4 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>
2016-11-18 08:33:31 +00:00

117 lines
4.6 KiB
Python

# 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)