mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-05-25 16:00:35 +00:00
implement panic log for gateway and launcher
add file logger to gateway ref issue: #1734 Signed-off-by: Cytown <cytown@gmail.com>
This commit is contained in:
@@ -34,7 +34,7 @@ func NewGatewayCommand() *cobra.Command {
|
||||
return nil
|
||||
},
|
||||
RunE: func(_ *cobra.Command, _ []string) error {
|
||||
return gateway.Run(debug, internal.GetConfigPath(), allowEmpty)
|
||||
return gateway.Run(debug, internal.GetPicoclawHome(), internal.GetConfigPath(), allowEmpty)
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
+17
-1
@@ -47,6 +47,10 @@ const (
|
||||
serviceShutdownTimeout = 30 * time.Second
|
||||
providerReloadTimeout = 30 * time.Second
|
||||
gracefulShutdownTimeout = 15 * time.Second
|
||||
|
||||
logPath = "logs"
|
||||
panicFile = "gateway_panic.log"
|
||||
logFile = "gateway.log"
|
||||
)
|
||||
|
||||
type services struct {
|
||||
@@ -79,7 +83,19 @@ func (p *startupBlockedProvider) GetDefaultModel() string {
|
||||
}
|
||||
|
||||
// Run starts the gateway runtime using the configuration loaded from configPath.
|
||||
func Run(debug bool, configPath string, allowEmptyStartup bool) error {
|
||||
func Run(debug bool, homePath, configPath string, allowEmptyStartup bool) error {
|
||||
panicPath := filepath.Join(homePath, logPath, panicFile)
|
||||
panicFunc, err := logger.InitPanic(panicPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error initializing panic log: %w", err)
|
||||
}
|
||||
defer panicFunc()
|
||||
|
||||
if err = logger.EnableFileLogging(filepath.Join(homePath, logPath, logFile)); err != nil {
|
||||
panic(fmt.Sprintf("error enabling file logging: %v", err))
|
||||
}
|
||||
defer logger.DisableFileLogging()
|
||||
|
||||
cfg, err := config.LoadConfig(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading config: %w", err)
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
)
|
||||
|
||||
func InitPanic(filePath string) (func(), error) {
|
||||
if err := os.MkdirAll(filepath.Dir(filePath), 0o755); err != nil {
|
||||
return nil, fmt.Errorf("failed to create log directory: %w", err)
|
||||
}
|
||||
writer := initPanicFile(filePath)
|
||||
if writer == nil {
|
||||
return nil, fmt.Errorf("failed to create log file: %s", filePath)
|
||||
}
|
||||
return func() {
|
||||
defer writer.Close()
|
||||
if err := recover(); err != nil {
|
||||
now := time.Now().Format("2006-01-02 15:04:05")
|
||||
stack := debug.Stack()
|
||||
logMsg := "\n\n====================\n[" + now + "] PANIC OCCURRED: " + fmt.Sprintf(
|
||||
"%v",
|
||||
err,
|
||||
) + "\n" + string(
|
||||
stack,
|
||||
)
|
||||
|
||||
writer.Write([]byte(logMsg))
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
func initPanicFile(panicFile string) io.WriteCloser {
|
||||
file, err := os.OpenFile(panicFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND|os.O_SYNC, 0o600)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("error in open panic: %v", err))
|
||||
}
|
||||
if err = Dup2(int(file.Fd()), int(os.Stderr.Fd())); err != nil {
|
||||
panic(fmt.Sprintf("error in syscall.Dup2: %v", err))
|
||||
}
|
||||
return file
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func initPanicFile(panicFile string) io.WriteCloser {
|
||||
file, err := os.OpenFile(panicFile, os.O_WRONLY|os.O_CREATE|os.O_SYNC|os.O_APPEND, 0600)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("error in open panic: %v", err))
|
||||
}
|
||||
err = windows.SetStdHandle(windows.STD_ERROR_HANDLE, windows.Handle(file.Fd()))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to redirect stderr to file: %v", err))
|
||||
}
|
||||
os.Stderr = file
|
||||
return file
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
//go:build linux && amd64
|
||||
// +build linux,amd64
|
||||
|
||||
package logger
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func Dup2(oldfd int, newfd int) error {
|
||||
return syscall.Dup2(oldfd, newfd)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
//go:build linux && arm64
|
||||
// +build linux,arm64
|
||||
|
||||
package logger
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func Dup2(oldfd int, newfd int) error {
|
||||
return syscall.Dup3(oldfd, newfd, 0)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
//go:build darwin
|
||||
// +build darwin
|
||||
|
||||
package logger
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func Dup2(oldfd int, newfd int) error {
|
||||
return syscall.Dup2(oldfd, newfd)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
//go:build linux && loong64
|
||||
// +build linux,loong64
|
||||
|
||||
package logger
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func Dup2(oldfd int, newfd int) error {
|
||||
return syscall.Dup3(oldfd, newfd, 0)
|
||||
}
|
||||
+15
-5
@@ -33,6 +33,10 @@ import (
|
||||
|
||||
const (
|
||||
appName = "PicoClaw"
|
||||
|
||||
logPath = "logs"
|
||||
panicFile = "launcher_panic.log"
|
||||
logFile = "launcher.log"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -72,6 +76,14 @@ func main() {
|
||||
|
||||
// Initialize logger
|
||||
picoHome := utils.GetPicoclawHome()
|
||||
|
||||
f := filepath.Join(picoHome, logPath, panicFile)
|
||||
panicFunc, err := logger.InitPanic(f)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("error initializing panic log: %v", err))
|
||||
}
|
||||
defer panicFunc()
|
||||
|
||||
// By default, detect terminal to decide console log behavior
|
||||
// If -console-logs flag is explicitly set, it overrides the detection
|
||||
enableConsole := *console
|
||||
@@ -79,11 +91,9 @@ func main() {
|
||||
// Disable console logging by setting level to Fatal (no output)
|
||||
logger.SetConsoleLevel(logger.FATAL)
|
||||
|
||||
logPath := filepath.Join(picoHome, "logs", "web.log")
|
||||
if err := logger.EnableFileLogging(logPath); err != nil {
|
||||
// FIXME: https://github.com/sipeed/picoclaw/issues/1734
|
||||
fmt.Fprintf(os.Stderr, "Failed to initialize logger: %v\n", err)
|
||||
os.Exit(1)
|
||||
f := filepath.Join(picoHome, logPath, logFile)
|
||||
if err = logger.EnableFileLogging(f); err != nil {
|
||||
panic(fmt.Sprintf("error enabling file logging: %v", err))
|
||||
}
|
||||
defer logger.DisableFileLogging()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user