aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Joseph Banks <[email protected]>2020-04-11 22:11:43 +0100
committerGravatar Joseph Banks <[email protected]>2020-04-11 22:11:43 +0100
commitee5a4df9537b46cdceb35243d887e84601d07795 (patch)
tree0a513a8030f2e6b21e1c876635bec3a76aa9b8ee
parentMerge branch 'master' into stats (diff)
Additional statistics
-rw-r--r--bot/cogs/defcon.py2
-rw-r--r--bot/cogs/error_handler.py14
-rw-r--r--bot/cogs/help_channels.py24
-rw-r--r--bot/cogs/stats.py14
4 files changed, 45 insertions, 9 deletions
diff --git a/bot/cogs/defcon.py b/bot/cogs/defcon.py
index 06b2f25c6..9197dcca3 100644
--- a/bot/cogs/defcon.py
+++ b/bot/cogs/defcon.py
@@ -146,6 +146,8 @@ class Defcon(Cog):
await ctx.send(self.build_defcon_msg(action, error))
await self.send_defcon_log(action, ctx.author, error)
+ self.bot.stats.gauge("defcon.days", days)
+
@defcon_group.command(name='enable', aliases=('on', 'e'))
@with_role(Roles.admins, Roles.owners)
async def enable_command(self, ctx: Context) -> None:
diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py
index 722376cc6..dae283c6a 100644
--- a/bot/cogs/error_handler.py
+++ b/bot/cogs/error_handler.py
@@ -171,19 +171,25 @@ class ErrorHandler(Cog):
if isinstance(e, errors.MissingRequiredArgument):
await ctx.send(f"Missing required argument `{e.param.name}`.")
await ctx.invoke(*help_command)
+ self.bot.stats.incr("errors.missing_required_argument")
elif isinstance(e, errors.TooManyArguments):
await ctx.send(f"Too many arguments provided.")
await ctx.invoke(*help_command)
+ self.bot.stats.incr("errors.too_many_arguments")
elif isinstance(e, errors.BadArgument):
await ctx.send(f"Bad argument: {e}\n")
await ctx.invoke(*help_command)
+ self.bot.stats.incr("errors.bad_argument")
elif isinstance(e, errors.BadUnionArgument):
await ctx.send(f"Bad argument: {e}\n```{e.errors[-1]}```")
+ self.bot.stats.incr("errors.bad_union_argument")
elif isinstance(e, errors.ArgumentParsingError):
await ctx.send(f"Argument parsing error: {e}")
+ self.bot.stats.incr("errors.argument_parsing_error")
else:
await ctx.send("Something about your input seems off. Check the arguments:")
await ctx.invoke(*help_command)
+ self.bot.stats.incr("errors.other_user_input_error")
@staticmethod
async def handle_check_failure(ctx: Context, e: errors.CheckFailure) -> None:
@@ -205,10 +211,12 @@ class ErrorHandler(Cog):
)
if isinstance(e, bot_missing_errors):
+ ctx.bot.stats.incr("errors.bot_permission_error")
await ctx.send(
f"Sorry, it looks like I don't have the permissions or roles I need to do that."
)
elif isinstance(e, (InChannelCheckFailure, errors.NoPrivateMessage)):
+ ctx.bot.stats.incr("errors.wrong_channel_or_dm_error")
await ctx.send(e)
@staticmethod
@@ -217,16 +225,20 @@ class ErrorHandler(Cog):
if e.status == 404:
await ctx.send("There does not seem to be anything matching your query.")
log.debug(f"API responded with 404 for command {ctx.command}")
+ ctx.bot.stats.incr("errors.api_error_404")
elif e.status == 400:
content = await e.response.json()
log.debug(f"API responded with 400 for command {ctx.command}: %r.", content)
await ctx.send("According to the API, your request is malformed.")
+ ctx.bot.stats.incr("errors.api_error_400")
elif 500 <= e.status < 600:
await ctx.send("Sorry, there seems to be an internal issue with the API.")
log.warning(f"API responded with {e.status} for command {ctx.command}")
+ ctx.bot.stats.incr("errors.api_internal_server_error")
else:
await ctx.send(f"Got an unexpected status code from the API (`{e.status}`).")
log.warning(f"Unexpected API response for command {ctx.command}: {e.status}")
+ ctx.bot.stats.incr(f"errors.api_error_{e.status}")
@staticmethod
async def handle_unexpected_error(ctx: Context, e: errors.CommandError) -> None:
@@ -236,7 +248,7 @@ class ErrorHandler(Cog):
f"```{e.__class__.__name__}: {e}```"
)
- ctx.bot.stats.incr("errors.commands")
+ ctx.bot.stats.incr("errors.unexpected")
with push_scope() as scope:
scope.user = {
diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py
index 389a4ad2a..01a77db2b 100644
--- a/bot/cogs/help_channels.py
+++ b/bot/cogs/help_channels.py
@@ -127,6 +127,9 @@ class HelpChannels(Scheduler, commands.Cog):
self.on_message_lock = asyncio.Lock()
self.init_task = self.bot.loop.create_task(self.init_cog())
+ # Stats
+ self.claim_times = {}
+
def cog_unload(self) -> None:
"""Cancel the init task and scheduled tasks when the cog unloads."""
log.trace("Cog unload: cancelling the init_cog task")
@@ -195,7 +198,7 @@ class HelpChannels(Scheduler, commands.Cog):
if ctx.channel.category == self.in_use_category:
self.cancel_task(ctx.channel.id)
- await self.move_to_dormant(ctx.channel)
+ await self.move_to_dormant(ctx.channel, "command")
else:
log.debug(f"{ctx.author} invoked command 'dormant' outside an in-use help channel")
@@ -406,7 +409,7 @@ class HelpChannels(Scheduler, commands.Cog):
f"and will be made dormant."
)
- await self.move_to_dormant(channel)
+ await self.move_to_dormant(channel, "auto")
else:
# Cancel the existing task, if any.
if has_task:
@@ -446,8 +449,12 @@ class HelpChannels(Scheduler, commands.Cog):
await self.ensure_permissions_synchronization(self.available_category)
self.report_stats()
- async def move_to_dormant(self, channel: discord.TextChannel) -> None:
- """Make the `channel` dormant."""
+ async def move_to_dormant(self, channel: discord.TextChannel, caller: str) -> None:
+ """
+ Make the `channel` dormant.
+
+ A caller argument is provided for metrics.
+ """
log.info(f"Moving #{channel} ({channel.id}) to the Dormant category.")
await channel.edit(
@@ -457,6 +464,13 @@ class HelpChannels(Scheduler, commands.Cog):
topic=DORMANT_TOPIC,
)
+ self.bot.stats.incr(f"help.dormant_calls.{caller}")
+
+ if self.claim_times.get(channel.id):
+ claimed = self.claim_times[channel.id]
+ in_use_time = datetime.now() - claimed
+ self.bot.stats.timer("help.in_use_time", in_use_time)
+
log.trace(f"Position of #{channel} ({channel.id}) is actually {channel.position}.")
log.trace(f"Sending dormant message for #{channel} ({channel.id}).")
@@ -560,6 +574,8 @@ class HelpChannels(Scheduler, commands.Cog):
self.bot.stats.incr("help.claimed")
+ self.claim_times[channel.id] = datetime.now()
+
log.trace(f"Releasing on_message lock for {message.id}.")
# Move a dormant channel to the Available category to fill in the gap.
diff --git a/bot/cogs/stats.py b/bot/cogs/stats.py
index 8fb7d8639..772ae2c97 100644
--- a/bot/cogs/stats.py
+++ b/bot/cogs/stats.py
@@ -1,3 +1,5 @@
+import string
+
from discord import Member, Message, Status
from discord.ext.commands import Bot, Cog, Context
@@ -11,6 +13,8 @@ CHANNEL_NAME_OVERRIDES = {
Channels.staff_lounge: "staff_lounge"
}
+ALLOWED_CHARS = string.ascii_letters + string.digits
+
class Stats(Cog):
"""A cog which provides a way to hook onto Discord events and forward to stats."""
@@ -32,6 +36,8 @@ class Stats(Cog):
if CHANNEL_NAME_OVERRIDES.get(message.channel.id):
reformatted_name = CHANNEL_NAME_OVERRIDES.get(message.channel.id)
+ reformatted_name = "".join([char for char in reformatted_name if char in ALLOWED_CHARS])
+
stat_name = f"channels.{reformatted_name}"
self.bot.stats.incr(stat_name)
@@ -73,13 +79,13 @@ class Stats(Cog):
offline = 0
for member in after.guild.members:
- if member.status == Status.online:
+ if member.status is Status.online:
online += 1
- elif member.status == Status.dnd:
+ elif member.status is Status.dnd:
dnd += 1
- elif member.status == Status.idle:
+ elif member.status is Status.idle:
idle += 1
- else:
+ elif member.status is Status.offline:
offline += 1
self.bot.stats.gauge("guild.status.online", online)