diff options
author | 2024-03-26 18:13:24 +0000 | |
---|---|---|
committer | 2024-03-26 18:13:24 +0000 | |
commit | 726c16c3664e6520e93a524ea9d006410512fed9 (patch) | |
tree | b0475cb680c2d8c779fe0743faf2f7710782b9f0 | |
parent | Bump emoji from 2.10.1 to 2.11.0 (#2974) (diff) | |
parent | Add sentry performance spans to thread bumper cog (diff) |
Merge pull request #2976 from python-discord/capture-cog-load-times
Capture cog load times using sentry performance tracking
-rw-r--r-- | bot/bot.py | 7 | ||||
-rw-r--r-- | bot/exts/info/python_news.py | 30 | ||||
-rw-r--r-- | bot/exts/info/subscribe.py | 34 | ||||
-rw-r--r-- | bot/exts/utils/thread_bumper.py | 40 |
4 files changed, 65 insertions, 46 deletions
diff --git a/bot/bot.py b/bot/bot.py index 84caf1873..fa3617f1b 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -6,7 +6,7 @@ import aiohttp from discord.errors import Forbidden from pydis_core import BotBase from pydis_core.utils.error_handling import handle_forbidden_from_block -from sentry_sdk import push_scope +from sentry_sdk import push_scope, start_transaction from bot import constants, exts from bot.log import get_logger @@ -29,6 +29,11 @@ class Bot(BotBase): super().__init__(*args, **kwargs) + async def load_extension(self, name: str, *args, **kwargs) -> None: + """Extend D.py's load_extension function to also record sentry performance stats.""" + with start_transaction(op="cog-load", name=name): + await super().load_extension(name, *args, **kwargs) + async def ping_services(self) -> None: """A helper to make sure all the services the bot relies on are available on startup.""" # Connect Site/API diff --git a/bot/exts/info/python_news.py b/bot/exts/info/python_news.py index e06c82bb8..c786a9d19 100644 --- a/bot/exts/info/python_news.py +++ b/bot/exts/info/python_news.py @@ -4,6 +4,7 @@ from datetime import UTC, datetime, timedelta import discord import feedparser +import sentry_sdk from bs4 import BeautifulSoup from discord.ext.commands import Cog from discord.ext.tasks import loop @@ -43,6 +44,22 @@ class PythonNews(Cog): self.webhook: discord.Webhook | None = None self.seen_items: dict[str, set[str]] = {} + async def cog_load(self) -> None: + """Load all existing seen items from db and create any missing mailing lists.""" + with sentry_sdk.start_span(description="Fetch mailing lists from site"): + response = await self.bot.api_client.get("bot/mailing-lists") + + for mailing_list in response: + self.seen_items[mailing_list["name"]] = set(mailing_list["seen_items"]) + + with sentry_sdk.start_span(description="Update site with new mailing lists"): + for mailing_list in ("pep", *constants.PythonNews.mail_lists): + if mailing_list not in self.seen_items: + await self.bot.api_client.post("bot/mailing-lists", json={"name": mailing_list}) + self.seen_items[mailing_list] = set() + + self.fetch_new_media.start() + async def cog_unload(self) -> None: """Stop news posting tasks on cog unload.""" self.fetch_new_media.cancel() @@ -225,19 +242,6 @@ class PythonNews(Cog): email_information = await resp.json() return thread_information, email_information - async def cog_load(self) -> None: - """Load all existing seen items from db and create any missing mailing lists.""" - response = await self.bot.api_client.get("bot/mailing-lists") - for mailing_list in response: - self.seen_items[mailing_list["name"]] = set(mailing_list["seen_items"]) - - for mailing_list in ("pep", *constants.PythonNews.mail_lists): - if mailing_list not in self.seen_items: - await self.bot.api_client.post("bot/mailing-lists", json={"name": mailing_list}) - self.seen_items[mailing_list] = set() - - self.fetch_new_media.start() - async def setup(bot: Bot) -> None: """Add `News` cog.""" diff --git a/bot/exts/info/subscribe.py b/bot/exts/info/subscribe.py index 048884587..5e33474bf 100644 --- a/bot/exts/info/subscribe.py +++ b/bot/exts/info/subscribe.py @@ -2,6 +2,7 @@ import operator from dataclasses import dataclass import discord +import sentry_sdk from discord.ext import commands from discord.interactions import Interaction from pydis_core.utils import members @@ -157,24 +158,27 @@ class Subscribe(commands.Cog): await self.bot.wait_until_guild_available() self.guild = self.bot.get_guild(constants.Guild.id) - for role in ASSIGNABLE_ROLES: - discord_role = self.guild.get_role(role.role_id) - if discord_role is None: - log.warning("Could not resolve %d to a role in the guild, skipping.", role.role_id) - continue - self.assignable_roles.append( - AssignableRole( - role_id=role.role_id, - name=discord_role.name, + with sentry_sdk.start_span(description="Prepare assignable roles"): + for role in ASSIGNABLE_ROLES: + discord_role = self.guild.get_role(role.role_id) + if discord_role is None: + log.warning("Could not resolve %d to a role in the guild, skipping.", role.role_id) + continue + self.assignable_roles.append( + AssignableRole( + role_id=role.role_id, + name=discord_role.name, + ) ) - ) + # Sort by role name + self.assignable_roles.sort(key=operator.attrgetter("name")) - # Sort by role name - self.assignable_roles.sort(key=operator.attrgetter("name")) + with sentry_sdk.start_span(description="Fetch/create the self assignable roles message"): + placeholder_message_view_tuple = await self._fetch_or_create_self_assignable_roles_message() + self_assignable_roles_message, self_assignable_roles_view = placeholder_message_view_tuple - placeholder_message_view_tuple = await self._fetch_or_create_self_assignable_roles_message() - self_assignable_roles_message, self_assignable_roles_view = placeholder_message_view_tuple - self._attach_persistent_roles_view(self_assignable_roles_message, self_assignable_roles_view) + with sentry_sdk.start_span(description="Attach self assignable role persistent view"): + self._attach_persistent_roles_view(self_assignable_roles_message, self_assignable_roles_view) @commands.cooldown(1, 10, commands.BucketType.member) @commands.command(name="subscribe", aliases=("unsubscribe",)) diff --git a/bot/exts/utils/thread_bumper.py b/bot/exts/utils/thread_bumper.py index e93301e0c..588ea1274 100644 --- a/bot/exts/utils/thread_bumper.py +++ b/bot/exts/utils/thread_bumper.py @@ -1,5 +1,6 @@ import discord +import sentry_sdk from discord.ext import commands from pydis_core.site_api import ResponseCodeError from pydis_core.utils.channel import get_or_fetch_channel @@ -67,23 +68,28 @@ class ThreadBumper(commands.Cog): await self.bot.wait_until_guild_available() threads_to_maybe_bump = [] - for thread_id in await self.bot.api_client.get(THREAD_BUMP_ENDPOINT): - try: - thread = await get_or_fetch_channel(self.bot, thread_id) - except discord.NotFound: - log.info("Thread %d has been deleted, removing from bumped threads.", thread_id) - await self.bot.api_client.delete(f"{THREAD_BUMP_ENDPOINT}/{thread_id}") - continue - - if not isinstance(thread, discord.Thread): - await self.bot.api_client.delete(f"{THREAD_BUMP_ENDPOINT}/{thread_id}") - continue - - if thread.archived: - threads_to_maybe_bump.append(thread) - - if threads_to_maybe_bump: - await self.unarchive_threads_not_manually_archived(threads_to_maybe_bump) + with sentry_sdk.start_span(description="Fetch threads to bump from site"): + bumped_threads_from_site = await self.bot.api_client.get(THREAD_BUMP_ENDPOINT) + + with sentry_sdk.start_span(description="Sync bumped threads in site with current guild state"): + for thread_id in bumped_threads_from_site: + try: + thread = await get_or_fetch_channel(self.bot, thread_id) + except discord.NotFound: + log.info("Thread %d has been deleted, removing from bumped threads.", thread_id) + await self.bot.api_client.delete(f"{THREAD_BUMP_ENDPOINT}/{thread_id}") + continue + + if not isinstance(thread, discord.Thread): + await self.bot.api_client.delete(f"{THREAD_BUMP_ENDPOINT}/{thread_id}") + continue + + if thread.archived: + threads_to_maybe_bump.append(thread) + + with sentry_sdk.start_span(description="Unarchive threads that should be bumped"): + if threads_to_maybe_bump: + await self.unarchive_threads_not_manually_archived(threads_to_maybe_bump) @commands.group(name="bump") async def thread_bump_group(self, ctx: commands.Context) -> None: |