package services import ( "fmt" "log" "os" "path/filepath" "runtime" "strings" "time" ) var ( logDir string isDevMode bool logLevel string = "INFO" // DEBUG, INFO, WARN, ERROR ) func init() { // 检测是否为开发模式 // 通过环境变量 DEV 或可执行文件名判断 isDevMode = os.Getenv("DEV") == "true" || strings.Contains(os.Args[0], "dev") || strings.Contains(os.Args[0], ".dev") // 开发模式下默认使用 DEBUG 级别 if isDevMode { logLevel = "DEBUG" log.SetFlags(log.LstdFlags | log.Lmicroseconds | log.Lshortfile) } else { log.SetFlags(log.LstdFlags) } // 设置日志目录 exePath, err := os.Executable() if err != nil { logDir = "./Log" } else { logDir = filepath.Join(filepath.Dir(exePath), "Log") } os.MkdirAll(logDir, 0755) } // SetLogLevel 设置日志级别 func SetLogLevel(level string) { logLevel = strings.ToUpper(level) } // IsDevMode 返回是否为开发模式 func IsDevMode() bool { return isDevMode } // shouldLog 判断是否应该记录该级别的日志 func shouldLog(level string) bool { levels := map[string]int{ "DEBUG": 0, "INFO": 1, "WARN": 2, "ERROR": 3, } currentLevel, ok := levels[logLevel] if !ok { currentLevel = 1 } msgLevel, ok := levels[strings.ToUpper(level)] if !ok { msgLevel = 1 } return msgLevel >= currentLevel } // getCallerInfo 获取调用者信息(仅在开发模式下) func getCallerInfo() string { if !isDevMode { return "" } pc, file, line, ok := runtime.Caller(3) if ok { funcName := runtime.FuncForPC(pc).Name() // 只取函数名,去掉包路径 parts := strings.Split(funcName, ".") funcName = parts[len(parts)-1] // 只取文件名 fileParts := strings.Split(file, "/") fileName := fileParts[len(fileParts)-1] return fmt.Sprintf("[%s:%d %s]", fileName, line, funcName) } return "" } // LogInfo 记录信息日志 func LogInfo(message string) { if !shouldLog("INFO") { return } callerInfo := getCallerInfo() logMessage("INFO", callerInfo+" "+message) } // LogError 记录错误日志 func LogError(message string) { if !shouldLog("ERROR") { return } callerInfo := getCallerInfo() logMessage("ERROR", callerInfo+" "+message) } // LogWarn 记录警告日志 func LogWarn(message string) { if !shouldLog("WARN") { return } callerInfo := getCallerInfo() logMessage("WARN", callerInfo+" "+message) } // LogDebug 记录调试日志 func LogDebug(message string) { if !shouldLog("DEBUG") { return } callerInfo := getCallerInfo() logMessage("DEBUG", callerInfo+" "+message) } // LogDebugf 格式化调试日志 func LogDebugf(format string, args ...interface{}) { if !shouldLog("DEBUG") { return } callerInfo := getCallerInfo() message := fmt.Sprintf(format, args...) logMessage("DEBUG", callerInfo+" "+message) } // LogInfof 格式化信息日志 func LogInfof(format string, args ...interface{}) { if !shouldLog("INFO") { return } callerInfo := getCallerInfo() message := fmt.Sprintf(format, args...) logMessage("INFO", callerInfo+" "+message) } // LogErrorf 格式化错误日志 func LogErrorf(format string, args ...interface{}) { if !shouldLog("ERROR") { return } callerInfo := getCallerInfo() message := fmt.Sprintf(format, args...) logMessage("ERROR", callerInfo+" "+message) } // LogWarnf 格式化警告日志 func LogWarnf(format string, args ...interface{}) { if !shouldLog("WARN") { return } callerInfo := getCallerInfo() message := fmt.Sprintf(format, args...) logMessage("WARN", callerInfo+" "+message) } // logMessage 写入日志消息 func logMessage(level, message string) { timestamp := time.Now().Format("2006-01-02 15:04:05.000") // 控制台输出(仅在开发模式下显示,避免发布版本弹窗) if isDevMode { log.Printf("[%s] %s %s", timestamp, level, message) } // 发布模式下不输出到控制台,只写入文件 // 文件输出(开发模式和发布模式都写入) logFile := filepath.Join(logDir, fmt.Sprintf("log%s.log", time.Now().Format("20060102"))) file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { return } defer file.Close() fileTimestamp := time.Now().Format("15:04:05.000") file.WriteString(fmt.Sprintf("%s [%s] %s\n", fileTimestamp, level, message)) }