Skip to content

Commit

Permalink
merge changes
Browse files Browse the repository at this point in the history
  • Loading branch information
RobbyV2 committed Oct 13, 2023
1 parent c1b8c2c commit 0cda763
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 11 deletions.
2 changes: 1 addition & 1 deletion ballsdex/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "2.8.1"
__version__ = "2.9.1"
42 changes: 42 additions & 0 deletions ballsdex/core/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import asyncio
import logging
import math
import types
import inspect
from typing import cast

import aiohttp
Expand All @@ -12,6 +14,7 @@
from discord import app_commands
from discord.ext import commands
from rich import print
from prometheus_client import Histogram

from ballsdex.core.dev import Dev
from ballsdex.core.metrics import PrometheusServer
Expand All @@ -31,6 +34,7 @@
from ballsdex.settings import settings

log = logging.getLogger("ballsdex.core.bot")
http_counter = Histogram("discord_http_requests", "HTTP requests", ["key", "code"])

PACKAGES = ["config", "players", "countryballs", "info", "admin", "trade"]

Expand All @@ -39,6 +43,38 @@ def owner_check(ctx: commands.Context[BallsDexBot]):
return ctx.bot.is_owner(ctx.author)


# observing the duration and status code of HTTP requests through aiohttp TraceConfig
async def on_request_start(
session: aiohttp.ClientSession,
trace_ctx: types.SimpleNamespace,
params: aiohttp.TraceRequestStartParams,
):
# register t1 before sending request
trace_ctx.start = session.loop.time()


async def on_request_end(
session: aiohttp.ClientSession,
trace_ctx: types.SimpleNamespace,
params: aiohttp.TraceRequestEndParams,
):
time = session.loop.time() - trace_ctx.start

# to categorize HTTP calls per path, we need to access the corresponding discord.http.Route
# object, which is not available in the context of an aiohttp TraceConfig, therefore it's
# obtained by accessing the locals() from the calling function HTTPConfig.request
# "params.url.path" is not usable as it contains raw IDs and tokens, breaking categories
frame = inspect.currentframe()
_locals = frame.f_back.f_back.f_back.f_back.f_back.f_locals
if route := _locals.get("route"):
route_key = route.key
else:
# calling function is HTTPConfig.static_login which has no Route object
route_key = f"{params.response.method} {params.url.path}"

http_counter.labels(route_key, params.response.status).observe(time)


class CommandTree(app_commands.CommandTree):
async def interaction_check(self, interaction: discord.Interaction, /) -> bool:
bot = cast(BallsDexBot, interaction.client)
Expand Down Expand Up @@ -68,6 +104,12 @@ def __init__(self, command_prefix: str, dev: bool = False, **options):
guilds=True, guild_messages=True, emojis_and_stickers=True, message_content=True
)

if settings.prometheus_enabled:
trace = aiohttp.TraceConfig()
trace.on_request_start.append(on_request_start)
trace.on_request_end.append(on_request_end)
options["http_trace"] = trace

super().__init__(command_prefix, intents=intents, tree_cls=CommandTree, **options)

self.dev = dev
Expand Down
10 changes: 8 additions & 2 deletions ballsdex/core/metrics.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import logging
import math

from aiohttp import web
from collections import defaultdict
from prometheus_client import Gauge, Histogram, generate_latest, CONTENT_TYPE_LATEST
from typing import TYPE_CHECKING

