From 2d1d4ad406228ef62ab078724cb7d1556e003d01 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Mon, 13 Jul 2026 16:03:19 +0800
Subject: [PATCH] chore: point independent project metadata to unified root

---
 C1.source/privatevoice.src/internal/logger/logger.go |   43 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/C1.source/privatevoice.src/internal/logger/logger.go b/C1.source/privatevoice.src/internal/logger/logger.go
index 6997408..2041c29 100755
--- a/C1.source/privatevoice.src/internal/logger/logger.go
+++ b/C1.source/privatevoice.src/internal/logger/logger.go
@@ -14,23 +14,66 @@
 	logFile *os.File
 )
 
+const (
+	maxLogBytes   = 10 * 1024 * 1024
+	maxLogBackups = 3
+)
+
 // Init initializes the file logger in the persistent app data directory.
 func Init() {
+	mu.Lock()
+	if logFile != nil {
+		logFile.Close()
+		logFile = nil
+	}
+	mu.Unlock()
+
 	dir := paths.AppSupportDir()
 	if err := os.MkdirAll(dir, 0755); err != nil {
 		fmt.Fprintf(os.Stderr, "failed to create log dir: %v\n", err)
 		return
 	}
 	path := filepath.Join(dir, "app.log")
+	if err := rotateIfNeeded(path); err != nil {
+		fmt.Fprintf(os.Stderr, "failed to rotate log file: %v\n", err)
+	}
 
 	f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "failed to open log file: %v\n", err)
 		return
 	}
+	mu.Lock()
+	defer mu.Unlock()
 	logFile = f
 }
 
+func rotateIfNeeded(path string) error {
+	info, err := os.Stat(path)
+	if err != nil {
+		if os.IsNotExist(err) {
+			return nil
+		}
+		return err
+	}
+	if info.Size() < maxLogBytes {
+		return nil
+	}
+
+	oldest := fmt.Sprintf("%s.%d", path, maxLogBackups)
+	if err := os.Remove(oldest); err != nil && !os.IsNotExist(err) {
+		return err
+	}
+	for i := maxLogBackups - 1; i >= 1; i-- {
+		from := fmt.Sprintf("%s.%d", path, i)
+		to := fmt.Sprintf("%s.%d", path, i+1)
+		if err := os.Rename(from, to); err != nil && !os.IsNotExist(err) {
+			return err
+		}
+	}
+	return os.Rename(path, path+".1")
+}
+
 func write(level, format string, args ...interface{}) {
 	msg := fmt.Sprintf(format, args...)
 	ts := time.Now().Format("2006-01-02 15:04:05")

--
Gitblit v1.9.3