language -> en, force displaying specific log lvl

This commit is contained in:
Dirk Alders 2025-07-19 14:19:54 +02:00
parent 50c2a2d33d
commit 044870b6e8
2 changed files with 71 additions and 10 deletions

View File

@ -3,12 +3,11 @@ import pickle
import socket import socket
import struct import struct
import threading import threading
from datetime import datetime # <--- HINZUGEFÜGT from datetime import datetime
from logging.handlers import SocketHandler
from textual.app import App, ComposeResult from textual.app import App, ComposeResult
from textual.containers import Vertical from textual.containers import Vertical
from textual.widgets import Footer, Header, Input, RichLog from textual.widgets import Footer, Header, Input, RichLog, Checkbox
# Mapping von Log-Level-Namen zu Farben für die Anzeige # Mapping von Log-Level-Namen zu Farben für die Anzeige
LEVEL_STYLES = { LEVEL_STYLES = {
@ -60,13 +59,19 @@ class LogViewerApp(App):
"""Eine Textual-App zum Anzeigen und Filtern von Python-Logs.""" """Eine Textual-App zum Anzeigen und Filtern von Python-Logs."""
CSS_PATH = "style.tcss" CSS_PATH = "style.tcss"
BINDINGS = [("q", "quit", "Beenden")] BINDINGS = [("q", "quit", "Quit")]
def __init__(self): def __init__(self):
super().__init__() super().__init__()
#
self.all_logs = [] self.all_logs = []
self.module_filter = "" self.module_filter = ""
self.level_filter = "" self.level_filter = ""
self.force_critical = True
self.force_error = True
self.force_warning = False
self.force_info = False
self.force_debug = False
self.log_display = RichLog(highlight=True, markup=True) self.log_display = RichLog(highlight=True, markup=True)
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
@ -75,8 +80,14 @@ class LogViewerApp(App):
with Vertical(id="app-grid"): with Vertical(id="app-grid"):
yield self.log_display yield self.log_display
with Vertical(id="bottom-bar"): with Vertical(id="bottom-bar"):
yield Input(placeholder="Modul filtern...", id="module_filter") yield Input(placeholder="module filter...", id="module_filter")
yield Input(placeholder="Level filtern...", id="level_filter") yield Input(placeholder="level filter...", id="level_filter")
with Vertical(id="force-bar"):
yield Checkbox("Force CRITICAL", self.force_critical, id="force_critical")
yield Checkbox("Force ERROR", self.force_error, id="force_error")
yield Checkbox("Force WARNING", self.force_warning, id="force_warning")
yield Checkbox("Force INFO", self.force_info, id="force_info")
yield Checkbox("Force DEBUG", self.force_debug, id="force_debug")
yield Footer() yield Footer()
def on_mount(self) -> None: def on_mount(self) -> None:
@ -89,6 +100,15 @@ class LogViewerApp(App):
self.all_logs.append(record) self.all_logs.append(record)
self._apply_filters_to_log(record) self._apply_filters_to_log(record)
def _force(self, lvl: str) -> bool:
rv = False
rv |= lvl == 'critical' and self.force_critical
rv |= lvl == 'error' and self.force_error
rv |= lvl == 'warning' and self.force_warning
rv |= lvl == 'info' and self.force_info
rv |= lvl == 'debug' and self.force_debug
return rv
def _apply_filters_to_log(self, record: logging.LogRecord): def _apply_filters_to_log(self, record: logging.LogRecord):
"""Prüft einen einzelnen Log-Eintrag gegen die Filter und zeigt ihn ggf. an.""" """Prüft einen einzelnen Log-Eintrag gegen die Filter und zeigt ihn ggf. an."""
module_match = False module_match = False
@ -99,7 +119,7 @@ class LogViewerApp(App):
for level_filter in self.level_filter.split(","): for level_filter in self.level_filter.split(","):
level_match |= level_filter.lower() in record.levelname.lower() level_match |= level_filter.lower() in record.levelname.lower()
if module_match and level_match: if self._force(record.levelname.lower()) or (module_match and level_match):
level_style = LEVEL_STYLES.get(record.levelname, "white") level_style = LEVEL_STYLES.get(record.levelname, "white")
timestamp_str = datetime.fromtimestamp(record.created).strftime("%Y-%m-%d %H:%M:%S") timestamp_str = datetime.fromtimestamp(record.created).strftime("%Y-%m-%d %H:%M:%S")
@ -129,6 +149,20 @@ class LogViewerApp(App):
self._update_display() self._update_display()
def on_checkbox_changed(self, message: Checkbox.Changed) -> None:
if message.checkbox.id == "force_critical":
self.force_critical = message.value
elif message.checkbox.id == "force_error":
self.force_error = message.value
elif message.checkbox.id == "force_warning":
self.force_warning = message.value
elif message.checkbox.id == "force_info":
self.force_info = message.value
elif message.checkbox.id == "force_debug":
self.force_debug = message.value
self._update_display()
if __name__ == "__main__": if __name__ == "__main__":
app = LogViewerApp() app = LogViewerApp()

View File

@ -2,13 +2,20 @@
layout: vertical; layout: vertical;
overflow-y: scroll; overflow-y: scroll;
scrollbar-gutter: stable; scrollbar-gutter: stable;
height: 90%; height: 80%;
} }
#bottom-bar { #bottom-bar {
layout: grid; layout: grid;
grid-size: 2; grid-size: 2;
height: 10%; height: 11%;
border-top: solid $primary;
}
#force-bar {
layout: grid;
grid-size: 5;
height: 9%;
border-top: solid $primary; border-top: solid $primary;
} }
@ -19,3 +26,23 @@
#level_filter { #level_filter {
width: 100%; width: 100%;
} }
#force_critical {
width: 100%;
}
#force_error {
width: 100%;
}
#force_warning {
width: 100%;
}
#force_info {
width: 100%;
}
#force_debug {
width: 100%;
}