Merge PR #899 into next, resolve conflicts in server.py and docs/browser-crawler-config.md

This commit is contained in:
unclecode
2025-04-22 14:56:47 +08:00
16 changed files with 132 additions and 140 deletions

View File

@@ -4,6 +4,7 @@ from typing import Optional, Dict, Any
from colorama import Fore, Style, init
import os
from datetime import datetime
from urllib.parse import unquote
class LogLevel(Enum):
@@ -44,11 +45,11 @@ class AsyncLoggerBase(ABC):
pass
@abstractmethod
def url_status(self, url: str, success: bool, timing: float, tag: str = "FETCH", url_length: int = 50):
def url_status(self, url: str, success: bool, timing: float, tag: str = "FETCH", url_length: int = 100):
pass
@abstractmethod
def error_status(self, url: str, error: str, tag: str = "ERROR", url_length: int = 50):
def error_status(self, url: str, error: str, tag: str = "ERROR", url_length: int = 100):
pass
class AsyncLogger(AsyncLoggerBase):
@@ -130,6 +131,14 @@ class AsyncLogger(AsyncLoggerBase):
def _get_icon(self, tag: str) -> str:
"""Get the icon for a tag, defaulting to info icon if not found."""
return self.icons.get(tag, self.icons["INFO"])
def _shorten(self, text, length, placeholder="..."):
"""Truncate text in the middle if longer than length, or pad if shorter."""
if len(text) <= length:
return text.ljust(length) # Pad with spaces to reach desired length
half = (length - len(placeholder)) // 2
shortened = text[:half] + placeholder + text[-half:]
return shortened.ljust(length) # Also pad shortened text to consistent length
def _write_to_file(self, message: str):
"""Write a message to the log file if configured."""
@@ -259,7 +268,7 @@ class AsyncLogger(AsyncLoggerBase):
success: bool,
timing: float,
tag: str = "FETCH",
url_length: int = 50,
url_length: int = 100,
):
"""
Convenience method for logging URL fetch status.
@@ -271,14 +280,15 @@ class AsyncLogger(AsyncLoggerBase):
tag: Tag for the message
url_length: Maximum length for URL in log
"""
decoded_url = unquote(url)
readable_url = self._shorten(decoded_url, url_length)
self._log(
level=LogLevel.SUCCESS if success else LogLevel.ERROR,
message="{url:.{url_length}}... | Status: {status} | Time: {timing:.2f}s",
message="{url} | {status} | : {timing:.2f}s",
tag=tag,
params={
"url": url,
"url_length": url_length,
"status": success,
"url": readable_url,
"status": "" if success else "",
"timing": timing,
},
colors={
@@ -299,11 +309,13 @@ class AsyncLogger(AsyncLoggerBase):
tag: Tag for the message
url_length: Maximum length for URL in log
"""
decoded_url = unquote(url)
readable_url = self._shorten(decoded_url, url_length)
self._log(
level=LogLevel.ERROR,
message="{url:.{url_length}}... | Error: {error}",
message="{url} | Error: {error}",
tag=tag,
params={"url": url, "url_length": url_length, "error": error},
params={"url": readable_url, "error": error},
)
class AsyncFileLogger(AsyncLoggerBase):
@@ -347,13 +359,13 @@ class AsyncFileLogger(AsyncLoggerBase):
"""Log an error message to file."""
self._write_to_file("ERROR", message, tag)
def url_status(self, url: str, success: bool, timing: float, tag: str = "FETCH", url_length: int = 50):
def url_status(self, url: str, success: bool, timing: float, tag: str = "FETCH", url_length: int = 100):
"""Log URL fetch status to file."""
status = "SUCCESS" if success else "FAILED"
message = f"{url[:url_length]}... | Status: {status} | Time: {timing:.2f}s"
self._write_to_file("URL_STATUS", message, tag)
def error_status(self, url: str, error: str, tag: str = "ERROR", url_length: int = 50):
def error_status(self, url: str, error: str, tag: str = "ERROR", url_length: int = 100):
"""Log error status to file."""
message = f"{url[:url_length]}... | Error: {error}"
self._write_to_file("ERROR", message, tag)