mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-09 07:48:57 +00:00
Merge pull request #850 from PR0M3TH3AN/codex/redirect-log-output-for-background-tasks
Refactor logging output handling
This commit is contained in:
46
src/main.py
46
src/main.py
@@ -9,6 +9,7 @@ if vendor_dir.exists():
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
|
from logging.handlers import QueueHandler, QueueListener
|
||||||
import signal
|
import signal
|
||||||
import time
|
import time
|
||||||
import argparse
|
import argparse
|
||||||
@@ -38,6 +39,7 @@ from utils import (
|
|||||||
)
|
)
|
||||||
from utils.clipboard import ClipboardUnavailableError
|
from utils.clipboard import ClipboardUnavailableError
|
||||||
from utils.atomic_write import atomic_write
|
from utils.atomic_write import atomic_write
|
||||||
|
from utils.logging_utils import ConsolePauseFilter
|
||||||
import queue
|
import queue
|
||||||
from local_bip85.bip85 import Bip85Error
|
from local_bip85.bip85 import Bip85Error
|
||||||
|
|
||||||
@@ -77,39 +79,43 @@ def load_global_config() -> dict:
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def configure_logging():
|
_queue_listener: QueueListener | None = None
|
||||||
logger = logging.getLogger()
|
|
||||||
logger.setLevel(logging.DEBUG) # Keep this as DEBUG to capture all logs
|
|
||||||
|
def configure_logging():
|
||||||
|
"""Configure application-wide logging with queue-based handlers."""
|
||||||
|
global _queue_listener
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
# Remove all handlers associated with the root logger object
|
|
||||||
for handler in logger.handlers[:]:
|
for handler in logger.handlers[:]:
|
||||||
logger.removeHandler(handler)
|
logger.removeHandler(handler)
|
||||||
|
|
||||||
# Ensure the 'logs' directory exists
|
|
||||||
log_directory = Path("logs")
|
log_directory = Path("logs")
|
||||||
if not log_directory.exists():
|
|
||||||
log_directory.mkdir(parents=True, exist_ok=True)
|
log_directory.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# Create handlers
|
log_queue: queue.Queue[logging.LogRecord] = queue.Queue()
|
||||||
c_handler = logging.StreamHandler(sys.stdout)
|
queue_handler = QueueHandler(log_queue)
|
||||||
f_handler = logging.FileHandler(log_directory / "main.log")
|
|
||||||
|
|
||||||
# Set levels: only errors and critical messages will be shown in the console
|
console_handler = logging.StreamHandler(sys.stderr)
|
||||||
c_handler.setLevel(logging.ERROR)
|
console_handler.setLevel(logging.ERROR)
|
||||||
f_handler.setLevel(logging.DEBUG)
|
console_handler.addFilter(ConsolePauseFilter())
|
||||||
|
|
||||||
|
file_handler = logging.FileHandler(log_directory / "main.log")
|
||||||
|
file_handler.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
# Create formatters and add them to handlers
|
|
||||||
formatter = logging.Formatter(
|
formatter = logging.Formatter(
|
||||||
"%(asctime)s [%(levelname)s] %(message)s [%(filename)s:%(lineno)d]"
|
"%(asctime)s [%(levelname)s] %(message)s [%(filename)s:%(lineno)d]",
|
||||||
)
|
)
|
||||||
c_handler.setFormatter(formatter)
|
console_handler.setFormatter(formatter)
|
||||||
f_handler.setFormatter(formatter)
|
file_handler.setFormatter(formatter)
|
||||||
|
|
||||||
# Add handlers to the logger
|
_queue_listener = QueueListener(log_queue, console_handler, file_handler)
|
||||||
logger.addHandler(c_handler)
|
_queue_listener.start()
|
||||||
logger.addHandler(f_handler)
|
|
||||||
|
logger.addHandler(queue_handler)
|
||||||
|
|
||||||
# Set logging level for third-party libraries to WARNING to suppress their debug logs
|
|
||||||
logging.getLogger("monstr").setLevel(logging.WARNING)
|
logging.getLogger("monstr").setLevel(logging.WARNING)
|
||||||
logging.getLogger("nostr").setLevel(logging.WARNING)
|
logging.getLogger("nostr").setLevel(logging.WARNING)
|
||||||
|
|
||||||
|
24
src/utils/logging_utils.py
Normal file
24
src/utils/logging_utils.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
|
_console_paused = False
|
||||||
|
|
||||||
|
|
||||||
|
class ConsolePauseFilter(logging.Filter):
|
||||||
|
"""Filter that blocks records when console logging is paused."""
|
||||||
|
|
||||||
|
def filter(
|
||||||
|
self, record: logging.LogRecord
|
||||||
|
) -> bool: # pragma: no cover - small utility
|
||||||
|
return not _console_paused
|
||||||
|
|
||||||
|
|
||||||
|
def pause_console_logging() -> None:
|
||||||
|
"""Temporarily pause logging to console handlers."""
|
||||||
|
global _console_paused
|
||||||
|
_console_paused = True
|
||||||
|
|
||||||
|
|
||||||
|
def resume_console_logging() -> None:
|
||||||
|
"""Resume logging to console handlers."""
|
||||||
|
global _console_paused
|
||||||
|
_console_paused = False
|
@@ -15,6 +15,7 @@ except ImportError: # pragma: no cover - POSIX only
|
|||||||
tty = None # type: ignore
|
tty = None # type: ignore
|
||||||
|
|
||||||
from utils.terminal_utils import clear_screen
|
from utils.terminal_utils import clear_screen
|
||||||
|
from utils.logging_utils import pause_console_logging, resume_console_logging
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_MAX_ATTEMPTS = 5
|
DEFAULT_MAX_ATTEMPTS = 5
|
||||||
@@ -107,12 +108,15 @@ def _masked_input_posix(prompt: str) -> str:
|
|||||||
def masked_input(prompt: str) -> str:
|
def masked_input(prompt: str) -> str:
|
||||||
"""Return input from the user while masking typed characters."""
|
"""Return input from the user while masking typed characters."""
|
||||||
func = _masked_input_windows if sys.platform == "win32" else _masked_input_posix
|
func = _masked_input_windows if sys.platform == "win32" else _masked_input_posix
|
||||||
|
pause_console_logging()
|
||||||
try:
|
try:
|
||||||
return func(prompt)
|
return func(prompt)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
raise
|
raise
|
||||||
except Exception: # pragma: no cover - fallback when TTY operations fail
|
except Exception: # pragma: no cover - fallback when TTY operations fail
|
||||||
return input(prompt)
|
return input(prompt)
|
||||||
|
finally:
|
||||||
|
resume_console_logging()
|
||||||
|
|
||||||
|
|
||||||
def prompt_seed_words(count: int = 12, *, max_attempts: int | None = None) -> str:
|
def prompt_seed_words(count: int = 12, *, max_attempts: int | None = None) -> str:
|
||||||
|
Reference in New Issue
Block a user