fixing up loggin
This commit is contained in:
parent
0f2521f8d6
commit
d86999732c
3 changed files with 49 additions and 13 deletions
|
|
@ -6,7 +6,7 @@ from PyQt5.QtWidgets import (
|
|||
QWidget, QVBoxLayout, QTextEdit, QLabel, QSizePolicy
|
||||
)
|
||||
from PyQt5.QtCore import Qt, pyqtSignal, QTimer
|
||||
from PyQt5.QtGui import QTextCursor, QFont
|
||||
from PyQt5.QtGui import QTextCursor, QFont, QTextCharFormat
|
||||
from pathlib import Path
|
||||
import datetime
|
||||
import html
|
||||
|
|
@ -120,6 +120,9 @@ class LogViewer(QWidget):
|
|||
def clear_log(self):
|
||||
"""Clear the log display and reset tracking."""
|
||||
self.log_display.clear()
|
||||
# Reset the char format so the red color from previous [MISMATCH]
|
||||
# HTML spans doesn't bleed into new plain-text appends.
|
||||
self.log_display.setCurrentCharFormat(QTextCharFormat())
|
||||
self.status_label.setText("Log cleared")
|
||||
# Reset tail file pointer and buffer if active
|
||||
self._tail_buffer = ""
|
||||
|
|
@ -171,11 +174,26 @@ class LogViewer(QWidget):
|
|||
self._tail_timer.start(self._tail_interval)
|
||||
|
||||
def stop_tail(self):
|
||||
"""Stop tailing the log file and close internal file handle."""
|
||||
"""Stop tailing the log file and close internal file handle.
|
||||
|
||||
Performs a final drain so no data written before this call is lost.
|
||||
"""
|
||||
try:
|
||||
self._tail_timer.stop()
|
||||
except Exception:
|
||||
pass
|
||||
# Final drain: read any remaining data before closing the handle
|
||||
try:
|
||||
self._poll_tail()
|
||||
except Exception:
|
||||
pass
|
||||
# Flush any leftover partial line sitting in the buffer
|
||||
if self._tail_buffer and self._tail_buffer.strip():
|
||||
try:
|
||||
self.append_log_message(self._tail_buffer)
|
||||
except Exception:
|
||||
pass
|
||||
self._tail_buffer = ""
|
||||
if self._tail_f:
|
||||
try:
|
||||
self._tail_f.close()
|
||||
|
|
@ -235,12 +253,13 @@ class LogViewer(QWidget):
|
|||
if "[MISMATCH]" in message:
|
||||
escaped = html.escape(message)
|
||||
self.log_display.append(f'<span style="color: #ff4444;">{escaped}</span>')
|
||||
# Emit signal on the header line ("Failed after retries") so the
|
||||
# counter increments once per mismatch event, not per line.
|
||||
if "Failed after retries" in message:
|
||||
self.mismatch_detected.emit()
|
||||
# Counting is handled via stdout MISMATCH_EVENT markers in
|
||||
# TranslationTab.append_log — the log viewer only handles display.
|
||||
else:
|
||||
self.log_display.append(message)
|
||||
# Explicitly wrap in a white span so Qt doesn't inherit red from
|
||||
# a preceding [MISMATCH] HTML append.
|
||||
escaped = html.escape(message)
|
||||
self.log_display.append(f'<span style="color: #ffffff;">{escaped}</span>')
|
||||
|
||||
# Scroll to bottom
|
||||
cursor = self.log_display.textCursor()
|
||||
|
|
|
|||
|
|
@ -814,8 +814,8 @@ class TranslationTab(QWidget):
|
|||
self.reset_view_button.setStyleSheet(icon_btn_style)
|
||||
self.open_translations_button.setStyleSheet(icon_btn_style)
|
||||
# Ensure emoji/icons are readable
|
||||
self.reset_view_button.setFont(QFont('', 12))
|
||||
self.open_translations_button.setFont(QFont('', 12))
|
||||
self.reset_view_button.setFont(QFont('Segoe UI', 12))
|
||||
self.open_translations_button.setFont(QFont('Segoe UI', 12))
|
||||
|
||||
# Create the stop button here so it sits in the same row as the
|
||||
# back/open buttons. Use a compact icon style to match them but
|
||||
|
|
@ -849,7 +849,7 @@ class TranslationTab(QWidget):
|
|||
self.stop_button.clicked.connect(self.stop_translation)
|
||||
self.stop_button.setStyleSheet(stop_button_style)
|
||||
# Slightly larger font for the emoji to make it visually clear
|
||||
self.stop_button.setFont(QFont('', 14))
|
||||
self.stop_button.setFont(QFont('Segoe UI', 14))
|
||||
self.stop_button.setVisible(False)
|
||||
|
||||
# Place both buttons on the left and totals on the right
|
||||
|
|
@ -1017,6 +1017,9 @@ class TranslationTab(QWidget):
|
|||
|
||||
# Right side - translation history log viewer
|
||||
self.translation_log_viewer = LogViewer()
|
||||
# Mismatch counting is driven by MISMATCH_EVENT stdout markers
|
||||
# detected in append_log. The log_viewer signal is kept as a
|
||||
# fallback for in-process mode (e.g. speaker-parse).
|
||||
self.translation_log_viewer.mismatch_detected.connect(self.on_mismatch_detected)
|
||||
|
||||
# Allow both left and right widgets to expand vertically so the
|
||||
|
|
@ -1743,6 +1746,11 @@ class TranslationTab(QWidget):
|
|||
self.translation_worker.start()
|
||||
|
||||
def append_log(self, message):
|
||||
# Detect mismatch markers emitted to stdout by translation.py.
|
||||
# This is the primary, non-racy detection path for subprocess mode.
|
||||
if isinstance(message, str) and message.startswith("MISMATCH_EVENT:"):
|
||||
self.on_mismatch_detected()
|
||||
return # marker is internal, not displayed
|
||||
try:
|
||||
pattern = r'^\W*(?P<filename>[^:]+):.*?\[Input:\s*(?P<input>\d+)\].*?\[Output:\s*(?P<output>\d+)\].*?\[Cost:\s*\$(?P<cost>[\d\.]+)\].*?\[(?P<time>[\d\.]+)s\]'
|
||||
m = re.search(pattern, message)
|
||||
|
|
@ -1941,10 +1949,11 @@ class TranslationTab(QWidget):
|
|||
except Exception:
|
||||
pass
|
||||
|
||||
# Stop tailing the log when finished
|
||||
# Stop tailing the log after a short delay so the final poll
|
||||
# can pick up any data written just before the worker finished.
|
||||
try:
|
||||
if hasattr(self, 'translation_log_viewer') and self.translation_log_viewer:
|
||||
self.translation_log_viewer.stop_tail()
|
||||
QTimer.singleShot(600, self.translation_log_viewer.stop_tail)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -1263,7 +1263,15 @@ def translateAI(text, history, fullPromptFlag, config, filename=None, pbar=None,
|
|||
|
||||
else: # Failure case after all retries
|
||||
if pbar: pbar.write(f"Translation failed after {max_retries + 1} attempts. Check mismatch log.")
|
||||
|
||||
|
||||
# Emit a machine-readable marker on stdout so the GUI worker
|
||||
# thread can detect the mismatch reliably (stdout is captured
|
||||
# synchronously, unlike file-tail polling which can be racy).
|
||||
try:
|
||||
print(f"MISMATCH_EVENT:{filename}", flush=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
formatted_mismatch_output = last_raw_translation
|
||||
try:
|
||||
parsed_json = json.loads(last_raw_translation)
|
||||
|
|
|
|||
Loading…
Reference in a new issue