Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

US47068 fixed disconnect for socketio.Client. Fixes stuck taurus sess… #1718

Merged
merged 1 commit into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 11 additions & 6 deletions bzt/bza.py
Original file line number Diff line number Diff line change
Expand Up @@ -840,12 +840,17 @@ def connected(self):
return self._sio.connected

def disconnect(self):
if self._sio.connected:
self._sio.disconnect()
self._log.info("Disconnecting from happysocks server")
# socketio client may be stuck in _handle_reconnect thread
# read/write thread runs only while the client is connected
if self._sio._reconnect_abort:
self._sio._reconnect_abort.set()
self._sio.disconnect()

def send_engine_metrics(self, metrics_batch: List[dict]):
if not self.connected():
self.connect()
self._log.debug(f"Sending {len(metrics_batch)} metrics items to happysocks")
self._sio.emit(HappysocksEngineNamespace.METRICS_EVENT, metrics_batch, HappysocksEngineNamespace.NAMESPACE,
callback=self._engine_namespace.metrics_callback)
try:
self._sio.emit(HappysocksEngineNamespace.METRICS_EVENT, metrics_batch, HappysocksEngineNamespace.NAMESPACE,
callback=self._engine_namespace.metrics_callback)
except BaseException as e:
raise TaurusNetworkError(f"Failed to send {len(metrics_batch)} metrics items") from e
10 changes: 10 additions & 0 deletions bzt/modules/blazemeter/blazemeter_reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@
if self._user.token and self.public_report:
report_link = self._master.make_report_public()
self.log.info("Public report link: %s", report_link)
if self._engine_metrics_enabled():
try:
self.happysocks_client.connect()
except BaseException:
self.log.error("Failed to connect to happysocks", exc_info=True)

Check warning on line 195 in bzt/modules/blazemeter/blazemeter_reporter.py

View check run for this annotation

Codecov / codecov/patch

bzt/modules/blazemeter/blazemeter_reporter.py#L194-L195

Added lines #L194 - L195 were not covered by tests

