Skip to content

Commit

Permalink
Merge pull request #169 from python-discord/paginate-pod-logs
Browse files Browse the repository at this point in the history
Paginate pod logs instead of truncating them
  • Loading branch information
jb3 authored May 28, 2024
2 parents d7a54e4 + 307dea6 commit dc416fb
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 26 deletions.
1 change: 1 addition & 0 deletions arthur/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Config(
guild_id: int = 267624335836053506
devops_channel_id: int = 675756741417369640
sentry_dsn: str = ""
trashcan: str = "<:trashcan:637136429717389331>"


GIT_SHA = environ.get("GIT_SHA", "development")
Expand Down
53 changes: 28 additions & 25 deletions arthur/exts/kubernetes/pods.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import zoneinfo
from datetime import datetime

import discord
import humanize
from discord.ext import commands
from kubernetes_asyncio.client.rest import ApiException
Expand All @@ -12,6 +13,7 @@
from arthur.apis.kubernetes import pods
from arthur.bot import KingArthur
from arthur.config import CONFIG
from arthur.pagination import LinePaginator
from arthur.utils import generate_error_message

MAX_MESSAGE_LENGTH = 2000
Expand Down Expand Up @@ -46,9 +48,10 @@ async def pods_list(self, ctx: commands.Context, namespace: str = "default") ->
pod_list = await pods.list_pods(namespace)

if len(pod_list.items) == 0:
return await ctx.send(
await ctx.send(
generate_error_message(description="No pods found, check the namespace exists.")
)
return

tables = [[]]

Expand Down Expand Up @@ -95,7 +98,7 @@ async def pods_list(self, ctx: commands.Context, namespace: str = "default") ->
for table in tables:
await ctx.send(tabulate_pod_data(table))

return None
return

@pods_cmd.command(name="logs", aliases=["log", "tail"])
@commands.check(lambda ctx: ctx.channel.id == CONFIG.devops_channel_id)
Expand All @@ -116,46 +119,46 @@ async def pods_logs(
pod_names = [pod_name]

if pod_names is None:
return await ctx.send(
await ctx.send(
generate_error_message(description="No pods found for the provided deployment.")
)
return

for pod in pod_names:
try:
logs = await pods.tail_pod(namespace, pod, lines=lines)
except ApiException as e:
if e.status == 404: # noqa: PLR2004, 404 is a known error
return await ctx.send(
await ctx.send(
generate_error_message(
description="Pod or namespace not found, check the name."
)
)
return await ctx.send(generate_error_message(description=str(e)))
return
await ctx.send(generate_error_message(description=str(e)))
return

if len(logs) == 0:
return await ctx.send(
generate_error_message(description="No logs found for the pod.")
)
await ctx.send(generate_error_message(description="No logs found for the pod."))
return

truncated = False
logs = logs.splitlines()

if len(logs) > MAX_MESSAGE_LENGTH - 100:
truncated = True
while len(logs) > MAX_MESSAGE_LENGTH - 100:
logs = logs[: logs.rfind("\n")]

message = f"**Logs for pod `{pod}` in namespace `{namespace}`**\n"

if truncated:
message += "`[Logs truncated]`\n"

message += "```"
message += logs
message += "```"

await ctx.send(message)
logs_embed = discord.Embed(
title=f"**Logs for pod `{pod}` in namespace `{namespace}`**",
colour=discord.Colour.blue(),
)
await LinePaginator.paginate(
lines=logs,
ctx=ctx,
max_size=MAX_MESSAGE_LENGTH,
empty=False,
embed=logs_embed,
prefix="```\n",
suffix="```",
)

return None
return


async def setup(bot: KingArthur) -> None:
Expand Down
63 changes: 63 additions & 0 deletions arthur/pagination.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from collections.abc import Sequence

import discord
from discord.ext.commands import Context
from pydis_core.utils.pagination import LinePaginator as _LinePaginator, PaginationEmojis

from arthur.config import CONFIG


class LinePaginator(_LinePaginator):
"""
A class that aids in paginating code blocks for Discord messages.
See the super class's docs for more info.
"""

@classmethod
async def paginate(
cls,
lines: list[str],
ctx: Context | discord.Interaction,
embed: discord.Embed,
prefix: str = "",
suffix: str = "",
max_lines: int | None = None,
max_size: int = 500,
scale_to_size: int = 4000,
restrict_to_user: discord.User | None = None,
timeout: int = 300,
footer_text: str | None = None,
url: str | None = None,
allowed_roles: Sequence[int] | None = None,
*,
reply: bool = False,
empty: bool = True,
exception_on_empty_embed: bool = False,
) -> discord.Message | None:
"""
Use a paginator and set of reactions to provide pagination over a set of lines.
Acts as a wrapper for the super class' `paginate` method to provide the pagination emojis by default.
Consult the super class's `paginate` method for detailed information.
"""
return await super().paginate(
pagination_emojis=PaginationEmojis(delete=CONFIG.trashcan),
lines=lines,
ctx=ctx,
embed=embed,
prefix=prefix,
suffix=suffix,
max_lines=max_lines,
max_size=max_size,
scale_to_size=scale_to_size,
empty=empty,
restrict_to_user=restrict_to_user,
timeout=timeout,
footer_text=footer_text,
url=url,
exception_on_empty_embed=exception_on_empty_embed,
reply=reply,
allowed_roles=allowed_roles,
)
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ ignore = [
"S311",
"SIM102", "SIM108",
"PD",
"PLR6301",
"PLR0913", "PLR0917", "PLR6301",

# Rules suggested to be ignored when using ruff format
"COM812", "D206", "E111", "E114", "E117", "E501", "ISC001", "Q000", "Q001", "Q002", "Q003", "W191",
Expand Down

0 comments on commit dc416fb

Please sign in to comment.