Merge "add trace_requests option to debug section"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index c4dad7e..2fdbb7e 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -421,6 +421,22 @@
 # Enable diagnostic commands (boolean value)
 #enable=true
 
+# A regex to determine which requests should be traced.  This
+# is a regex to match the caller for rest client requests to
+# be able to selectively trace calls out of specific classes
+# and methods. It largely exists for test development, and is
+# not expected to be used in a real deploy of tempest. This
+# will be matched against the discovered ClassName:method in
+# the test environment.  Expected values for this field are:
+# * ClassName:test_method_name - traces one test_method  *
+# ClassName:setUp(Class) - traces specific setup functions  *
+# ClassName:tearDown(Class) - traces specific teardown
+# functions  * ClassName:_run_cleanups - traces the cleanup
+# functions  If nothing is specified, this feature is not
+# enabled. To trace everything specify .* as the regex.
+# (string value)
+#trace_requests=
+
 
 [identity]
 
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index 35d4ff2..830968e 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -281,24 +281,50 @@
                 return resp[i]
         return ""
 
-    def _log_request(self, method, req_url, resp, secs=""):
+    def _log_request(self, method, req_url, resp,
+                     secs="", req_headers=None,
+                     req_body=None, resp_body=None):
         # if we have the request id, put it in the right part of the log
         extra = dict(request_id=self._get_request_id(resp))
         # NOTE(sdague): while we still have 6 callers to this function
         # we're going to just provide work around on who is actually
         # providing timings by gracefully adding no content if they don't.
         # Once we're down to 1 caller, clean this up.
+        caller_name = self._find_caller()
         if secs:
             secs = " %.3fs" % secs
         self.LOG.info(
             'Request (%s): %s %s %s%s' % (
-                self._find_caller(),
+                caller_name,
                 resp['status'],
                 method,
                 req_url,
                 secs),
             extra=extra)
 
+        # We intentionally duplicate the info content because in a parallel
+        # world this is important to match
+        trace_regex = CONF.debug.trace_requests
+        if trace_regex and re.search(trace_regex, caller_name):
+            log_fmt = """Request (%s): %s %s %s%s
+    Request - Headers: %s
+        Body: %s
+    Response - Headers: %s
+        Body: %s"""
+
+            self.LOG.debug(
+                log_fmt % (
+                    caller_name,
+                    resp['status'],
+                    method,
+                    req_url,
+                    secs,
+                    str(req_headers),
+                    str(req_body)[:2048],
+                    str(resp),
+                    str(resp_body)[:2048]),
+                extra=extra)
+
     def _parse_resp(self, body):
         if self._get_type() is "json":
             body = json.loads(body)
@@ -382,7 +408,10 @@
         resp, resp_body = self.http_obj.request(
             req_url, method, headers=req_headers, body=req_body)
         end = time.time()
-        self._log_request(method, req_url, resp, secs=(end - start))
+        self._log_request(method, req_url, resp, secs=(end - start),
+                          req_headers=req_headers, req_body=req_body,
+                          resp_body=resp_body)
+
         # Verify HTTP response codes
         self.response_checker(method, url, req_headers, req_body, resp,
                               resp_body)
diff --git a/tempest/config.py b/tempest/config.py
index af96132..0212d8a 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -794,6 +794,26 @@
     cfg.BoolOpt('enable',
                 default=True,
                 help="Enable diagnostic commands"),
+    cfg.StrOpt('trace_requests',
+               default='',
+               help="""A regex to determine which requests should be traced.
+
+This is a regex to match the caller for rest client requests to be able to
+selectively trace calls out of specific classes and methods. It largely
+exists for test development, and is not expected to be used in a real deploy
+of tempest. This will be matched against the discovered ClassName:method
+in the test environment.
+
+Expected values for this field are:
+
+ * ClassName:test_method_name - traces one test_method
+ * ClassName:setUp(Class) - traces specific setup functions
+ * ClassName:tearDown(Class) - traces specific teardown functions
+ * ClassName:_run_cleanups - traces the cleanup functions
+
+If nothing is specified, this feature is not enabled. To trace everything
+specify .* as the regex.
+""")
 ]
 
 input_scenario_group = cfg.OptGroup(name="input-scenario",