def _start_online(self):
"""
Expand Down Expand Up @@ -446,6 +451,11 @@
"""
Sends engine metrics to happysocks API via WebSockets.
"""
if not self.happysocks_client.connected():
# This may happen when the client hasn't managed to connect - e.g error during initial connect,
# may reconnect later. Engine metrics are buffered for a short period.
self.log.warning("Unable to send engine health metrics to happysocks. No connection to server.")
return

Check warning on line 458 in bzt/modules/blazemeter/blazemeter_reporter.py

View check run for this annotation

Codecov / codecov/patch

bzt/modules/blazemeter/blazemeter_reporter.py#L457-L458

Added lines #L457 - L458 were not covered by tests
raw_data = self._engine_metrics_buffer.get_data()
metrics_batch = HappysocksMetricsConverter.to_metrics_batch(raw_data, self._sess_id,
self._master_id,
Expand Down
48 changes: 37 additions & 11 deletions tests/unit/test_bza.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,10 @@ def test_connect_error(self, mock_socketio_class):
def test_connect_success(self, mock_socketio_class):
# prepare mocks
sio = mock_socketio_class.return_value
sio.connected.return_value = True
# perform test
client = HappysocksClient("https://happysocks-5100-tester-dev.blazemeter.net", "r-v4-64102f1ab8795890049369",
"ci12NC02NDEwMmYxYWI", True, True)
client.connect()
self.assertTrue(sio.connected())
sio.connect.assert_called_once()
args = sio.connect.call_args
self.assertEqual(args[0][0], "https://happysocks-5100-tester-dev.blazemeter.net")
Expand All @@ -102,12 +100,10 @@ def test_connect_success(self, mock_socketio_class):
def test_connect_success_trailing_slash(self, mock_socketio_class):
# prepare mocks
sio = mock_socketio_class.return_value
sio.connected.return_value = True
# perform test
client = HappysocksClient("https://happysocks-5100-tester-dev.blazemeter.net/", "r-v4-64102f1ab8795890049369",
"ci12NC02NDEwMmYxYWI", True, True)
client.connect()
self.assertTrue(sio.connected())
sio.connect.assert_called_once()
args = sio.connect.call_args
self.assertEqual(args[0][0], "https://happysocks-5100-tester-dev.blazemeter.net")
Expand All @@ -121,12 +117,10 @@ def test_connect_success_trailing_slash(self, mock_socketio_class):
def test_connect_success_hs_path(self, mock_socketio_class):
# prepare mocks
sio = mock_socketio_class.return_value
sio.connected.return_value = True
# perform test
client = HappysocksClient("https://prod-rc.blazemeter.com/hs", "r-v4-64102f1ab8795890049369",
"ci12NC02NDEwMmYxYWI", True, True)
client.connect()
self.assertTrue(sio.connected())
sio.connect.assert_called_once()
args = sio.connect.call_args
self.assertEqual(args[0][0], "https://prod-rc.blazemeter.com")
Expand All @@ -140,18 +134,28 @@ def test_connect_success_hs_path(self, mock_socketio_class):
def test_disconnect_not_connected(self, mock_socketio_class):
# prepare mocks
sio = mock_socketio_class.return_value
sio.connected = False
sio._reconnect_abort = None
# perform test
client = HappysocksClient("https://happysocks-5100-tester-dev.blazemeter.net", "r-v4-64102f1ab8795890049369",
"ci12NC02NDEwMmYxYWI", True, True)
client.disconnect()
sio.disconnect.assert_not_called()
sio.disconnect.assert_called_once()

@patch('bzt.bza.socketio.Client')
def test_disconnect_while_reconnecting(self, mock_socketio_class):
# prepare mocks
sio = mock_socketio_class.return_value
# perform test
client = HappysocksClient("https://happysocks-5100-tester-dev.blazemeter.net", "r-v4-64102f1ab8795890049369",
"ci12NC02NDEwMmYxYWI", True, True)
client.disconnect()
sio._reconnect_abort.set.assert_called_once()
sio.disconnect.assert_called_once()

@patch('bzt.bza.socketio.Client')
def test_disconnect_connected(self, mock_socketio_class):
# prepare mocks
sio = mock_socketio_class.return_value
type(sio).connected = PropertyMock(side_effect=[True, False])
# perform test
client = HappysocksClient("https://happysocks-5100-tester-dev.blazemeter.net", "r-v4-64102f1ab8795890049369",
"ci12NC02NDEwMmYxYWI", True, True)
Expand All @@ -164,7 +168,6 @@ def test_disconnect_connected(self, mock_socketio_class):
def test_send_engine_metrics(self, mock_socketio_class):
# prepare mocks
sio = mock_socketio_class.return_value
sio.connected = False
# perform test
client = HappysocksClient("https://prod-rc.blazemeter.com/hs", "r-v4-64102f1ab8795890049369",
"ci12NC02NDEwMmYxYWI", True, True)
Expand All @@ -185,7 +188,6 @@ def test_send_engine_metrics(self, mock_socketio_class):
}
])
# verify
sio.connect.assert_called_once()
sio.emit.assert_called_once()
args = sio.emit.call_args
self.assertEqual(args[0][0], "metrics")
Expand Down Expand Up @@ -265,3 +267,27 @@ def test_send_metrics_error(self):
# error while processing metrics in happysocks is handled by HappysocksEngineNamespace callback and logged
# we have no reliable way of waiting for the callback before disconnect
time.sleep(0.1)

def test_send_metrics_not_connected(self):
self.server.engine_namespace.metrics_response = {}
metrics_to_send = [
{
'metadata': {
'source': 'local',
'entityId': 'r-v4-64102f1ab8795890049369',
'masterId': 100,
'calibrationId': 200,
'calibrationStepId': 300,
},
'timestamp': 1678892271398,
'values': {
'cpu': 9.4,
'mem': 5560.0,
}
}
]
try:
self.client.send_engine_metrics(metrics_to_send)
self.fail("Expected TaurusNetworkError")
except TaurusNetworkError:
pass