From 2db65773b0316ec3e25ca0cd1a57b06b7d5c8a97 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Mon, 23 Aug 2021 10:37:37 +0200 Subject: [PATCH] Fix: track better why a connection (method) failed (#47) Also make it more obvious what is a final call, and what is a "this method failed". --- .../application/helpers/token_connect.py | 16 ++++++++-------- game_coordinator/database/redis.py | 10 ++++++++-- game_coordinator/web.py | 1 + 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/game_coordinator/application/helpers/token_connect.py b/game_coordinator/application/helpers/token_connect.py index c19fdf0..ec7af15 100644 --- a/game_coordinator/application/helpers/token_connect.py +++ b/game_coordinator/application/helpers/token_connect.py @@ -80,9 +80,9 @@ async def _timeout(self): try: await asyncio.sleep(TIMEOUT) - # If we reach here, we haven't managed to get a connection within 10 seconds. Time to call it a day. + # If we reach here, we haven't managed to get a connection within TIMEOUT seconds. Time to call it a day. self._timeout_task = None - await self._connect_failed() + await self._connect_failed("timeout") except Exception: log.exception("Exception during _timeout()") @@ -111,13 +111,13 @@ async def _connect(self): # If TURN failed, we have no other method left, so fail the attempt. self._connect_task = None - asyncio.create_task(self._connect_failed()) + asyncio.create_task(self._connect_failed("out-of-methods")) break except SocketClosed: # Either of the two sides closed the Game Coordinator # connection. So cancel the connection attempt. self._connect_task = None - asyncio.create_task(self._connect_failed(True)) + asyncio.create_task(self._connect_failed("closed")) break except Exception: log.exception("Exception during _connect_next_wait()") @@ -132,7 +132,7 @@ async def _connect_next_wait(self): async def connect_failed(self, tracking_number): if tracking_number == 0: # Client requested we stop with this connection attempt. So clean it up! - asyncio.create_task(self._connect_failed(True)) + asyncio.create_task(self._connect_failed("stop")) return # Check if this is our current attempt. Server and client send @@ -141,7 +141,7 @@ async def connect_failed(self, tracking_number): if tracking_number != self._tracking_number: return - await self._application.database.stats_connect(self._connect_method, False) + await self._application.database.stats_connect(self._connect_method, False, False) # Try the next attempt now. self._tracking_number += 1 @@ -197,7 +197,7 @@ async def _connect_turn_connect(self, connection_string): connection_string, ) - async def _connect_failed(self, on_request=False): + async def _connect_failed(self, stats_type): if self._connect_task: self._connect_task.cancel() self._connect_task = None @@ -219,6 +219,6 @@ async def _connect_failed(self, on_request=False): # If the server already left, that is fine. pass - await self._application.database.stats_connect("closed" if on_request else "failed", False) + await self._application.database.stats_connect(stats_type, False) self._application.delete_token(self.token) diff --git a/game_coordinator/database/redis.py b/game_coordinator/database/redis.py index 750ab32..3072f91 100644 --- a/game_coordinator/database/redis.py +++ b/game_coordinator/database/redis.py @@ -327,8 +327,14 @@ async def server_offline(self, server_id): async def stats_verify(self, connection_type_name): await self._stats("verify", connection_type_name) - async def stats_connect(self, method_name, result): - key = "connect" if result else "connect-failed" + async def stats_connect(self, method_name, result, final=True): + if result: + # Successful connections are always final. + key = "connect" + elif final: + key = "connect-failed" + else: + key = "connect-method-failed" await self._stats(key, method_name) diff --git a/game_coordinator/web.py b/game_coordinator/web.py index 18ba318..96b0229 100644 --- a/game_coordinator/web.py +++ b/game_coordinator/web.py @@ -22,6 +22,7 @@ async def stats_handler(request): "listing": await DB_INSTANCE.get_stats("listing"), "connect": await DB_INSTANCE.get_stats("connect"), "connect-failed": await DB_INSTANCE.get_stats("connect-failed"), + "connect-method-failed": await DB_INSTANCE.get_stats("connect-method-failed"), "turn": await DB_INSTANCE.get_stats("turn"), } )