Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions sdk/core/azure-core/azure/core/pipeline/policies/_universal.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,20 @@ def on_request(self, request):
for header, value in http_request.headers.items():
value = self._redact_header(header, value)
logger.info(" %r: %r", header, value)
if isinstance(http_request.body, types.GeneratorType):
logger.info("File upload")
return
try:
if isinstance(http_request.body, types.AsyncGeneratorType):
logger.info("File upload")
return
except AttributeError:
pass
if http_request.body:
logger.info("A body is sent with the request")
return
logger.info("No body was attached to the request")
return
except Exception as err: # pylint: disable=broad-except
logger.warning("Failed to log request: %s", repr(err))

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
# ------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------
"""Tests for the HttpLoggingPolicy."""

import logging
import pytest
import sys
try:
from unittest import mock
except ImportError:
import mock
from azure.core.pipeline import (
PipelineResponse,
PipelineRequest,
PipelineContext
)
from azure.core.pipeline.transport import (
HttpRequest,
HttpResponse,
)
from azure.core.pipeline.policies import (
HttpLoggingPolicy,
)


def test_http_logger():

class MockHandler(logging.Handler):
def __init__(self):
super(MockHandler, self).__init__()
self.messages = []
def reset(self):
self.messages = []
def emit(self, record):
self.messages.append(record)
mock_handler = MockHandler()

logger = logging.getLogger("testlogger")
logger.addHandler(mock_handler)
logger.setLevel(logging.DEBUG)

policy = HttpLoggingPolicy(logger=logger)

universal_request = HttpRequest('GET', 'http://127.0.0.1/')
http_response = HttpResponse(universal_request, None)
http_response.status_code = 202
request = PipelineRequest(universal_request, PipelineContext(None))

# Basics

policy.on_request(request)
response = PipelineResponse(request, http_response, request.context)
policy.on_response(request, response)

assert all(m.levelname == 'INFO' for m in mock_handler.messages)
assert len(mock_handler.messages) == 6
assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'"
assert mock_handler.messages[1].message == "Request method: 'GET'"
assert mock_handler.messages[2].message == 'Request headers:'
assert mock_handler.messages[3].message == 'No body was attached to the request'
assert mock_handler.messages[4].message == 'Response status: 202'
assert mock_handler.messages[5].message == 'Response headers:'

mock_handler.reset()

# Let's make this request a failure, retried twice

policy.on_request(request)
response = PipelineResponse(request, http_response, request.context)
policy.on_response(request, response)

policy.on_request(request)
response = PipelineResponse(request, http_response, request.context)
policy.on_response(request, response)

assert all(m.levelname == 'INFO' for m in mock_handler.messages)
assert len(mock_handler.messages) == 12
assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'"
assert mock_handler.messages[1].message == "Request method: 'GET'"
assert mock_handler.messages[2].message == 'Request headers:'
assert mock_handler.messages[3].message == 'No body was attached to the request'
assert mock_handler.messages[4].message == 'Response status: 202'
assert mock_handler.messages[5].message == 'Response headers:'
assert mock_handler.messages[6].message == "Request URL: 'http://127.0.0.1/'"
assert mock_handler.messages[7].message == "Request method: 'GET'"
assert mock_handler.messages[8].message == 'Request headers:'
assert mock_handler.messages[9].message == 'No body was attached to the request'
assert mock_handler.messages[10].message == 'Response status: 202'
assert mock_handler.messages[11].message == 'Response headers:'

mock_handler.reset()

# Headers and query parameters

policy.allowed_query_params = ['country']

universal_request.headers = {
"Accept": "Caramel",
"Hate": "Chocolat",
}
http_response.headers = {
"Content-Type": "Caramel",
"HateToo": "Chocolat",
}
universal_request.url = "http://127.0.0.1/?country=france&city=aix"

policy.on_request(request)
response = PipelineResponse(request, http_response, request.context)
policy.on_response(request, response)

assert all(m.levelname == 'INFO' for m in mock_handler.messages)
assert len(mock_handler.messages) == 10
assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/?country=france&city=REDACTED'"
assert mock_handler.messages[1].message == "Request method: 'GET'"
assert mock_handler.messages[2].message == "Request headers:"
# Dict not ordered in Python, exact logging order doesn't matter
assert set([
mock_handler.messages[3].message,
mock_handler.messages[4].message
]) == set([
" 'Accept': 'Caramel'",
" 'Hate': 'REDACTED'"
])
assert mock_handler.messages[5].message == 'No body was attached to the request'
assert mock_handler.messages[6].message == "Response status: 202"
assert mock_handler.messages[7].message == "Response headers:"
# Dict not ordered in Python, exact logging order doesn't matter
assert set([
mock_handler.messages[8].message,
mock_handler.messages[9].message
]) == set([
" 'Content-Type': 'Caramel'",
" 'HateToo': 'REDACTED'"
])

mock_handler.reset()



def test_http_logger_operation_level():

