From 5fd2815577c85719d6da75b1bf6a9560dcda7c3c Mon Sep 17 00:00:00 2001
From: Yujun Zhang <zhang.yujunz@zte.com.cn>
Date: Tue, 4 Jul 2017 15:27:36 +0800
Subject: [PATCH] Add option --profile to trigger profiling

Implements: blueprint osprofiler-support
Change-Id: Ia47981d6036b5425c880fc3daefb67389e99a5ec
---
 vitrageclient/client.py |  7 +++++++
 vitrageclient/shell.py  | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/vitrageclient/client.py b/vitrageclient/client.py
index 049841c..d2cc6d0 100644
--- a/vitrageclient/client.py
+++ b/vitrageclient/client.py
@@ -15,6 +15,8 @@ from vitrageclient import exc
 from keystoneauth1 import adapter as keystoneauth
 from oslo_utils import importutils
 
+profiler_web = importutils.try_import('osprofiler.web')
+
 
 # noinspection PyPep8Naming
 def Client(version, *args, **kwargs):
@@ -28,6 +30,11 @@ class VitrageClient(keystoneauth.Adapter):
     def request(self, url, method, **kwargs):
         headers = kwargs.setdefault('headers', {})
         headers.setdefault('Accept', 'application/json')
+
+        if profiler_web:
+            # no header will be added if profiler is not initialized
+            headers.update(profiler_web.get_trace_id_headers())
+
         raise_exc = kwargs.pop('raise_exc', True)
         resp = super(VitrageClient, self).request(url, method,
                                                   raise_exc=False,
diff --git a/vitrageclient/shell.py b/vitrageclient/shell.py
index 6a11746..4fa575b 100644
--- a/vitrageclient/shell.py
+++ b/vitrageclient/shell.py
@@ -27,6 +27,7 @@ import warnings
 from cliff import app
 from cliff import commandmanager
 from keystoneauth1 import loading
+from oslo_utils import importutils
 
 from vitrageclient import __version__
 from vitrageclient import auth
@@ -40,6 +41,9 @@ from vitrageclient.v1.cli import template
 from vitrageclient.v1.cli import topology
 
 
+profiler = importutils.try_import('osprofiler.profiler')
+
+
 class VitrageCommandManager(commandmanager.CommandManager):
     COMMANDS = {
         'topology show': topology.TopologyShow,
@@ -90,6 +94,22 @@ class VitrageShell(app.App):
                             default=os.environ.get('VITRAGE_API_VERSION', '1'),
                             help='Defaults to env[VITRAGE_API_VERSION] or 1.')
 
+        if profiler:
+            parser.add_argument(
+                '--profile',
+                metavar='HMAC_KEY',
+                default=os.environ.get('OS_PROFILE'),
+                help='HMAC key to use for encrypting context '
+                     'data for performance profiling of request. '
+                     'This key should be the value of the HMAC '
+                     'key configured for the osprofiler '
+                     'middleware in Vitrage api; it is specified '
+                     'in the Vitrage configuration file at'
+                     '"/etc/vitrage/vitrage.conf". Without the '
+                     'key, profiling will not be triggered even '
+                     'if osprofiler is enabled on the server '
+                     'side.')
+
         plugin = self.register_keyauth_argparse_arguments(parser)
 
         if not isinstance(plugin, auth.VitrageNoAuthLoader):
@@ -131,6 +151,19 @@ class VitrageShell(app.App):
                 endpoint_override = self.options.endpoint
             else:
                 endpoint_override = None
+
+            if hasattr(self.options, "profile"):
+                # Initialize the root of the future trace: the created trace
+                # ID will be used as the very first parent to which all
+                # related traces will be bound to. The given HMAC key must
+                # correspond to the one set in vitrage api vitrage.conf,
+                # otherwise the latter will fail to check the request
+                # signature and will skip initialization of osprofiler on the
+                # server side.
+                profiler.init(self.options.profile)
+                trace_id = profiler.get().get_base_id()
+                print("To display trace use the command:\n\n"
+                      "  osprofiler trace show --html %s " % trace_id)
             auth_plugin = loading.load_auth_from_argparse_arguments(
                 self.options)
             session = loading.load_session_from_argparse_arguments(