Expand All @@ -27,13 +29,17 @@ def __init__(self, bot: "BallsDexBot", host: str = "localhost", port: int = 1526

self.app.add_routes((web.get("/metrics", self.get),))

self.guild_count = Gauge("guilds", "Number of guilds the server is in")
self.guild_count = Gauge("guilds", "Number of guilds the server is in", ["size"])
self.shards_latecy = Histogram(
"gateway_latency", "Shard latency with the Discord gateway", ["shard_id"]
)

async def collect_metrics(self):
self.guild_count.set(len(self.bot.guilds))
guilds: dict[int, int] = defaultdict(int)
for guild in self.bot.guilds:
guilds[10 ** math.ceil(math.log(max(guild.member_count - 1, 1), 10))] += 1
for size, count in guilds.items():
self.guild_count.labels(size=size).set(count)

for shard_id, latency in self.bot.latencies:
self.shards_latecy.labels(shard_id=shard_id).observe(latency)
Expand Down
31 changes: 25 additions & 6 deletions ballsdex/packages/players/cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ class SortingChoices(enum.Enum):
catch_date = "-catch_date"
rarity = "ball__rarity"
special = "special__id"
health_bonus = "-health_bonus"
attack_bonus = "-attack_bonus"
stats = "stats"

# manual sorts are not sorted by SQL queries but by our code
# this may be do-able with SQL still, but I don't have much experience ngl
Expand All @@ -111,6 +114,7 @@ async def list(
interaction: discord.Interaction,
user: discord.User | None = None,
sort: SortingChoices | None = None,
reverse: bool = False,
):
"""
List your djiboutiballs.
Expand All @@ -119,8 +123,10 @@ async def list(
----------
user: discord.User
The user whose collection you want to view, if not yours.
sort: SortingCHoices
sort: SortingChoices
Choose how countryballs are sorted. Can be used to show duplicates.
reverse: bool
Reverse the output of the list.
"""
user: discord.User | discord.Member = user or interaction.user
await interaction.response.defer(thinking=True)
Expand All @@ -146,6 +152,8 @@ async def list(
for countryball in countryballs:
count[countryball.countryball.pk] += 1
countryballs.sort(key=lambda m: (-count[m.countryball.pk], m.countryball.pk))
elif sort == SortingChoices.stats:
countryballs = await player.balls.all().order_by("-health_bonus", "-attack_bonus")
else:
countryballs = await player.balls.all().order_by(sort.value)
else:
Expand All @@ -161,6 +169,8 @@ async def list(
f"{user.name} doesn't have any {settings.collectible_name} yet."
)
return
if reverse:
countryballs.reverse()

paginator = CountryballsViewer(interaction, countryballs)
if user == interaction.user:
Expand Down Expand Up @@ -280,23 +290,32 @@ async def info(self, interaction: discord.Interaction, countryball: BallInstance

@app_commands.command()
@app_commands.checks.cooldown(1, 60, key=lambda i: i.user.id)
async def last(self, interaction: discord.Interaction):
async def last(self, interaction: discord.Interaction, user: discord.Member = None):
"""
Display info of your last caught djiboutiball.
Display info of your or another users last caught countryball.
Parameters
----------
user: discord.Member
The user you would like to see
"""
await interaction.response.defer(thinking=True)
try:
player = await Player.get(discord_id=interaction.user.id)
player = await Player.get(discord_id=user_obj.id)
except DoesNotExist:
msg = f"{'You do' if user is None else f'{user_obj.display_name} does'}"
await interaction.followup.send(
f"You do not have any {settings.collectible_name} yet.", ephemeral=True
f"{msg} not have any {settings.collectible_name} yet.",
ephemeral=True,
)
return

countryball = await player.balls.all().order_by("-id").first().select_related("ball")
if not countryball:
msg = f"{'You do' if user is None else f'{user_obj.display_name} does'}"
await interaction.followup.send(
f"You do not have any {settings.collectible_name} yet.", ephemeral=True
f"{msg} not have any {settings.collectible_name} yet.",
ephemeral=True,
)
return

Expand Down
12 changes: 10 additions & 2 deletions ballsdex/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def read_settings(path: "Path"):

def write_default_settings(path: "Path"):
path.write_text(
"""# yaml-language-server: $schema=config-ref.json
"""# yaml-language-server: $schema=json-config-ref.json
# paste the bot token after regenerating it here
discord-token:
Expand Down Expand Up @@ -197,6 +197,7 @@ def update_settings(path: "Path"):
content = path.read_text()

add_owners = True
add_config_ref = "# yaml-language-server: $schema=json-config-ref.json" not in content

for line in content.splitlines():
if line.startswith("owners:"):
Expand All @@ -213,5 +214,12 @@ def update_settings(path: "Path"):
co-owners:
"""

if any((add_owners,)):
if add_config_ref:
if "# yaml-language-server: $schema=config-ref.json" in content:
# old file name replacement
content = content.replace("$schema=config-ref.json", "$schema=json-config-ref.json")
else:
content = "# yaml-language-server: $schema=json-config-ref.json\n" + content

if any((add_owners, add_config_ref)):
path.write_text(content)

0 comments on commit 0cda763

Please sign in to comment.