language -> en, force displaying specific log lvl
This commit is contained in:
parent
50c2a2d33d
commit
044870b6e8
48
loggy.py
48
loggy.py
@ -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()
|
||||||
|
31
style.tcss
31
style.tcss
@ -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%;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user