def send(self, data, headers, timeout=None): response = None # ensure headers are byte strings headers = { k.encode("ascii") if isinstance(k, compat.text_type) else k: v.encode("ascii") if isinstance(v, compat.text_type) else v for k, v in headers.items() } if compat.PY2 and isinstance(self._url, compat.text_type): url = self._url.encode("utf-8") else: url = self._url try: try: response = self.http.urlopen("POST", url, body=data, headers=headers, timeout=timeout, preload_content=False) logger.info("Sent request, url=%s size=%.2fkb status=%s", url, len(data) / 1024.0, response.status) except Exception as e: print_trace = True if isinstance(e, MaxRetryError) and isinstance( e.reason, TimeoutError): message = "Connection to APM Server timed out " "(url: %s, timeout: %s seconds)" % ( self._url, timeout, ) print_trace = False else: message = "Unable to reach APM Server: %s (url: %s)" % ( e, self._url) raise TransportException(message, data, print_trace=print_trace) body = response.read() if response.status >= 400: if response.status == 429: # rate-limited message = "Temporarily rate limited: " print_trace = False else: message = "HTTP %s: " % response.status print_trace = True message += body.decode("utf8") raise TransportException(message, data, print_trace=print_trace) return response.getheader("Location") finally: if response: response.close()
async def send(self, data, headers, timeout): from elasticapm.transport.base import TransportException self.data = data if self.url == urlparse("http://error"): raise TransportException("", data, False) await asyncio.sleep(0.0001)
def test_send_remote_failover_async(self, should_try, http_send): should_try.return_value = True client = Client( servers=['http://example.com'], app_name='app_name', secret_token='secret', async_mode=True, ) logger = mock.Mock() client.error_logger.error = logger # test error encoded_data = client.encode({'message': 'oh no'}) http_send.side_effect = TransportException('oopsie', encoded_data) client.send_remote('http://example.com/api/store', data=encoded_data) client.close() assert client.state.status == client.state.ERROR assert len(logger.call_args_list) == 2 assert 'oopsie' in logger.call_args_list[0][0][0] assert 'oh no' in logger.call_args_list[1][0][1] # test recovery http_send.side_effect = None client.send_remote('http://example.com/api/store', 'foo') client.close() assert client.state.status == client.state.ONLINE
def send(self, data, headers, timeout=None): if timeout is None: timeout = defaults.TIMEOUT response = None try: try: response = self.http.urlopen('POST', self._url, body=data, headers=headers, timeout=timeout) except Exception as e: print_trace = True if isinstance(e, MaxRetryError) and isinstance( e.reason, TimeoutError): message = ("Connection to APM Server timed out " "(url: %s, timeout: %d seconds)" % (self._url, timeout)) print_trace = False else: message = 'Unable to reach APM Server: %s (url: %s)' % ( e, self._url) raise TransportException(message, data, print_trace=print_trace) body = response.read() if response.status >= 400: if response.status == 429: # rate-limited message = 'Temporarily rate limited: ' print_trace = False else: message = 'HTTP %s: ' % response.status print_trace = True message += body.decode('utf8') raise TransportException(message, data, print_trace=print_trace) return response.getheader('Location') finally: if response: response.close()
def test_sync_transport_fail_and_recover(mock_send, caplog): mock_send.side_effect = TransportException("meh") transport = Transport() transport.queue("x", {}, flush=True) assert transport.state.did_fail() # first retry should be allowed immediately assert transport.state.should_try() # recover mock_send.side_effect = None transport.queue("x", {}, flush=True) assert not transport.state.did_fail()
def test_sync_transport_fail_and_recover(mock_send, caplog): transport = Transport(client=None) transport.start_thread() try: mock_send.side_effect = TransportException("meh") transport.queue("x", {}) transport.flush() assert transport.state.did_fail() # first retry should be allowed immediately assert transport.state.should_try() # recover mock_send.side_effect = None transport.queue("x", {}) transport.flush() assert not transport.state.did_fail() finally: transport.close()
def send(self, data, headers, timeout=None): """ Sends a request to a remote webserver using HTTP POST. Returns the shortcut URL of the recorded error on Elastic APM """ req = Request(self._url, headers=headers) if timeout is None: timeout = defaults.TIMEOUT response = None try: try: response = urlopen(req, data, timeout) except TypeError: response = urlopen(req, data) except Exception as e: print_trace = True if isinstance(e, socket.timeout): message = ("Connection to APM Server timed out " "(url: %s, timeout: %d seconds)" % (self._url, timeout)) elif isinstance(e, HTTPError): body = e.read() if e.code == 429: # rate-limited message = 'Temporarily rate limited: ' print_trace = False else: message = 'Unable to reach APM Server: ' message += '%s (url: %s, body: %s)' % (e, self._url, body) else: message = 'Unable to reach APM Server: %s (url: %s)' % ( e, self._url) raise TransportException(message, data, print_trace=print_trace) finally: if response: response.close() return response.info().get('Location')