Skip to content

Commit

Permalink
Added timed rotating file handler for logging, and improved the LogHe…
Browse files Browse the repository at this point in the history
…lper
  • Loading branch information
LobaDK committed Apr 12, 2024
1 parent 5f002d0 commit 146373a
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 27 deletions.
11 changes: 8 additions & 3 deletions QuantumKat.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,11 @@ async def init_models():
misc_helper = MiscHelper()
discord_helper = DiscordHelper()

logger = log_helper.create_logger("QuantumKat", "logs/QuantumKat.log")
logger = log_helper.create_logger(
log_helper.TimedRotatingFileAndStreamHandler(
logger_name="QuantumKat", log_file="logs/quantumkat/QuantumKat.log"
)
)

# If False, will exit if a required program is missing
# Can be set to True for debugging without needing them installed
Expand Down Expand Up @@ -197,7 +201,8 @@ async def ensure_user_in_db(ctx: commands.Context) -> None:
view.message = await ctx.send(
textwrap.dedent(
"""\
Hello! Looks like this is your first time interacting with me. In order to for certain commands to work properly, I need to store your Discord username and user ID in my database. Alongside this, I also log all errors and my commands for debugging purposes.
Hello! Looks like this is your first time interacting with me. In order for certain commands to work properly, I need to store your Discord username and user ID in my database. Alongside this, I also log all errors and my commands for debugging purposes.
Logs are stored for approximately 1-7 days before being deleted.
The following commands store additional information in the database:
- `?chat` and `?sharedchat` stores the chat history between you and me.
Expand Down Expand Up @@ -281,7 +286,7 @@ async def on_ready():
Latency to Discord: {int(bot.latency * 1000)}ms.
Discord.py version: {discord.__version__}
\nStarted at {datetime.now()}\n
{bot.user} has appeared from the {num2words(randint(1,1000),
{bot.user} has appeared from the {num2words(randint(1, 1000),
to="ordinal_num")} {choice(quantum)}!"""
logger.info(message)
print(message)
Expand Down
7 changes: 6 additions & 1 deletion cogs/Activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@
from discord import Game
from discord.ext import commands, tasks
from num2words import num2words
from helpers import LogHelper


class Activity(commands.Cog):
def __init__(self, bot: commands.Bot):

self.bot = bot

self.logger = bot.log_helper.create_logger("Activity", "logs/Activity.log")
self.logger = bot.log_helper.create_logger(
LogHelper.TimedRotatingFileAndStreamHandler(
logger_name="Activity", log_file="logs/activity/Activity.log"
)
)

self.hissList = ["Hissing", "Hissed"]

Expand Down
3 changes: 2 additions & 1 deletion cogs/Auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import sys
from sql import database
from sql import crud, schemas
from helpers import LogHelper

sys.path.append(".")

Expand All @@ -11,7 +12,7 @@ class Auth(commands.Cog):
def __init__(self, bot: commands.Bot) -> None:
self.bot = bot

self.logger = bot.log_helper.create_logger("Auth", "logs/Auth.log")
self.logger = bot.log_helper.create_logger(LogHelper.TimedRotatingFileAndStreamHandler(logger_name="Auth", log_file="logs/auth/Auth.log"))

@commands.command(aliases=["requestauth", "auth"])
@commands.cooldown(1, 300, commands.BucketType.guild)
Expand Down
3 changes: 2 additions & 1 deletion cogs/Chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from sql import database
from sql import crud, schemas
from helpers import LogHelper

sys.path.append(".")

Expand All @@ -18,7 +19,7 @@ class Chat(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot

self.logger = bot.log_helper.create_logger("Chat", "logs/Chat.log")
self.logger = bot.log_helper.create_logger(LogHelper.TimedRotatingFileAndStreamHandler(logger_name="Chat", log_file="logs/chat/Chat.log"))

self.historylogger = bot.log_helper.create_logger(
"ChatHistory", "logs/ChatHistory.log"
Expand Down
7 changes: 6 additions & 1 deletion cogs/Control.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@
import discord

from discord.ext import commands
from helpers import LogHelper


class Control(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
self.locations = ["universe", "reality", "dimension", "timeline"]

self.logger = bot.log_helper.create_logger("Control", "logs/Control.log")
self.logger = bot.log_helper.create_logger(
LogHelper.TimedRotatingFileAndStreamHandler(
logger_name="Control", log_file="logs/control/Control.log"
)
)

async def get_permissions(self, guild: discord.Guild) -> list[str]:
permissions = []
Expand Down
6 changes: 5 additions & 1 deletion cogs/Entanglement.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@
from discord.ext import commands
from num2words import num2words
from psutil import cpu_percent, disk_usage, virtual_memory
from helpers import LogHelper


class Entanglements(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot

self.logger = bot.log_helper.create_logger(
"Entanglements", "logs/Entanglements.log"
LogHelper.TimedRotatingFileAndStreamHandler(
logger_name="Entanglements",
log_file="logs/entanglements/Entanglements.log",
)
)

initial_extensions = []
Expand Down
7 changes: 6 additions & 1 deletion cogs/Field.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,18 @@
from ntplib import NTPClient
from num2words import num2words
from re import compile
from helpers import LogHelper


class Fields(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot

self.logger = bot.log_helper.create_logger("Fields", "logs/Fields.log")
self.logger = bot.log_helper.create_logger(
LogHelper.TimedRotatingFileAndStreamHandler(
logger_name="Fields", log_file="logs/fields/Fields.log"
)
)

self.aURL = "https://aaaa.lobadk.com/"
self.a_folder = "/var/www/aaaa/"
Expand Down
7 changes: 6 additions & 1 deletion cogs/Tunnel.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@

from discord.ext import commands
from discord import Client
from helpers import LogHelper


class Tunnel(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot

self.logger = bot.log_helper.create_logger("Tunnel", "logs/Tunnel.log")
self.logger = bot.log_helper.create_logger(
LogHelper.TimedRotatingFileAndStreamHandler(
logger_name="Tunnel", log_file="logs/tunnel/Tunnel.log"
)
)

@commands.Cog.listener()
async def on_command_error(
Expand Down
85 changes: 69 additions & 16 deletions helpers.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import logging
from logging.handlers import TimedRotatingFileHandler
import sqlite3
import os
import shutil
import discord
from discord.ext import commands
from pydantic import BaseModel
from typing import Optional

"""
This module contains helper classes for logging, database operations, Discord-related operations, and miscellaneous utility functions.
Expand All @@ -25,6 +28,18 @@ class LogHelper:
create_logger(logger_name, log_file, file_log_level, stream_log_level): Creates a logger with the given name and log file.
"""

class HandlerBase(BaseModel):
logger_name: str
log_file: str

class FileAndStreamHandler(HandlerBase):
file_log_level: Optional[int] = logging.INFO
stream_log_level: Optional[int] = logging.ERROR

class TimedRotatingFileAndStreamHandler(FileAndStreamHandler):
interval: Optional[str] = "midnight"
backup_count: Optional[int] = 7

def logger_exists(self, logger_name: str) -> bool:
"""
Checks if a logger with the given name exists.
Expand All @@ -38,11 +53,7 @@ def logger_exists(self, logger_name: str) -> bool:
return logger_name in logging.Logger.manager.loggerDict

def create_logger(
self,
logger_name: str,
log_file: str,
file_log_level=logging.INFO,
stream_log_level=logging.ERROR,
self, log: FileAndStreamHandler | TimedRotatingFileAndStreamHandler
) -> logging.Logger:
"""
Creates a logger with the given name and log file.
Expand All @@ -52,25 +63,32 @@ def create_logger(
If the logger already exists, it will be returned without any changes.
Args:
logger_name (str): The name of the logger to create.
log_file (str): The path to the log file to use.
file_log_level (int, optional): The log level for the file handler. Defaults to logging.INFO.
stream_log_level (int, optional): The log level for the stream handler. Defaults to logging.ERROR.
log (FileAndStreamHandler | TimedRotatingFileAndStreamHandler): The log object containing the logger name and log file.
Returns:
logging.Logger: The created logger.
"""
if self.logger_exists(logger_name):
return logging.getLogger(logger_name)
if self.logger_exists(log.logger_name):
return logging.getLogger(log.logger_name)

logger = logging.getLogger(logger_name)
logger = logging.getLogger(log.logger_name)
logger.setLevel(logging.DEBUG)
file_handler = self._create_file_handler(log_file, file_log_level)
logger.addHandler(file_handler)

stream_handler = self._create_stream_handler(stream_log_level)
stream_handler = self._create_stream_handler(log.stream_log_level)
logger.addHandler(stream_handler)

if isinstance(log, self.FileAndStreamHandler):
file_handler = self._create_file_handler(log.log_file, log.file_log_level)
logger.addHandler(file_handler)
elif isinstance(log, self.TimedRotatingFileAndStreamHandler):
timed_rotating_file_handler = self._create_timed_rotating_file_handler(
log.log_file,
log.file_log_level,
log.interval,
log.backup_count,
)
logger.addHandler(timed_rotating_file_handler)

return logger

def _create_file_handler(self, log_file: str, level: int) -> logging.FileHandler:
Expand Down Expand Up @@ -118,6 +136,37 @@ def _create_stream_handler(self, level: int) -> logging.StreamHandler:
handler.setLevel(level)
return handler

def _create_timed_rotating_file_handler(
self, log_file: str, level: int, interval: str, backup_count: int
) -> TimedRotatingFileHandler:
"""
Creates a logging TimedRotatingFileHandler with the specified log file, level, interval, and backup count.
Args:
log_file (str): The path and name of the log file to create.
level (int): The log level for the file handler.
interval (str): The interval at which log files should be rotated (e.g., 'midnight', 'daily', 'weekly', 'monthly').
backup_count (int): The number of backup log files to keep.
Returns:
logging.handlers.TimedRotatingFileHandler: The created TimedRotatingFileHandler object.
"""
handler = TimedRotatingFileHandler(
filename=log_file,
when=interval,
backupCount=backup_count,
encoding="utf-8",
)
date_format = "%Y-%m-%d %H:%M:%S"
formatter = logging.Formatter(
"[{asctime}] [{levelname:<8}] {name}: {message}",
datefmt=date_format,
style="{",
)
handler.setFormatter(formatter)
handler.setLevel(level)
return handler


class DBHelper:
"""
Expand All @@ -140,7 +189,11 @@ class DBHelper:
def __init__(
self,
conn: sqlite3.Connection,
logger=LogHelper().create_logger("DBHelper", "logs/db.log"),
logger=LogHelper().create_logger(
LogHelper.TimedRotatingFileAndStreamHandler(
logger_name="DBHelper", log_file="logs/db.log"
)
),
):
"""
DBHelper constructor.
Expand Down
7 changes: 6 additions & 1 deletion pubapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,20 @@
class Search(BaseModel):
search: str


class SearchResponse(BaseModel):
files: list[str]
count: int


class AppendSearch(Search):
pass


class AppendSearchResponse(BaseModel):
file: str


@app.exception_handler(HTTPException)
async def http_exception_handler(request, exc):
return JSONResponse(
Expand Down Expand Up @@ -84,6 +88,7 @@ async def aaaasearch(request: Request, search: Search = Depends(Search)):
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e)
)


@app.get("/a/", response_model=AppendSearchResponse)
@limiter.limit("10/minute")
async def a(request: Request, search: AppendSearch = Depends(AppendSearch)):
Expand All @@ -105,7 +110,7 @@ async def a(request: Request, search: AppendSearch = Depends(AppendSearch)):
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e)
)


def start_api():
uvicorn.run(app, host="127.0.0.1", port=8000)

0 comments on commit 146373a

Please sign in to comment.