Interactive TUI¶
The pylogshield.tui package provides the full-screen interactive log viewer and its supporting components.
Quick Start¶
from pathlib import Path
from pylogshield.tui.app import LogViewerApp
# Open the TUI programmatically
app = LogViewerApp(log_path=Path("~/.logs/myapp.log").expanduser())
app.run()
# Pre-apply an ERROR+ level filter
app = LogViewerApp(log_path=Path("app.log"), initial_level="ERROR")
app.run()
# Start in live-follow mode
app = LogViewerApp(log_path=Path("app.log"), start_following=True)
app.run()
LogViewerApp¶
LogViewerApp(log_path: Path, initial_level: Optional[str] = None, start_following: bool = False)
¶
Bases: App[None]
Interactive TUI log viewer.
FilterState¶
Dataclass holding the active filter configuration. Passed to LogViewerApp or returned from the filter panel modal.
FilterState(levels: Set[str] = (lambda: {'CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'})(), time_range: str = 'all', logger_name: str = '', search_text: str = '', search_regex: bool = False)
dataclass
¶
Example¶
from pylogshield.tui.app import FilterState
# Show only ERROR and CRITICAL from the last hour
state = FilterState(
levels={"ERROR", "CRITICAL"},
time_range="1h",
logger_name="",
search_text="payment",
search_regex=False,
)
LogReader¶
Reads, parses, and optionally tails a log file. Supports JSON-formatted logs (from JsonFormatter), the current PyLogShield standard plain-text format, and the legacy plain-text format.
LogReader(path: Path)
¶
Reads, parses, and optionally follows a log file.
| METHOD | DESCRIPTION |
|---|---|
tail |
|
follow |
Block until stop() is called, invoking callback for each new line. |
stop |
|
tail(limit: int = 5000) -> List[ParsedLine]
¶
follow(callback: Callable[[ParsedLine], None], interval: float = 0.25) -> None
¶
Block until stop() is called, invoking callback for each new line.
Creates a fresh stop event for each session so that a concurrent or prior stop() call cannot race with the new session starting.
stop() -> None
¶
Example — tail last N lines¶
from pathlib import Path
from pylogshield.tui.reader import LogReader
reader = LogReader(Path("~/.logs/myapp.log").expanduser())
lines = reader.tail(limit=100)
for line in lines:
print(f"[{line.level}] {line.message}")
Example — live follow in a background thread¶
import threading
from pylogshield.tui.reader import LogReader, ParsedLine
def on_new_line(line: ParsedLine) -> None:
print(f"{line.timestamp} {line.level} {line.message}")
reader = LogReader(Path("app.log"))
t = threading.Thread(target=reader.follow, args=(on_new_line,), daemon=True)
t.start()
# ... later, stop the thread:
reader.stop()
t.join(timeout=1.0)
ParsedLine¶
Dataclass representing a single parsed log line, returned by LogReader.tail() and passed to LogReader.follow() callbacks.
ParsedLine(timestamp: str, level: str, logger: str, module: str, lineno: int, message: str, raw: str, extra: Dict[str, object] = dict())
dataclass
¶
Fields¶
| Field | Type | Description |
|---|---|---|
timestamp |
str |
ISO 8601 or plain-text timestamp string |
level |
str |
Level name: DEBUG, INFO, WARNING, ERROR, CRITICAL, or N/A |
logger |
str |
Logger name passed to get_logger() |
module |
str |
Module name where the log call originated (module:lineno source) |
lineno |
int |
Line number in module where the log call originated |
message |
str |
The formatted log message |
raw |
str |
The original unparsed line from the file |
extra |
dict |
Any extra key/value fields from JSON-formatted logs |
Exporter¶
Writes a list of ParsedLine rows to one of four formats. Exports only the rows passed in — combine with LogReader.tail() or filtering to export a subset.
Exporter(rows: List[ParsedLine], filepath: Path)
¶
Example — export filtered rows to CSV¶
from pathlib import Path
from pylogshield.tui.reader import LogReader
from pylogshield.tui.exporter import Exporter
reader = LogReader(Path("app.log"))
all_rows = reader.tail(limit=5000)
# Keep only ERROR and CRITICAL
errors = [r for r in all_rows if r.level in {"ERROR", "CRITICAL"}]
Exporter(errors, Path("errors-export.csv")).to_csv()
Exporter(errors, Path("errors-export.html")).to_html()
Example — export to all four formats¶
from pathlib import Path
from pylogshield.tui.reader import LogReader
from pylogshield.tui.exporter import Exporter
from datetime import date
reader = LogReader(Path("app.log"))
rows = reader.tail(limit=1000)
stem = f"myapp-export-{date.today().isoformat()}"
exp = Exporter(rows, Path(f"{stem}.csv"))
exp.to_csv() # → myapp-export-2026-05-09.csv
Exporter(rows, Path(f"{stem}.json")).to_json() # → myapp-export-2026-05-09.json
Exporter(rows, Path(f"{stem}.txt")).to_text() # → myapp-export-2026-05-09.txt
Exporter(rows, Path(f"{stem}.html")).to_html() # → myapp-export-2026-05-09.html