class MockHandler(logging.Handler):
def __init__(self):
super(MockHandler, self).__init__()
self.messages = []
def reset(self):
self.messages = []
def emit(self, record):
self.messages.append(record)
mock_handler = MockHandler()

logger = logging.getLogger("testlogger")
logger.addHandler(mock_handler)
logger.setLevel(logging.DEBUG)

policy = HttpLoggingPolicy()
kwargs={'logger': logger}

universal_request = HttpRequest('GET', 'http://127.0.0.1/')
http_response = HttpResponse(universal_request, None)
http_response.status_code = 202
request = PipelineRequest(universal_request, PipelineContext(None, **kwargs))

# Basics

policy.on_request(request)
response = PipelineResponse(request, http_response, request.context)
policy.on_response(request, response)

assert all(m.levelname == 'INFO' for m in mock_handler.messages)
assert len(mock_handler.messages) == 6
assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'"
assert mock_handler.messages[1].message == "Request method: 'GET'"
assert mock_handler.messages[2].message == 'Request headers:'
assert mock_handler.messages[3].message == 'No body was attached to the request'
assert mock_handler.messages[4].message == 'Response status: 202'
assert mock_handler.messages[5].message == 'Response headers:'

mock_handler.reset()

# Let's make this request a failure, retried twice

request = PipelineRequest(universal_request, PipelineContext(None, **kwargs))

policy.on_request(request)
response = PipelineResponse(request, http_response, request.context)
policy.on_response(request, response)

policy.on_request(request)
response = PipelineResponse(request, http_response, request.context)
policy.on_response(request, response)

assert all(m.levelname == 'INFO' for m in mock_handler.messages)
assert len(mock_handler.messages) == 12
assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'"
assert mock_handler.messages[1].message == "Request method: 'GET'"
assert mock_handler.messages[2].message == 'Request headers:'
assert mock_handler.messages[3].message == 'No body was attached to the request'
assert mock_handler.messages[4].message == 'Response status: 202'
assert mock_handler.messages[5].message == 'Response headers:'
assert mock_handler.messages[6].message == "Request URL: 'http://127.0.0.1/'"
assert mock_handler.messages[7].message == "Request method: 'GET'"
assert mock_handler.messages[8].message == 'Request headers:'
assert mock_handler.messages[9].message == 'No body was attached to the request'
assert mock_handler.messages[10].message == 'Response status: 202'
assert mock_handler.messages[11].message == 'Response headers:'

mock_handler.reset()


def test_http_logger_with_body():

class MockHandler(logging.Handler):
def __init__(self):
super(MockHandler, self).__init__()
self.messages = []
def reset(self):
self.messages = []
def emit(self, record):
self.messages.append(record)
mock_handler = MockHandler()

logger = logging.getLogger("testlogger")
logger.addHandler(mock_handler)
logger.setLevel(logging.DEBUG)

policy = HttpLoggingPolicy(logger=logger)

universal_request = HttpRequest('GET', 'http://127.0.0.1/')
universal_request.body = "testbody"
http_response = HttpResponse(universal_request, None)
http_response.status_code = 202
request = PipelineRequest(universal_request, PipelineContext(None))

policy.on_request(request)
response = PipelineResponse(request, http_response, request.context)
policy.on_response(request, response)

assert all(m.levelname == 'INFO' for m in mock_handler.messages)
assert len(mock_handler.messages) == 6
assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'"
assert mock_handler.messages[1].message == "Request method: 'GET'"
assert mock_handler.messages[2].message == 'Request headers:'
assert mock_handler.messages[3].message == 'A body is sent with the request'
assert mock_handler.messages[4].message == 'Response status: 202'
assert mock_handler.messages[5].message == 'Response headers:'

mock_handler.reset()


@pytest.mark.skipif(sys.version_info < (3, 6), reason="yield in async function is not supported in 3.5")
def test_http_logger_with_generator_body():

async def _g():
yield 1

class MockHandler(logging.Handler):
def __init__(self):
super(MockHandler, self).__init__()
self.messages = []
def reset(self):
self.messages = []
def emit(self, record):
self.messages.append(record)
mock_handler = MockHandler()

logger = logging.getLogger("testlogger")
logger.addHandler(mock_handler)
logger.setLevel(logging.DEBUG)

policy = HttpLoggingPolicy(logger=logger)

universal_request = HttpRequest('GET', 'http://127.0.0.1/')
universal_request.body = _g()
http_response = HttpResponse(universal_request, None)
http_response.status_code = 202
request = PipelineRequest(universal_request, PipelineContext(None))

policy.on_request(request)
response = PipelineResponse(request, http_response, request.context)
policy.on_response(request, response)

assert all(m.levelname == 'INFO' for m in mock_handler.messages)
assert len(mock_handler.messages) == 6
assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'"
assert mock_handler.messages[1].message == "Request method: 'GET'"
assert mock_handler.messages[2].message == 'Request headers:'
assert mock_handler.messages[3].message == 'File upload'
assert mock_handler.messages[4].message == 'Response status: 202'
assert mock_handler.messages[5].message == 'Response headers:'

mock_handler.reset()
Loading