core/logger/logger.go

406 lines
8.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}