package logger import ( "encoding/json" "fmt" "io" "log" "os" "path/filepath" "strings" "sync" "time" "git.apinb.com/bsm-sdk/core/conf" "git.apinb.com/bsm-sdk/core/utils" "git.apinb.com/bsm-sdk/core/vars" ) // Logger 日志器结构 type Logger struct { level vars.LogLevel infoLogger *log.Logger warnLogger *log.Logger errorLogger *log.Logger fatalLogger *log.Logger debugLogger *log.Logger fileWriter io.Writer consoleWriter io.Writer mu sync.RWMutex name string logDir string currentDate string onRemote bool endpoint string } var ( globalLogger *Logger once sync.Once ) // InitLogger 初始化全局日志器 func InitLogger(cfg *conf.LogConf) error { var err error once.Do(func() { globalLogger, err = NewLogger(cfg) }) return err } // NewLogger 创建新的日志器 func NewLogger(cfg *conf.LogConf) (*Logger, error) { // 确保日志目录存在 if err := os.MkdirAll(cfg.Dir, 0755); err != nil { return nil, fmt.Errorf("创建日志目录失败: %v", err) } // 控制台输出 consoleWriter := os.Stdout // 文件输出 fileWriter, err := createLogFile(cfg.Dir, cfg.Name) if err != nil { return nil, fmt.Errorf("创建日志文件失败: %v", err) } // 创建多输出写入器 multiWriter := io.MultiWriter(consoleWriter, fileWriter) logger := &Logger{ level: vars.LogLevel(cfg.Level), fileWriter: fileWriter, consoleWriter: consoleWriter, logDir: cfg.Dir, name: strings.ToLower(cfg.Name), currentDate: time.Now().Format("2006-01-02"), onRemote: cfg.Remote, endpoint: cfg.Endpoint, } // 创建不同级别的日志器 logger.infoLogger = log.New(multiWriter, "[INFO] ", log.LstdFlags) logger.warnLogger = log.New(multiWriter, "[WARN] ", log.LstdFlags) logger.errorLogger = log.New(multiWriter, "[ERROR] ", log.LstdFlags) logger.fatalLogger = log.New(multiWriter, "[FATAL] ", log.LstdFlags) logger.debugLogger = log.New(multiWriter, "[DEBUG] ", log.LstdFlags) return logger, nil } // createLogFile 创建日志文件 func createLogFile(logDir, name string) (io.Writer, error) { filename := fmt.Sprintf("%s_%s.log", name, time.Now().Format("2006-01-02")) filepath := filepath.Join(logDir, filename) file, err := os.OpenFile(filepath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { return nil, err } return file, nil } // checkAndRotateLog 检查并轮转日志文件 func (l *Logger) checkAndRotateLog() error { today := time.Now().Format("2006-01-02") if l.currentDate != today { l.mu.Lock() defer l.mu.Unlock() if l.currentDate != today { // 关闭旧文件 if closer, ok := l.fileWriter.(io.Closer); ok { closer.Close() } // 创建新文件 newFileWriter, err := createLogFile(l.logDir, l.name) if err != nil { return err } l.fileWriter = newFileWriter l.currentDate = today // 重新创建多输出写入器 multiWriter := io.MultiWriter(l.consoleWriter, l.fileWriter) l.infoLogger = log.New(multiWriter, "[INFO] ", log.LstdFlags) l.warnLogger = log.New(multiWriter, "[WARN] ", log.LstdFlags) l.errorLogger = log.New(multiWriter, "[ERROR] ", log.LstdFlags) l.fatalLogger = log.New(multiWriter, "[FATAL] ", log.LstdFlags) l.debugLogger = log.New(multiWriter, "[DEBUG] ", log.LstdFlags) } } return nil } func (l *Logger) sendToRemote(level, name, out string) { if l.endpoint == "" { return } data := map[string]interface{}{ "level": level, "name": name, "out": out, } jsonBytes, _ := json.Marshal(data) utils.HttpPost(l.endpoint, nil, jsonBytes) } // Debug 输出调试信息 func (l *Logger) Debug(v ...interface{}) { if l.level <= vars.DEBUG { l.checkAndRotateLog() out := fmt.Sprint(v...) if l.onRemote { go l.sendToRemote("DEBUG", l.name, out) } l.debugLogger.Output(2, out) } } // Debugf 格式化输出调试信息 func (l *Logger) Debugf(format string, v ...interface{}) { if l.level <= vars.DEBUG { l.checkAndRotateLog() out := fmt.Sprintf(format, v...) if l.onRemote { go l.sendToRemote("DEBUG", l.name, out) } l.debugLogger.Output(2, out) } } // Info 输出信息 func (l *Logger) Info(v ...interface{}) { if l.level <= vars.INFO { l.checkAndRotateLog() out := fmt.Sprint(v...) if l.onRemote { go l.sendToRemote("INFO", l.name, out) } l.infoLogger.Output(2, out) } } // Infof 格式化输出信息 func (l *Logger) Infof(format string, v ...interface{}) { if l.level <= vars.INFO { l.checkAndRotateLog() out := fmt.Sprintf(format, v...) if l.onRemote { go l.sendToRemote("INFO", l.name, out) } l.infoLogger.Output(2, out) } } // Warn 输出警告 func (l *Logger) Warn(v ...interface{}) { if l.level <= vars.WARN { l.checkAndRotateLog() out := fmt.Sprint(v...) if l.onRemote { go l.sendToRemote("WARN", l.name, out) } l.warnLogger.Output(2, out) } } // Warnf 格式化输出警告 func (l *Logger) Warnf(format string, v ...interface{}) { if l.level <= vars.WARN { l.checkAndRotateLog() out := fmt.Sprintf(format, v...) if l.onRemote { go l.sendToRemote("WARN", l.name, out) } l.warnLogger.Output(2, out) } } // Error 输出错误 func (l *Logger) Error(v ...interface{}) { if l.level <= vars.ERROR { l.checkAndRotateLog() out := fmt.Sprint(v...) if l.onRemote { go l.sendToRemote("ERROR", l.name, out) } l.errorLogger.Output(2, out) } } // Errorf 格式化输出错误 func (l *Logger) Errorf(format string, v ...interface{}) { if l.level <= vars.ERROR { l.checkAndRotateLog() out := fmt.Sprintf(format, v...) if l.onRemote { go l.sendToRemote("ERROR", l.name, out) } l.errorLogger.Output(2, out) } } // Fatal 输出致命错误并退出程序 func (l *Logger) Fatal(v ...interface{}) { l.checkAndRotateLog() out := fmt.Sprint(v...) if l.onRemote { go l.sendToRemote("FATAL", l.name, out) } l.fatalLogger.Output(2, out) os.Exit(1) } // Fatalf 格式化输出致命错误并退出程序 func (l *Logger) Fatalf(format string, v ...interface{}) { l.checkAndRotateLog() out := fmt.Sprintf(format, v...) if l.onRemote { go l.sendToRemote("FATAL", l.name, out) } l.fatalLogger.Output(2, out) os.Exit(1) } // Print 输出信息(兼容标准log包) func (l *Logger) Print(v ...interface{}) { l.Info(v...) } // Printf 格式化输出信息(兼容标准log包) func (l *Logger) Printf(format string, v ...interface{}) { l.Infof(format, v...) } // Println 输出信息并换行(兼容标准log包) func (l *Logger) Println(v ...interface{}) { l.Info(v...) } // SetLevel 设置日志级别 func (l *Logger) SetLevel(level vars.LogLevel) { l.mu.Lock() defer l.mu.Unlock() l.level = level } // GetLevel 获取日志级别 func (l *Logger) GetLevel() vars.LogLevel { l.mu.RLock() defer l.mu.RUnlock() return l.level } // Close 关闭日志器 func (l *Logger) Close() error { if closer, ok := l.fileWriter.(io.Closer); ok { return closer.Close() } return nil } // 全局日志函数(兼容标准log包) // Debug 全局调试日志 func Debug(v ...interface{}) { if globalLogger != nil { globalLogger.Debug(v...) } } // Debugf 全局调试日志 func Debugf(format string, v ...interface{}) { if globalLogger != nil { globalLogger.Debugf(format, v...) } } // Info 全局信息日志 func Info(v ...interface{}) { if globalLogger != nil { globalLogger.Info(v...) } } // Infof 全局信息日志 func Infof(format string, v ...interface{}) { if globalLogger != nil { globalLogger.Infof(format, v...) } } // Warn 全局警告日志 func Warn(v ...interface{}) { if globalLogger != nil { globalLogger.Warn(v...) } } // Warnf 全局警告日志 func Warnf(format string, v ...interface{}) { if globalLogger != nil { globalLogger.Warnf(format, v...) } } // Error 全局错误日志 func Error(v ...interface{}) { if globalLogger != nil { globalLogger.Error(v...) } } // Errorf 全局错误日志 func Errorf(format string, v ...interface{}) { if globalLogger != nil { globalLogger.Errorf(format, v...) } } // Fatal 全局致命错误日志 func Fatal(v ...interface{}) { if globalLogger != nil { globalLogger.Fatal(v...) } } // Fatalf 全局致命错误日志 func Fatalf(format string, v ...interface{}) { if globalLogger != nil { globalLogger.Fatalf(format, v...) } } // Print 全局打印日志(兼容标准log包) func Print(v ...interface{}) { if globalLogger != nil { globalLogger.Print(v...) } } // Printf 全局打印日志(兼容标准log包) func Printf(format string, v ...interface{}) { if globalLogger != nil { globalLogger.Printf(format, v...) } } // Println 全局打印日志(兼容标准log包) func Println(v ...interface{}) { if globalLogger != nil { globalLogger.Println(v...) } } // GetLogger 获取全局日志器实例 func GetLogger() *Logger { return globalLogger }