Enable osprofiler interface in glanceclient shell

To help end user uses profiling by glanceclient CLI directly, the
change added '--profile <HMAC_KEY>' argument to the shell.

This change also fixed a function regression, it was used to pass
necessary trace info to glance server via http header:
dbb242b776 (diff-740dd7d9149f46fe4c01ef0ab7eb3bfbL196)

In addition:
1. If client app want to enable profiling feature for glanceclient
object, please see: http://paste.openstack.org/show/85722/
2. Afer adding more trace point into Client object, as fundamental
requirement of osprofiler, what we need to notice caller is providing
correct messaging notifier in the context code.

The relevant change for glance server is ready at:
I45a19f5eb5304c2b78a9e12cbc0744941a807304

DocImpact

Change-Id: If42b69b2695a5f88536ecbc2c1b3592d9dbd880a
Signed-off-by: Zhi Yan Liu <lzy.dev@gmail.com>
This commit is contained in:
Zhi Yan Liu 2014-08-01 15:02:22 +08:00 committed by Boris Pavlovic
parent c59ba203dd
commit 9a53c1fdcb
2 changed files with 40 additions and 4 deletions
glanceclient

@ -79,11 +79,14 @@ class HTTPClient(object):
def log_curl_request(self, method, url, headers, data, kwargs):
curl = ['curl -i -X %s' % method]
for (key, value) in self.session.headers.items():
headers = copy.deepcopy(headers)
headers.update(self.session.headers)
for (key, value) in six.iteritems(headers):
if key.lower() == 'x-auth-token':
value = '*' * 3
header = '-H \'%s: %s\'' % (key, value)
curl.append(strutils.safe_encode(header))
curl.append(header)
if not self.session.verify:
curl.append('-k')
@ -98,7 +101,10 @@ class HTTPClient(object):
curl.append('-d \'%s\'' % data)
curl.append(url)
LOG.debug(strutils.safe_encode(' '.join(curl), errors='ignore'))
msg = ' '.join([strutils.safe_encode(item, errors='ignore')
for item in curl])
LOG.debug(msg)
@staticmethod
def log_http_response(resp, body=None):
@ -160,6 +166,9 @@ class HTTPClient(object):
headers['Content-Type'] = content_type
stream = True if content_type == 'application/octet-stream' else False
if osprofiler_web:
headers.update(osprofiler_web.get_trace_id_headers())
# Note(flaper87): Before letting headers / url fly,
# they should be encoded otherwise httplib will
# complain.

@ -32,6 +32,7 @@ import six.moves.urllib.parse as urlparse
import glanceclient
from glanceclient.common import utils
from glanceclient import exc
from glanceclient.openstack.common import importutils
from glanceclient.openstack.common import strutils
from keystoneclient.auth.identity import v2 as v2_auth
@ -40,6 +41,8 @@ from keystoneclient import discover
from keystoneclient.openstack.common.apiclient import exceptions as ks_exc
from keystoneclient import session
osprofiler_profiler = importutils.try_import("osprofiler.profiler")
class OpenStackImagesShell(object):
@ -255,7 +258,21 @@ class OpenStackImagesShell(object):
parser.add_argument('--os_image_api_version',
help=argparse.SUPPRESS)
# FIXME(bobt): this method should come from python-keystoneclient
if osprofiler_profiler:
parser.add_argument('--profile',
metavar='HMAC_KEY',
help='HMAC key to use for encrypting context '
'data for performance profiling of operation. '
'This key should be the value of HMAC key '
'configured in osprofiler middleware in '
'glance, it is specified in paste '
'configuration file at '
'/etc/glance/api-paste.ini and '
'/etc/glance/registry-paste.ini. Without key '
'the profiling will not be triggered even '
'if osprofiler is enabled on server side.')
# FIXME(bobt): this method should come from python-keystoneclient
self._append_global_identity_args(parser)
return parser
@ -555,6 +572,10 @@ class OpenStackImagesShell(object):
LOG.addHandler(logging.StreamHandler())
LOG.setLevel(logging.DEBUG if args.debug else logging.INFO)
profile = osprofiler_profiler and options.profile
if profile:
osprofiler_profiler.init(options.profile)
client = self._get_versioned_client(api_version, args,
force_auth=False)
@ -562,6 +583,12 @@ class OpenStackImagesShell(object):
args.func(client, args)
except exc.Unauthorized:
raise exc.CommandError("Invalid OpenStack Identity credentials.")
finally:
if profile:
trace_id = osprofiler_profiler.get().get_base_id()
print("Profiling trace ID: %s" % trace_id)
print("To display trace use next command:\n"
"osprofiler trace show --html %s " % trace_id)
@utils.arg('command', metavar='<subcommand>', nargs='?',
help='Display help for <subcommand>.')