feat: measure gateway latency (#10)

This commit is contained in:
Slipstream 2025-06-10 15:40:16 -06:00 committed by GitHub
parent 84b4e49c6a
commit c6fb120449
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 30 additions and 3 deletions

View File

@ -365,6 +365,13 @@ class Client:
"""Indicates if the client has successfully connected to the Gateway and is ready."""
return self._ready_event.is_set()
@property
def latency(self) -> Optional[float]:
"""Returns the gateway latency in seconds, or ``None`` if unavailable."""
if self._gateway:
return self._gateway.latency
return None
async def wait_until_ready(self) -> None:
"""|coro|
Waits until the client is fully connected to Discord and the initial state is processed.

View File

@ -63,6 +63,9 @@ class GatewayClient:
self._keep_alive_task: Optional[asyncio.Task] = None
self._receive_task: Optional[asyncio.Task] = None
self._last_heartbeat_sent: Optional[float] = None
self._last_heartbeat_ack: Optional[float] = None
# For zlib decompression
self._buffer = bytearray()
self._inflator = zlib.decompressobj()
@ -103,6 +106,7 @@ class GatewayClient:
async def _heartbeat(self):
"""Sends a heartbeat to the Gateway."""
self._last_heartbeat_sent = time.monotonic()
payload = {"op": GatewayOpcode.HEARTBEAT, "d": self._last_sequence}
await self._send_json(payload)
# print("Sent heartbeat.")
@ -388,6 +392,7 @@ class GatewayClient:
print("Performing initial IDENTIFY.")
await self._identify()
elif op == GatewayOpcode.HEARTBEAT_ACK:
self._last_heartbeat_ack = time.monotonic()
# print("Received heartbeat ACK.")
pass # Good, connection is alive
else:
@ -491,3 +496,18 @@ class GatewayClient:
self._session_id = None
self._last_sequence = None
self._resume_gateway_url = None # This might be re-fetched anyway
@property
def latency(self) -> Optional[float]:
"""Returns the latency between heartbeat and ACK in seconds."""
if self._last_heartbeat_sent is None or self._last_heartbeat_ack is None:
return None
return self._last_heartbeat_ack - self._last_heartbeat_sent
@property
def last_heartbeat_sent(self) -> Optional[float]:
return self._last_heartbeat_sent
@property
def last_heartbeat_ack(self) -> Optional[float]:
return self._last_heartbeat_ack

View File

@ -92,10 +92,10 @@ class TestCog(Cog):
async def ping_hybrid(
self, ctx: Union[CommandContext, AppCommandContext], arg: Optional[str] = None
):
# latency = self.client.latency # Assuming client has latency attribute from gateway - Commented out for now
latency_ms = "N/A" # Placeholder
latency = self.client.latency
latency_ms = f"{latency * 1000:.0f}" if latency is not None else "N/A"
hybrid = HybridContext(ctx)
await hybrid.send(f"Pong! Arg: {arg} (Hybrid)")
await hybrid.send(f"Pong! {latency_ms}ms. Arg: {arg} (Hybrid)")
@slash_command(name="options_test", description="Tests various option types.")
async def options_test_slash(