def test_url_property(get_http_host): http_host = get_http_host() http_host.port = None security = http_logging.HttpSecurity(ssl_enable=False) config = http_logging.ConfigLog(security=security) transport = AsyncHttpTransport( http_host=http_host, config=config, ) assert transport.url == \ f'http://{http_host.name}/{http_host.path}' security.ssl_enable = True transport = AsyncHttpTransport( http_host=http_host, config=config, ) assert transport.url == \ f'https://{http_host.name}/{http_host.path}' http_host.port = 1234 transport = AsyncHttpTransport( http_host=http_host, config=config, ) assert transport.url == \ f'https://{http_host.name}:{http_host.port}/{http_host.path}'
def test_send_success_request( mock_requests, mock_logger, mock_json, get_http_host, ): http_host = get_http_host() security = http_logging.HttpSecurity(ssl_enable=True) config = http_logging.ConfigLog( use_logging=True, security=security, ) mock_response = mock.Mock() mock_response.ok = False mock_post = mock.Mock(return_value=mock_response) mock_requests.Session().post = mock_post mock_json.dumps().encoding.return_value = '{"foo": "bar"}' transport = AsyncHttpTransport( http_host=http_host, config=config, ) events = mock.Mock() batches = [mock.MagicMock(), mock.MagicMock(), mock.MagicMock()] for batch in batches: batch.__len__.return_value = 10 transport._AsyncHttpTransport__batches = mock.Mock(return_value=batches) transport.send(events=events) transport._AsyncHttpTransport__batches.assert_called_with(events) mock_logger.debug.assert_called() mock_logger.exception.assert_not_called() mock_requests.Session.assert_called() post_requests = mock_post.mock_calls assert len(post_requests) == 3 for batch in batches: expected_request = mock.call( transport.url, headers=transport.headers, json=batch, verify=transport._ssl_verify, timeout=transport._timeout, ) assert expected_request in post_requests
def test_headers_property(get_http_host): http_host = get_http_host() transport = AsyncHttpTransport( http_host=http_host, ) transport.get_custom_headers = mock.Mock(return_value={}) assert transport.headers == {'Content-Type': 'application/json'} transport.get_custom_headers = mock.Mock(return_value={'foo': 'bar'}) assert transport.headers == { 'Content-Type': 'application/json', 'foo': 'bar', }
def test_send_failed_request( mock_requests, mock_logger, mock_json, get_http_host, ): http_host = get_http_host() security = http_logging.HttpSecurity(ssl_enable=True) config = http_logging.ConfigLog( use_logging=True, security=security, ) req_exception = requests.exceptions.RequestException('HTTP Error') mock_response = mock.Mock() mock_response.ok = False # Simulate failed request mock_response.raise_for_status.side_effect = req_exception mock_post = mock.Mock(return_value=mock_response) mock_requests.Session().post = mock_post mock_json.dumps().encoding.return_value = '{"foo": "bar"}' transport = AsyncHttpTransport( http_host=http_host, config=config, ) events = mock.Mock() batches = [mock.MagicMock()] batches[0].__len__.return_value = 10 transport._AsyncHttpTransport__batches = mock.Mock(return_value=batches) transport.send(events=events) assert len(mock_post.mock_calls) == 1 mock_requests.Session().close.assert_called() mock_response.raise_for_status.assert_called() mock_logger.debug.assert_called() mock_logger.exception.assert_called_with(req_exception)
def test_custom_formatter_and_transport(http_host): config = http_logging.ConfigLog() transport = AsyncHttpTransport(http_host=http_host, config=config) formatter = HttpLogFormatter() handler = AsyncHttpHandler( http_host=http_host, support_class=http_logging.SupportClass( http_host=http_host, config=config, _transport=transport, _formatter=formatter, ), ) handler._setup_transport() assert handler._transport == transport assert handler.formatter == formatter
def test_get_custom_headers(get_http_host): http_host = get_http_host() transport = AsyncHttpTransport( http_host=http_host, ) assert transport.get_custom_headers() == {} dummy_headers = {'foo': 'bar'} mock_custom_headers = mock.Mock(return_value=dummy_headers) config = http_logging.ConfigLog(custom_headers=mock_custom_headers) transport = AsyncHttpTransport( http_host=http_host, config=config, ) assert transport.get_custom_headers() == dummy_headers
def test_custom_path(get_http_host): http_host = get_http_host() transport = AsyncHttpTransport(http_host=http_host) assert transport._path == http_host.path
def test_handler(run_localserver, localhost): custom_path = 'foo-bar-path' custom_header_dict = {'Foo': 'Bar'} http_host = HttpHost( name=localhost.host, port=localhost.port, path=custom_path, timeout=localhost.timeout ) security = HttpSecurity( ssl_enable=False, ssl_verify=False, ) config = ConfigLog( database_path=localhost.database_path, use_logging=True, custom_headers=lambda: custom_header_dict, security=security, ) support_class = SupportClass( http_host=http_host, config=config, _transport=AsyncHttpTransport( http_host=http_host, config=config, ), ) log_handler = AsyncHttpHandler( http_host=http_host, config=config, support_class=support_class, ) logger = logging.getLogger('test_handler') logger.setLevel(logging.DEBUG) logger.addHandler(log_handler) logged_messages = { 'debug': 'Does this help debugging?', 'info': 'Some information...', 'warning': 'You\'ve been warned!', } try: x = 1/0 # NOQA except Exception: logged_messages['error'] = traceback.format_exc() info_extra = {'foo': 'bar'} for level, message in logged_messages.items(): if level == 'info': getattr(logger, level)(message, extra=info_extra) else: getattr(logger, level)(message) # Trigger event flushing to make sure logs are sent to localserver # See: https://archive.vn/B6yFt#selection-3749.0-3795.34 print('Flushing log events...') log_handler.flush() count = 0 while True and count <= 10: response = requests.post(url=localhost.last_response_url) data = response.json()['last_response'] if data is None: time.sleep(0.5) count += 1 continue break assert response.ok is True assert data['request']['http']['method'] == 'POST' assert data['request']['url']['path'] == f'/{custom_path}' # Verify headers for key, val in custom_header_dict.items(): assert data['request']['headers'].get(key) == val recorded_logs = data['request']['body'] recorded_logs_by_level = { log['level']['name']: log for log in recorded_logs } assert len(recorded_logs) == len(logged_messages) for level, message in logged_messages.items(): recorded_log = recorded_logs_by_level[level.upper()] assert recorded_log['message'] == str(message) if level == 'info': assert 'extra' in recorded_log.keys() assert recorded_log['extra'] == info_extra else: assert 'extra' not in recorded_log.keys()