feat(logging): Add panic recovery and error logging for UI crashes
- Added Error() and Fatal() logging functions for non-debug errors - Added Panic() function to log panics with full stack traces - Added RecoverPanic() for defer statements to catch crashes - Added panic recovery to main() function - Added panic recovery to queue job processing goroutine - All panics now logged to videotools.log with timestamps and stack traces - Helps diagnose UI crashes that occur during FFmpeg processing
This commit is contained in:
parent
9c63ce03a3
commit
21119e1d5a
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime/debug"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -80,3 +81,50 @@ func FilePath() string {
|
||||||
func History() []string {
|
func History() []string {
|
||||||
return history
|
return history
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Error logs an error message with a category (always logged, even when debug is off)
|
||||||
|
func Error(cat Category, format string, args ...interface{}) {
|
||||||
|
msg := fmt.Sprintf("%s ERROR: %s", cat, fmt.Sprintf(format, args...))
|
||||||
|
timestamp := time.Now().Format(time.RFC3339Nano)
|
||||||
|
if file != nil {
|
||||||
|
fmt.Fprintf(file, "%s %s\n", timestamp, msg)
|
||||||
|
}
|
||||||
|
history = append(history, fmt.Sprintf("%s %s", timestamp, msg))
|
||||||
|
if len(history) > historyMax {
|
||||||
|
history = history[len(history)-historyMax:]
|
||||||
|
}
|
||||||
|
logger.Printf("%s %s", timestamp, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatal logs a fatal error and exits (always logged)
|
||||||
|
func Fatal(cat Category, format string, args ...interface{}) {
|
||||||
|
msg := fmt.Sprintf("%s FATAL: %s", cat, fmt.Sprintf(format, args...))
|
||||||
|
timestamp := time.Now().Format(time.RFC3339Nano)
|
||||||
|
if file != nil {
|
||||||
|
fmt.Fprintf(file, "%s %s\n", timestamp, msg)
|
||||||
|
file.Sync()
|
||||||
|
}
|
||||||
|
logger.Printf("%s %s", timestamp, msg)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Panic logs a panic with stack trace
|
||||||
|
func Panic(recovered interface{}) {
|
||||||
|
msg := fmt.Sprintf("%s PANIC: %v\nStack trace:\n%s", CatSystem, recovered, string(debug.Stack()))
|
||||||
|
timestamp := time.Now().Format(time.RFC3339Nano)
|
||||||
|
if file != nil {
|
||||||
|
fmt.Fprintf(file, "%s %s\n", timestamp, msg)
|
||||||
|
file.Sync()
|
||||||
|
}
|
||||||
|
history = append(history, fmt.Sprintf("%s %s", timestamp, msg))
|
||||||
|
logger.Printf("%s %s", timestamp, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecoverPanic should be used with defer to catch and log panics
|
||||||
|
func RecoverPanic() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
Panic(r)
|
||||||
|
// Re-panic to let the program crash with the logged info
|
||||||
|
panic(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.leaktechnologies.dev/stu/VideoTools/internal/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
// JobType represents the type of job to execute
|
// JobType represents the type of job to execute
|
||||||
|
|
@ -373,6 +375,7 @@ func (q *Queue) ResumeAll() {
|
||||||
|
|
||||||
// processJobs continuously processes pending jobs
|
// processJobs continuously processes pending jobs
|
||||||
func (q *Queue) processJobs() {
|
func (q *Queue) processJobs() {
|
||||||
|
defer logging.RecoverPanic() // Catch and log any panics in job processing
|
||||||
for {
|
for {
|
||||||
q.mu.Lock()
|
q.mu.Lock()
|
||||||
if !q.running {
|
if !q.running {
|
||||||
|
|
|
||||||
1
main.go
1
main.go
|
|
@ -5945,6 +5945,7 @@ func (s *appState) stopPlayer() {
|
||||||
func main() {
|
func main() {
|
||||||
logging.Init()
|
logging.Init()
|
||||||
defer logging.Close()
|
defer logging.Close()
|
||||||
|
defer logging.RecoverPanic() // Catch and log any panics with stack trace
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
logging.SetDebug(*debugFlag || os.Getenv("VIDEOTOOLS_DEBUG") != "")
|
logging.SetDebug(*debugFlag || os.Getenv("VIDEOTOOLS_DEBUG") != "")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user