2025-10-02 18:06:23 +08:00
|
|
|
|
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"
|
2025-10-04 17:42:26 +08:00
|
|
|
|
"git.apinb.com/bsm-sdk/core/vars"
|
2025-10-02 18:06:23 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Logger 日志器结构
|
|
|
|
|
type Logger struct {
|
2025-10-04 17:42:26 +08:00
|
|
|
|
level vars.LogLevel
|
2025-10-02 18:06:23 +08:00
|
|
|
|
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{
|
2025-10-07 17:31:14 +08:00
|
|
|
|
level: cfg.Level,
|
2025-10-02 18:06:23 +08:00
|
|
|
|
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{}) {
|
2025-10-04 17:42:26 +08:00
|
|
|
|
if l.level <= vars.DEBUG {
|
2025-10-02 18:06:23 +08:00
|
|
|
|
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{}) {
|
2025-10-04 17:42:26 +08:00
|
|
|
|
if l.level <= vars.DEBUG {
|
2025-10-02 18:06:23 +08:00
|
|
|
|
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{}) {
|
2025-10-04 17:42:26 +08:00
|
|
|
|
if l.level <= vars.INFO {
|
2025-10-02 18:06:23 +08:00
|
|
|
|
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{}) {
|
2025-10-04 17:42:26 +08:00
|
|
|
|
if l.level <= vars.INFO {
|
2025-10-02 18:06:23 +08:00
|
|
|
|
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{}) {
|
2025-10-04 17:42:26 +08:00
|
|
|
|
if l.level <= vars.WARN {
|
2025-10-02 18:06:23 +08:00
|
|
|
|
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{}) {
|
2025-10-04 17:42:26 +08:00
|
|
|
|
if l.level <= vars.WARN {
|
2025-10-02 18:06:23 +08:00
|
|
|
|
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{}) {
|
2025-10-04 17:42:26 +08:00
|
|
|
|
if l.level <= vars.ERROR {
|
2025-10-02 18:06:23 +08:00
|
|
|
|
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{}) {
|
2025-10-04 17:42:26 +08:00
|
|
|
|
if l.level <= vars.ERROR {
|
2025-10-02 18:06:23 +08:00
|
|
|
|
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 设置日志级别
|
2025-10-04 17:42:26 +08:00
|
|
|
|
func (l *Logger) SetLevel(level vars.LogLevel) {
|
2025-10-02 18:06:23 +08:00
|
|
|
|
l.mu.Lock()
|
|
|
|
|
defer l.mu.Unlock()
|
|
|
|
|
l.level = level
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetLevel 获取日志级别
|
2025-10-04 17:42:26 +08:00
|
|
|
|
func (l *Logger) GetLevel() vars.LogLevel {
|
2025-10-02 18:06:23 +08:00
|
|
|
|
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
|
|
|
|
|
}
|