additional logging and error handling

This commit is contained in:
2026-05-29 10:44:50 +02:00
parent 72a0e52e08
commit 9ddc1f5b99
3 changed files with 72 additions and 10 deletions

View File

@@ -8,6 +8,7 @@ import polars as pl
import sqlalchemy as sql
from wce_crm import db
from wce_crm.logging import logger_back as logger
class CompanyInfo(TypedDict):
@@ -83,6 +84,7 @@ def _transform_for_gui_output(
def comp_search_choices() -> tuple[tuple[str, int], ...]:
# TODO no reload functionality
logger.debug("[Call backend] comp_search_choices")
q = db.DF_CRM_MASTER.lazy()
counter = pl.int_range(0, pl.len()).over(pl.col.ma_unternehmensname)
q = q.with_columns(
@@ -98,6 +100,7 @@ def comp_search_choices() -> tuple[tuple[str, int], ...]:
def comp_search_get_info(
ma_id: int,
) -> CompanyInfo:
logger.debug("[Call backend] comp_search_get_info")
df = db.DF_CRM_MASTER.filter(pl.col.ma_id == ma_id)
if df.height > 1 or df.height == 0:
raise ValueError(f"Größe des zurückgelieferten Datenpakets ungültig: {df.height}")
@@ -111,6 +114,7 @@ def contact_person_search_choices(
use_both_names: bool,
) -> tuple[tuple[str, int], ...]:
# TODO no reload functionality
logger.debug("[Call backend] contact_person_search_choices")
q = db.DF_CONTACT_PERSON.lazy()
if ma_id is not None:
q = q.filter(pl.col.ma_id == ma_id)
@@ -136,6 +140,7 @@ def contact_person_search_choices(
def contact_person_search_get_info(
an_id: int,
) -> ContactPersonInfo:
logger.debug("[Call backend] contact_person_search_get_info")
df = db.DF_CONTACT_PERSON.filter(pl.col.an_id == an_id)
if df.height > 1 or df.height == 0:
raise ValueError(f"Größe des zurückgelieferten Datenpakets ungültig: {df.height}")
@@ -147,6 +152,7 @@ def contact_person_search_get_info(
def insert_initial_recording(
data: dict[str, Any],
) -> None:
logger.debug("[Call backend] insert_initial_recording")
stmt = db.grunderfassung_unternehmen.insert().values(data)
with db.ENGINE.begin() as conn:
conn.execute(stmt)
@@ -156,6 +162,7 @@ def update_initial_recording(
id_: int,
data: dict[str, Any],
) -> None:
logger.debug("[Call backend] update_initial_recording")
stmt = (
db.grunderfassung_unternehmen.update()
.where(db.grunderfassung_unternehmen.c.erfassung_id == id_)
@@ -168,6 +175,7 @@ def update_initial_recording(
def get_initial_recording(
id_: int,
) -> dict[str, Any]:
logger.debug("[Call backend] get_initial_recording")
stmt = db.grunderfassung_unternehmen.select().where(
db.grunderfassung_unternehmen.c.erfassung_id == id_
)
@@ -190,6 +198,7 @@ class FrontpageCompany:
def get_company_list() -> list[FrontpageCompany]:
logger.debug("[Call backend] get_company_list")
stmt = sql.select(
db.grunderfassung_unternehmen.c.erfassung_id,
db.grunderfassung_unternehmen.c.Partnersuche__un_suche,

View File

@@ -8,6 +8,7 @@ import json
import pickle
import re
import sys
import traceback
import uuid
from collections import defaultdict
from collections.abc import Container, Iterable, Sequence
@@ -33,7 +34,9 @@ from PySide6.QtCore import (
QObject,
Qt,
QTimer,
QtMsgType,
Signal,
qInstallMessageHandler,
)
from PySide6.QtGui import QAction
from PySide6.QtWidgets import (
@@ -1073,11 +1076,11 @@ def set_form_data(
value = data
else:
if key not in data:
logger_gui.debug("---- Key not in data: %s")
logger_gui.debug("-------- Data: %s", pformat(data))
logger_gui.error("Key not in data: %s", key)
logger_gui.error("Data:\n%s", pformat(data))
value = data[key]
logger_gui.debug("---- Key set: %s", key)
logger_gui.debug("Key set: %s", key)
set_widget_value(widget, value)
@@ -3634,9 +3637,51 @@ class MainWindow(QMainWindow):
help_menu.addAction(about_action)
# ** global exception handling
def global_exception_handler(exc_type, exc_value, exc_traceback):
"""catches all unhandled errors"""
# format error
error_msg = "".join(traceback.format_exception(exc_type, exc_value, exc_traceback))
logger_gui.critical(f"UNEXPECTED ERROR:\n{error_msg}")
# message to user
# check if QApplication exists otherwise crashing of crash handler possible)
if QApplication.instance():
msg_box = QMessageBox()
msg_box.setIcon(QMessageBox.Icon.Critical)
msg_box.setWindowTitle("Kritischer Fehler")
msg_box.setText(
"Ein unerwarteter Fehler ist aufgetreten. Die Details wurden protokolliert."
)
# details for user or screenshots
msg_box.setDetailedText(error_msg)
msg_box.exec()
sys.exit(1)
def qt_message_handler(mode, context, message):
"""forwards internal Qt C++ warnings to Python loggers"""
if mode == QtMsgType.QtInfoMsg:
logger_gui.info(message)
elif mode == QtMsgType.QtWarningMsg:
logger_gui.warning(message)
elif mode == QtMsgType.QtCriticalMsg:
logger_gui.error(message)
elif mode == QtMsgType.QtFatalMsg:
logger_gui.critical(message)
if __name__ == "__main__":
sys.excepthook = global_exception_handler
qInstallMessageHandler(qt_message_handler)
try:
app = QApplication(sys.argv)
app.setStyleSheet(QSS)
window = MainWindow()
window.show()
sys.exit(app.exec())
except Exception as err:
logger_gui.critical("Fehler beim Starten der Anwendung:\n%s", str(err), exc_info=True)

View File

@@ -1,6 +1,6 @@
import logging
from dopt_basics.logging import BASE_LOGGER, setup_logging
from dopt_basics.logging import BASE_LOGGER, LoggingConfig, setup_logging
from wce_crm.constants import Config
@@ -14,12 +14,16 @@ if Config.DEVELOPMENT_STATE:
if not Config.PATH_LOGGING.exists():
Config.PATH_LOGGING.mkdir()
setup_logging(
LOGGING_CFG: LoggingConfig = LoggingConfig(
enable_stderr=enable_stderr,
enable_file=enable_file,
logging_dir=Config.PATH_LOGGING,
log_filename=Config.LOG_FILENAME,
file_max_bytes=10_485_760,
file_backup_count=2,
)
setup_logging(LOGGING_CFG)
logger_base = BASE_LOGGER.getChild("wce_crm")
# ** GUI
@@ -31,3 +35,7 @@ logger_get_data = logger_gui.getChild("get_data")
logger_get_data.setLevel(logging.DEBUG)
logger_auto_form = logger_gui.getChild("get_data_auto_form")
logger_auto_form.setLevel(logging.DEBUG)
# ** Backend
logger_back = logger_base.getChild("backend")
logger_back.setLevel(logging.DEBUG)