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:
@@ -30,11 +30,12 @@ from discordbot.patreon import checkPatreonPosts
|
|||||||
from discordbot.youtube import checkYouTubeVideos
|
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.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.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
|
from protondb import searhProtonDb
|
||||||
|
|
||||||
class DiscordBot(discord.Client):
|
class DiscordBot(discord.Client):
|
||||||
def __init__(self, *, intents: discord.Intents):
|
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.tree = app_commands.CommandTree(self)
|
||||||
self.synced = False
|
self.synced = False
|
||||||
|
|
||||||
|
|||||||
@@ -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 l’option 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
|
||||||
@@ -55,6 +55,8 @@ if __name__ == '__main__':
|
|||||||
# Calmer les logs verbeux de certaines libs si besoin
|
# Calmer les logs verbeux de certaines libs si besoin
|
||||||
logging.getLogger('werkzeug').setLevel(logging.WARNING)
|
logging.getLogger('werkzeug').setLevel(logging.WARNING)
|
||||||
logging.getLogger('discord').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)
|
# Hook exceptions non-capturées (threads inclus)
|
||||||
def _log_uncaught(exc_type, exc, tb):
|
def _log_uncaught(exc_type, exc, tb):
|
||||||
|
|||||||
Reference in New Issue
Block a user