Add rate limit logging and enhance Discord bot initialization

- Introduced a new module `rate_limit_logging.py` to log HTTP headers for Discord API rate limits (HTTP 429).
- Updated the Discord bot initialization in `__init__.py` to include a custom HTTP trace configuration for better rate limit handling.
- Adjusted logging levels in `run-web.py` to reduce verbosity for rate limit headers.
This commit is contained in:
2026-03-25 23:10:02 +01:00
parent 3c7d7f4e80
commit b51430e2b2
3 changed files with 71 additions and 1 deletions
+2 -1
View File
@@ -30,11 +30,12 @@ from discordbot.patreon import checkPatreonPosts
from discordbot.youtube import checkYouTubeVideos
from discordbot.auto_rooms import on_voice_state_update_auto_rooms, on_raw_reaction_add_auto_rooms, on_message_auto_rooms, cleanup_orphaned_auto_rooms
from discordbot.member_stats import record_message, on_voice_state_update_track_voice
from discordbot.rate_limit_logging import build_discord_http_trace_config
from protondb import searhProtonDb
class DiscordBot(discord.Client):
def __init__(self, *, intents: discord.Intents):
super().__init__(intents=intents)
super().__init__(intents=intents, http_trace=build_discord_http_trace_config())
self.tree = app_commands.CommandTree(self)
self.synced = False
+67
View File
@@ -0,0 +1,67 @@
"""
Journalisation des en-têtes HTTP sur les réponses 429 (rate limit Discord).
Réf. Discord : https://support-dev.discord.com/hc/en-us/articles/6223003921559-My-Bot-is-Being-Rate-Limited
discord.py transmet ce TraceConfig aiohttp via loption Client(http_trace=...).
Le corps JSON (retry_after, global) est toujours loggé par le logger discord.http.
"""
import logging
from typing import Any
import aiohttp
logger = logging.getLogger('discord.ratelimit_headers')
# En-têtes utiles pour identifier le type de limite (global / user / shared, etc.)
_HEADER_KEYS = (
'X-RateLimit-Limit',
'X-RateLimit-Remaining',
'X-RateLimit-Reset',
'X-RateLimit-Reset-After',
'X-RateLimit-Scope',
'X-Ratelimit-Bucket',
'X-Ratelimit-Limit',
'X-Ratelimit-Remaining',
'X-Ratelimit-Reset',
'Retry-After',
'Via',
)
def _collect_headers(resp: aiohttp.ClientResponse) -> dict[str, str]:
h = resp.headers
out: dict[str, str] = {}
for key in _HEADER_KEYS:
val = h.get(key)
if val is not None:
out[key] = val
return out
def build_discord_http_trace_config() -> aiohttp.TraceConfig:
trace = aiohttp.TraceConfig()
async def on_request_end(
session: aiohttp.ClientSession,
trace_config_ctx: Any,
params: Any,
) -> None:
try:
resp = getattr(params, 'response', None)
if resp is None or getattr(resp, 'status', None) != 429:
return
method = getattr(params, 'method', '?')
url = getattr(params, 'url', '?')
hdr = _collect_headers(resp)
logger.warning(
'Discord API 429 %s %s | rate_limit_headers=%s',
method,
url,
hdr,
)
except Exception:
logger.debug('rate_limit trace callback failed', exc_info=True)
trace.on_request_end.append(on_request_end)
return trace
+2
View File
@@ -55,6 +55,8 @@ if __name__ == '__main__':
# Calmer les logs verbeux de certaines libs si besoin
logging.getLogger('werkzeug').setLevel(logging.WARNING)
logging.getLogger('discord').setLevel(logging.WARNING)
# 429 : en-têtes X-RateLimit-* (voir discordbot/rate_limit_logging.py + doc Discord rate limits)
logging.getLogger('discord.ratelimit_headers').setLevel(logging.WARNING)
# Hook exceptions non-capturées (threads inclus)
def _log_uncaught(exc_type, exc, tb):