summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-03-18 21:35:11 +0000
committerGerrit Code Review <review@openstack.org>2015-03-18 21:35:11 +0000
commitbde71a25f11a0ad067df6c648c3b550254c825d5 (patch)
treea8afa312df6884f850a9b0541439ed046dbbb9ec
parent7e63af0c4e10687513bd0cf527e6151dd94e5589 (diff)
parentc0a731204e3326d0446437f6c2849af9ad9c714b (diff)
downloadpython-keystoneclient-bde71a25f11a0ad067df6c648c3b550254c825d5.tar.gz
Merge "Allow passing logger object to request"
-rw-r--r--keystoneclient/adapter.py8
-rw-r--r--keystoneclient/session.py48
-rw-r--r--keystoneclient/tests/unit/test_session.py58
3 files changed, 93 insertions, 21 deletions
diff --git a/keystoneclient/adapter.py b/keystoneclient/adapter.py
index e8e0a29..74399da 100644
--- a/keystoneclient/adapter.py
+++ b/keystoneclient/adapter.py
@@ -40,13 +40,16 @@ class Adapter(object):
be attempted for connection errors.
Default None - use session default which
is don't retry.
+ :param logger: A logging object to use for requests that pass through this
+ adapter.
+ :type logger: logging.Logger
"""
@utils.positional()
def __init__(self, session, service_type=None, service_name=None,
interface=None, region_name=None, endpoint_override=None,
version=None, auth=None, user_agent=None,
- connect_retries=None):
+ connect_retries=None, logger=None):
# NOTE(jamielennox): when adding new parameters to adapter please also
# add them to the adapter call in httpclient.HTTPClient.__init__
self.session = session
@@ -59,6 +62,7 @@ class Adapter(object):
self.user_agent = user_agent
self.auth = auth
self.connect_retries = connect_retries
+ self.logger = logger
def _set_endpoint_filter_kwargs(self, kwargs):
if self.service_type:
@@ -85,6 +89,8 @@ class Adapter(object):
kwargs.setdefault('user_agent', self.user_agent)
if self.connect_retries is not None:
kwargs.setdefault('connect_retries', self.connect_retries)
+ if self.logger:
+ kwargs.setdefault('logger', self.logger)
return self.session.request(url, method, **kwargs)
diff --git a/keystoneclient/session.py b/keystoneclient/session.py
index 0bb0de2..4492ede 100644
--- a/keystoneclient/session.py
+++ b/keystoneclient/session.py
@@ -162,8 +162,8 @@ class Session(object):
@utils.positional()
def _http_log_request(self, url, method=None, data=None,
- json=None, headers=None):
- if not _logger.isEnabledFor(logging.DEBUG):
+ json=None, headers=None, logger=_logger):
+ if not logger.isEnabledFor(logging.DEBUG):
# NOTE(morganfainberg): This whole debug section is expensive,
# there is no need to do the work if we're not going to emit a
# debug log.
@@ -192,12 +192,13 @@ class Session(object):
if data:
string_parts.append("-d '%s'" % data)
- _logger.debug(' '.join(string_parts))
+ logger.debug(' '.join(string_parts))
@utils.positional()
def _http_log_response(self, response=None, json=None,
- status_code=None, headers=None, text=None):
- if not _logger.isEnabledFor(logging.DEBUG):
+ status_code=None, headers=None, text=None,
+ logger=_logger):
+ if not logger.isEnabledFor(logging.DEBUG):
return
if response:
@@ -220,14 +221,15 @@ class Session(object):
if text:
string_parts.append('\nRESP BODY: %s\n' % text)
- _logger.debug(' '.join(string_parts))
+ logger.debug(' '.join(string_parts))
@utils.positional(enforcement=utils.positional.WARN)
def request(self, url, method, json=None, original_ip=None,
user_agent=None, redirect=None, authenticated=None,
endpoint_filter=None, auth=None, requests_auth=None,
raise_exc=True, allow_reauth=True, log=True,
- endpoint_override=None, connect_retries=0, **kwargs):
+ endpoint_override=None, connect_retries=0, logger=_logger,
+ **kwargs):
"""Send an HTTP request with the specified characteristics.
Wrapper around `requests.Session.request` to handle tasks such as
@@ -286,6 +288,10 @@ class Session(object):
response. (optional, default True)
:param bool log: If True then log the request and response data to the
debug log. (optional, default True)
+ :param logger: The logger object to use to log request and responses.
+ If not provided the keystoneclient.session default
+ logger will be used.
+ :type logger: logging.Logger
:param kwargs: any other parameter that can be passed to
requests.Session.request (such as `headers`). Except:
'data' will be overwritten by the data in 'json' param.
@@ -361,7 +367,8 @@ class Session(object):
if log:
self._http_log_request(url, method=method,
data=kwargs.get('data'),
- headers=headers)
+ headers=headers,
+ logger=logger)
# Force disable requests redirect handling. We will manage this below.
kwargs['allow_redirects'] = False
@@ -370,7 +377,8 @@ class Session(object):
redirect = self.redirect
send = functools.partial(self._send_request,
- url, method, redirect, log, connect_retries)
+ url, method, redirect, log, logger,
+ connect_retries)
resp = send(**kwargs)
# handle getting a 401 Unauthorized response by invalidating the plugin
@@ -384,14 +392,14 @@ class Session(object):
resp = send(**kwargs)
if raise_exc and resp.status_code >= 400:
- _logger.debug('Request returned failure status: %s',
- resp.status_code)
+ logger.debug('Request returned failure status: %s',
+ resp.status_code)
raise exceptions.from_response(resp, method, url)
return resp
- def _send_request(self, url, method, redirect, log, connect_retries,
- connect_retry_delay=0.5, **kwargs):
+ def _send_request(self, url, method, redirect, log, logger,
+ connect_retries, connect_retry_delay=0.5, **kwargs):
# NOTE(jamielennox): We handle redirection manually because the
# requests lib follows some browser patterns where it will redirect
# POSTs as GETs for certain statuses which is not want we want for an
@@ -419,18 +427,18 @@ class Session(object):
if connect_retries <= 0:
raise
- _logger.info(_LI('Failure: %(e)s. Retrying in %(delay).1fs.'),
- {'e': e, 'delay': connect_retry_delay})
+ logger.info(_LI('Failure: %(e)s. Retrying in %(delay).1fs.'),
+ {'e': e, 'delay': connect_retry_delay})
time.sleep(connect_retry_delay)
return self._send_request(
- url, method, redirect, log,
+ url, method, redirect, log, logger,
connect_retries=connect_retries - 1,
connect_retry_delay=connect_retry_delay * 2,
**kwargs)
if log:
- self._http_log_response(response=resp)
+ self._http_log_response(response=resp, logger=logger)
if resp.status_code in self._REDIRECT_STATUSES:
# be careful here in python True == 1 and False == 0
@@ -446,13 +454,13 @@ class Session(object):
try:
location = resp.headers['location']
except KeyError:
- _logger.warn(_LW("Failed to redirect request to %s as new "
- "location was not provided."), resp.url)
+ logger.warn(_LW("Failed to redirect request to %s as new "
+ "location was not provided."), resp.url)
else:
# NOTE(jamielennox): We don't pass through connect_retry_delay.
# This request actually worked so we can reset the delay count.
new_resp = self._send_request(
- location, method, redirect, log,
+ location, method, redirect, log, logger,
connect_retries=connect_retries,
**kwargs)
diff --git a/keystoneclient/tests/unit/test_session.py b/keystoneclient/tests/unit/test_session.py
index 1d01c3a..e76ff42 100644
--- a/keystoneclient/tests/unit/test_session.py
+++ b/keystoneclient/tests/unit/test_session.py
@@ -12,6 +12,7 @@
import argparse
import itertools
+import logging
import uuid
import mock
@@ -608,6 +609,34 @@ class SessionAuthTests(utils.TestCase):
self.assertEqual(auth.TEST_USER_ID, sess.get_user_id())
self.assertEqual(auth.TEST_PROJECT_ID, sess.get_project_id())
+ def test_logger_object_passed(self):
+ logger = logging.getLogger(uuid.uuid4().hex)
+ logger.setLevel(logging.DEBUG)
+ logger.propagate = False
+
+ io = six.StringIO()
+ handler = logging.StreamHandler(io)
+ logger.addHandler(handler)
+
+ auth = AuthPlugin()
+ sess = client_session.Session(auth=auth)
+ response = uuid.uuid4().hex
+
+ self.stub_url('GET',
+ text=response,
+ headers={'Content-Type': 'text/html'})
+
+ resp = sess.get(self.TEST_URL, logger=logger)
+
+ self.assertEqual(response, resp.text)
+ output = io.getvalue()
+
+ self.assertIn(self.TEST_URL, output)
+ self.assertIn(response, output)
+
+ self.assertNotIn(self.TEST_URL, self.logger.output)
+ self.assertNotIn(response, self.logger.output)
+
class AdapterTest(utils.TestCase):
@@ -771,6 +800,35 @@ class AdapterTest(utils.TestCase):
self.assertEqual(auth.TEST_USER_ID, adpt.get_user_id())
self.assertEqual(auth.TEST_PROJECT_ID, adpt.get_project_id())
+ def test_logger_object_passed(self):
+ logger = logging.getLogger(uuid.uuid4().hex)
+ logger.setLevel(logging.DEBUG)
+ logger.propagate = False
+
+ io = six.StringIO()
+ handler = logging.StreamHandler(io)
+ logger.addHandler(handler)
+
+ auth = AuthPlugin()
+ sess = client_session.Session(auth=auth)
+ adpt = adapter.Adapter(sess, auth=auth, logger=logger)
+
+ response = uuid.uuid4().hex
+
+ self.stub_url('GET', text=response,
+ headers={'Content-Type': 'text/html'})
+
+ resp = adpt.get(self.TEST_URL, logger=logger)
+
+ self.assertEqual(response, resp.text)
+ output = io.getvalue()
+
+ self.assertIn(self.TEST_URL, output)
+ self.assertIn(response, output)
+
+ self.assertNotIn(self.TEST_URL, self.logger.output)
+ self.assertNotIn(response, self.logger.output)
+
class ConfLoadingTests(utils.TestCase):