Skip to content

Commit

Permalink
feat: broadcast logs to websocket
Browse files Browse the repository at this point in the history
  • Loading branch information
Gaisberg authored and Gaisberg committed Aug 14, 2024
1 parent 6eaf4e1 commit c7cf951
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 2 deletions.
22 changes: 21 additions & 1 deletion src/controllers/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from program.scrapers import Scraping
from program.settings.manager import settings_manager
from sqlalchemy import func, select
from loguru import logger

router = APIRouter(
responses={404: {"description": "Not found"}},
Expand Down Expand Up @@ -134,4 +135,23 @@ async def get_stats(_: Request):
payload["incomplete_retries"] = incomplete_retries
payload["states"] = states

return {"success": True, "data": payload}
return {"success": True, "data": payload}

@router.get("/logs")
async def get_logs():
log_file_path = None
for handler in logger._core.handlers.values():
if ".log" in handler._name:
log_file_path = handler._sink._path
break

if not log_file_path:
return {"success": False, "message": "Log file handler not found"}

try:
with open(log_file_path, 'r') as log_file:
log_contents = log_file.read()
return {"success": True, "logs": log_contents}
except Exception as e:
logger.error(f"Failed to read log file: {e}")
return {"success": False, "message": str(e)}

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.
18 changes: 18 additions & 0 deletions src/controllers/ws.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
import asyncio
import json
import logging
from loguru import logger
from fastapi import APIRouter, WebSocket, WebSocketDisconnect

class WebSocketHandler(logging.Handler):
def emit(self, record: logging.LogRecord):
event_loop = None
try:
event_loop = asyncio.get_event_loop()
except RuntimeError:
pass
try:
message = self.format(record)
if event_loop and event_loop.is_running():
asyncio.create_task(manager.send_log_message(message))
else:
asyncio.run(manager.send_log_message(message))
except Exception:
self.handleError(record)

router = APIRouter(
prefix="/ws",
tags=["websocket"],
Expand Down
4 changes: 3 additions & 1 deletion src/utils/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from program.settings.manager import settings_manager
from rich.console import Console
from utils import data_dir_path
from controllers.ws import manager
from controllers.ws import WebSocketHandler

LOG_ENABLED: bool = settings_manager.settings.log

Expand Down Expand Up @@ -112,6 +112,8 @@ def get_log_settings(name, default_color, default_icon):
# }
])

logger.add(WebSocketHandler(), format=log_format)


def scrub_logs():
"""Remove old log files based on retention settings."""
Expand Down

0 comments on commit c7cf951

Please sign in to comment.