// logger/boot_logger.go package logger import ( "fmt" "io" "log" "os" "path/filepath" "time" ) type BootLoggerFactory struct { } var ( bootLogFile *os.File bootLogger *log.Logger ) // InitBootLogger 初始化启动日志(只在启动阶段使用) func InitBootLog() *BootLoggerFactory { if logToFile := os.Getenv("LOG_TO_FILE"); logToFile == "false" { return &BootLoggerFactory{} } // 1. 确保日志目录存在 logDir := "logs" if err := os.MkdirAll(logDir, 0755); err != nil { log.Fatalf("创建日志目录失败: %v", err) } // 2. 创建启动日志文件 timestamp := time.Now().Format("20060102-150405") filename := fmt.Sprintf("boot-%s-%s.log", serviceName, timestamp) filePath := filepath.Join(logDir, filename) file, err := os.Create(filePath) if err != nil { log.Fatalf("创建启动日志文件失败: %v", err) } bootLogFile = file // 3. 创建专门的bootLogger,同时输出到文件和控制台 multiWriter := io.MultiWriter(os.Stdout, bootLogFile) bootLogger = log.New(multiWriter, "", log.LstdFlags|log.Lshortfile) // 4. 重定向标准库log到bootLogger(重要!) log.SetOutput(multiWriter) log.SetFlags(log.LstdFlags | log.Lshortfile) // 5. 记录启动信息 BootLog("=== 服务启动开始 ===") BootLog("服务名称: %s", serviceName) BootLog("启动时间: %s", time.Now().Format("2006-01-02 15:04:05")) BootLog("启动日志文件: %s", filePath) return &BootLoggerFactory{} } // BootLog 启动阶段专用日志函数 func BootLog(format string, v ...interface{}) { if bootLogger != nil { // 使用bootLogger记录 bootLogger.Printf(format, v...) } else { // 后备:直接使用标准库log log.Printf(format, v...) } } func (f *BootLoggerFactory) GetName() string { return "BootLoggerFactory" } // CloseBootLogger 关闭启动日志,切换到运行日志 func (f *BootLoggerFactory) Close() { if bootLogger != nil { BootLog("=== 启动阶段结束,切换到运行时日志 ===") } if bootLogFile != nil { bootLogFile.Close() bootLogFile = nil } bootLogger = nil }