Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions proxy/tg_ws_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,8 +568,9 @@ def main():
help='Log to file with rotation (default: stderr only)')
ap.add_argument('--log-max-mb', type=float, default=5, metavar='MB',
help='Max log file size in MB before rotation (default 5)')
ap.add_argument('--log-backups', type=int, default=0, metavar='N',
help='Number of rotated log files to keep (default 0)')
ap.add_argument('--log-backups', type=int, default=1, metavar='N',
help='Number of rotated log files to keep (min 1; '
'rotation needs at least one backup to bound size)')
ap.add_argument('--buf-kb', type=int, default=256, metavar='KB',
help='Socket send/recv buffer size in KB (default 256)')
ap.add_argument('--pool-size', type=int, default=4, metavar='N',
Expand Down Expand Up @@ -640,11 +641,11 @@ def main():
root.addHandler(console)

if args.log_file:
fh = logging.handlers.RotatingFileHandler(
from utils.logging_setup import build_log_handler
fh = build_log_handler(
args.log_file,
maxBytes=max(32 * 1024, int(args.log_max_mb * 1024 * 1024)),
backupCount=max(0, args.log_backups),
encoding='utf-8',
log_max_mb=args.log_max_mb,
backups=args.log_backups,
)
fh.setFormatter(log_fmt)
root.addHandler(fh)
Expand Down
39 changes: 39 additions & 0 deletions utils/logging_setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Shared construction of the rotating log file handler.

Centralizes the rotation invariant so both the tray and the CLI log paths
behave identically and the file can never grow without bound (issue #885).

A ``RotatingFileHandler`` only rotates when ``backupCount >= 1``: CPython's
``doRollover`` skips the entire rotation block when ``backupCount == 0``, so
``maxBytes`` is silently ignored and the active file grows forever. We force
at least one backup here regardless of caller input.
"""

from __future__ import annotations

import logging.handlers


_MIN_BYTES = 32 * 1024
_MIN_BACKUPS = 1


def build_log_handler(
path: str,
log_max_mb: float = 5,
backups: int = 1,
) -> logging.handlers.RotatingFileHandler:
"""Create a RotatingFileHandler that actually rotates.

``backups`` is clamped to at least 1 so rotation is always active, and
``maxBytes`` keeps a small floor so a misconfigured tiny size can't cause
rotation on every line.
"""
max_bytes = max(_MIN_BYTES, int(log_max_mb * 1024 * 1024))
backup_count = max(_MIN_BACKUPS, int(backups))
return logging.handlers.RotatingFileHandler(
path,
maxBytes=max_bytes,
backupCount=backup_count,
encoding="utf-8",
)
8 changes: 2 additions & 6 deletions utils/tray_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from proxy import __version__, get_link_host, parse_dc_ip_list, proxy_config, coerce_domain_list
from proxy.tg_ws_proxy import _run
from utils.default_config import default_tray_config
from utils.logging_setup import build_log_handler

log = logging.getLogger("tg-ws-tray")

Expand Down Expand Up @@ -155,12 +156,7 @@ def setup_logging(verbose: bool = False, log_max_mb: float = 5) -> None:
root.setLevel(level)
logging.getLogger('asyncio').setLevel(logging.WARNING)

fh = logging.handlers.RotatingFileHandler(
str(LOG_FILE),
maxBytes=max(32 * 1024, int(log_max_mb * 1024 * 1024)),
backupCount=0,
encoding="utf-8",
)
fh = build_log_handler(str(LOG_FILE), log_max_mb=log_max_mb, backups=1)
fh.setLevel(logging.DEBUG)
fh.setFormatter(logging.Formatter(_LOG_FMT_FILE, datefmt="%Y-%m-%d %H:%M:%S"))
root.addHandler(fh)
Expand Down