Reduce polling request log noise

This commit is contained in:
Dymas
2026-05-17 21:20:24 +02:00
parent ae090c954b
commit d0af0258f2
6 changed files with 34 additions and 3 deletions
+4
View File
@@ -1,5 +1,9 @@
# Changelog # Changelog
## 0.32.1 - 2026-05-17
- Suppressed stdout request logging for routine polling endpoints such as `/api/queue` and `/api/watchlist/refresh-status`, reducing noisy access-log spam during normal browser use.
## 0.32.0 - 2026-05-17 ## 0.32.0 - 2026-05-17
- Changed bulk `Refresh All` processing to pace requests with a configurable delay between shows, reducing the chance of flooding upstream episode sources on large watchlists. - Changed bulk `Refresh All` processing to pace requests with a configurable delay between shows, reducing the chance of flooding upstream episode sources on large watchlists.
+2 -1
View File
@@ -2,7 +2,7 @@
A local web UI for a system-wide `ani-cli` install. A local web UI for a system-wide `ani-cli` install.
Current version: `0.32.0` Current version: `0.32.1`
## Project Layout ## Project Layout
@@ -159,6 +159,7 @@ The app currently includes:
- Background `Refresh All` execution with status polling, no inline thumbnail downloads during the bulk job, and a configurable delay between shows to reduce upstream request bursts. - Background `Refresh All` execution with status polling, no inline thumbnail downloads during the bulk job, and a configurable delay between shows to reduce upstream request bursts.
- Optional scheduled background watchlist refreshes with Config page controls for enable/disable and refresh period. - Optional scheduled background watchlist refreshes with Config page controls for enable/disable and refresh period.
- Scheduled background refresh runs now log queue, start, and completion status to stdout so container logs show whether they finished successfully, with errors, or failed. - Scheduled background refresh runs now log queue, start, and completion status to stdout so container logs show whether they finished successfully, with errors, or failed.
- Routine browser polling endpoints such as the search-page queue poll and watchlist refresh-status poll now stay quiet in stdout request logs to reduce log spam.
- Search and Watchlist polling now use a shared serial browser polling helper so slow responses do not cause overlapping poll requests to pile up in the background. - Search and Watchlist polling now use a shared serial browser polling helper so slow responses do not cause overlapping poll requests to pile up in the background.
- That shared browser polling helper now also tears itself down on page unload and uses chained `setTimeout` scheduling instead of a bare repeating interval. - That shared browser polling helper now also tears itself down on page unload and uses chained `setTimeout` scheduling instead of a bare repeating interval.
- Controlled shutdown and runtime reset now cancel active download workers when waiting for teardown, reducing the chance of orphaned background downloads outliving the web process. - Controlled shutdown and runtime reset now cancel active download workers when waiting for teardown, reducing the chance of orphaned background downloads outliving the web process.
+1 -1
View File
@@ -1 +1 @@
0.32.0 0.32.1
+1 -1
View File
@@ -16,7 +16,7 @@ from uuid import uuid4
PROJECT_ROOT = Path(__file__).resolve().parent PROJECT_ROOT = Path(__file__).resolve().parent
ANI_CLI = os.environ.get("ANI_CLI_BIN") or shutil.which("ani-cli") or "ani-cli" ANI_CLI = os.environ.get("ANI_CLI_BIN") or shutil.which("ani-cli") or "ani-cli"
APP_NAME = "ani-cli-web" APP_NAME = "ani-cli-web"
VERSION = "0.32.0" VERSION = "0.32.1"
ALLANIME_BASE = "allanime.day" ALLANIME_BASE = "allanime.day"
ALLANIME_API = f"https://api.{ALLANIME_BASE}" ALLANIME_API = f"https://api.{ALLANIME_BASE}"
ALLANIME_REFERER = "https://allmanga.to" ALLANIME_REFERER = "https://allmanga.to"
+4
View File
@@ -70,6 +70,7 @@ def dependency_status():
class Handler(BaseHTTPRequestHandler): class Handler(BaseHTTPRequestHandler):
server_version = "AniCliWeb/1.0" server_version = "AniCliWeb/1.0"
remote_token_cookie_name = "ani_cli_web_token" remote_token_cookie_name = "ani_cli_web_token"
quiet_poll_paths = {"/api/queue", "/api/watchlist/refresh-status"}
def _context(self): def _context(self):
context = getattr(self, "handler_context", None) or getattr(type(self), "handler_context", None) context = getattr(self, "handler_context", None) or getattr(type(self), "handler_context", None)
@@ -467,6 +468,9 @@ class Handler(BaseHTTPRequestHandler):
self.error(HTTPStatus.INTERNAL_SERVER_ERROR, "Internal server error.") self.error(HTTPStatus.INTERNAL_SERVER_ERROR, "Internal server error.")
def log_message(self, fmt, *args): def log_message(self, fmt, *args):
parsed = urlparse(getattr(self, "path", "") or "")
if self.command == "GET" and parsed.path in Handler.quiet_poll_paths:
return
print(f"{self.address_string()} - {fmt % args}") print(f"{self.address_string()} - {fmt % args}")
+22
View File
@@ -1408,6 +1408,28 @@ class HandlerRouteTests(unittest.TestCase):
class TemplateHelperTests(unittest.TestCase): class TemplateHelperTests(unittest.TestCase):
def test_log_message_skips_queue_poll_requests(self):
handler = object.__new__(APP.Handler)
handler.path = "/api/queue?page=1&per_page=10"
handler.command = "GET"
handler.address_string = lambda: "127.0.0.1"
with mock.patch("builtins.print") as print_mock:
APP.Handler.log_message(handler, '"GET /api/queue?page=1&per_page=10 HTTP/1.1" %s -', 200)
print_mock.assert_not_called()
def test_log_message_keeps_non_poll_requests(self):
handler = object.__new__(APP.Handler)
handler.path = "/api/config"
handler.command = "GET"
handler.address_string = lambda: "127.0.0.1"
with mock.patch("builtins.print") as print_mock:
APP.Handler.log_message(handler, '"GET /api/config HTTP/1.1" %s -', 200)
print_mock.assert_called_once()
def test_page_links_marks_active_page(self): def test_page_links_marks_active_page(self):
markup = APP.render_page_links("config") markup = APP.render_page_links("config")
self.assertIn('class="page-link active" href="/config"', markup) self.assertIn('class="page-link active" href="/config"', markup)