2025-07-17 17:42:52 +08:00
|
|
|
package utils
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
|
|
|
|
"log"
|
|
|
|
|
"os"
|
|
|
|
|
"path/filepath"
|
|
|
|
|
"runtime"
|
2025-10-28 11:07:00 +08:00
|
|
|
"strings"
|
2025-07-17 17:42:52 +08:00
|
|
|
"sync"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// LogLevel 日志级别
|
|
|
|
|
type LogLevel int
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
DEBUG LogLevel = iota
|
|
|
|
|
INFO
|
|
|
|
|
WARN
|
|
|
|
|
ERROR
|
|
|
|
|
FATAL
|
|
|
|
|
)
|
|
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
// String 返回级别的字符串表示
|
2025-07-17 17:42:52 +08:00
|
|
|
func (l LogLevel) String() string {
|
|
|
|
|
switch l {
|
|
|
|
|
case DEBUG:
|
|
|
|
|
return "DEBUG"
|
|
|
|
|
case INFO:
|
|
|
|
|
return "INFO"
|
|
|
|
|
case WARN:
|
|
|
|
|
return "WARN"
|
|
|
|
|
case ERROR:
|
|
|
|
|
return "ERROR"
|
|
|
|
|
case FATAL:
|
|
|
|
|
return "FATAL"
|
|
|
|
|
default:
|
|
|
|
|
return "UNKNOWN"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
// Logger 简化的日志器
|
2025-07-17 17:42:52 +08:00
|
|
|
type Logger struct {
|
2025-11-07 18:50:08 +08:00
|
|
|
level LogLevel
|
|
|
|
|
logger *log.Logger
|
2025-07-17 17:42:52 +08:00
|
|
|
file *os.File
|
2025-11-07 18:50:08 +08:00
|
|
|
mu sync.RWMutex
|
2025-10-28 11:07:00 +08:00
|
|
|
}
|
|
|
|
|
|
2025-07-17 17:42:52 +08:00
|
|
|
var (
|
|
|
|
|
globalLogger *Logger
|
2025-11-07 18:50:08 +08:00
|
|
|
loggerOnce sync.Once
|
2025-07-17 17:42:52 +08:00
|
|
|
)
|
|
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
// InitLogger 初始化日志器
|
|
|
|
|
func InitLogger() error {
|
2025-07-17 17:42:52 +08:00
|
|
|
var err error
|
2025-11-07 18:50:08 +08:00
|
|
|
loggerOnce.Do(func() {
|
|
|
|
|
globalLogger = &Logger{
|
|
|
|
|
level: INFO,
|
|
|
|
|
logger: log.New(os.Stdout, "", log.LstdFlags),
|
2025-07-17 17:42:52 +08:00
|
|
|
}
|
|
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
// 创建日志目录
|
|
|
|
|
logDir := "logs"
|
|
|
|
|
if err = os.MkdirAll(logDir, 0755); err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建日志文件
|
|
|
|
|
logFile := filepath.Join(logDir, "app.log")
|
|
|
|
|
globalLogger.file, err = os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 同时输出到控制台和文件
|
|
|
|
|
globalLogger.logger = log.New(io.MultiWriter(os.Stdout, globalLogger.file), "", log.LstdFlags)
|
2025-07-17 17:42:52 +08:00
|
|
|
})
|
2025-11-07 18:50:08 +08:00
|
|
|
|
2025-07-17 17:42:52 +08:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetLogger 获取全局日志器
|
|
|
|
|
func GetLogger() *Logger {
|
|
|
|
|
if globalLogger == nil {
|
2025-11-07 18:50:08 +08:00
|
|
|
InitLogger()
|
2025-07-17 17:42:52 +08:00
|
|
|
}
|
|
|
|
|
return globalLogger
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// log 内部日志方法
|
|
|
|
|
func (l *Logger) log(level LogLevel, format string, args ...interface{}) {
|
2025-11-07 18:50:08 +08:00
|
|
|
if level < l.level {
|
2025-07-17 17:42:52 +08:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取调用者信息
|
|
|
|
|
_, file, line, ok := runtime.Caller(2)
|
2025-11-07 18:50:08 +08:00
|
|
|
caller := "unknown"
|
|
|
|
|
if ok {
|
|
|
|
|
caller = fmt.Sprintf("%s:%d", filepath.Base(file), line)
|
2025-07-17 17:42:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
message := fmt.Sprintf(format, args...)
|
2025-11-07 18:50:08 +08:00
|
|
|
logMessage := fmt.Sprintf("[%s] [%s] %s", level.String(), caller, message)
|
2025-07-17 17:42:52 +08:00
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
l.logger.Println(logMessage)
|
2025-10-28 11:07:00 +08:00
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
// Fatal级别终止程序
|
|
|
|
|
if level == FATAL {
|
2025-07-17 17:42:52 +08:00
|
|
|
os.Exit(1)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Debug 调试日志
|
|
|
|
|
func (l *Logger) Debug(format string, args ...interface{}) {
|
|
|
|
|
l.log(DEBUG, format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Info 信息日志
|
|
|
|
|
func (l *Logger) Info(format string, args ...interface{}) {
|
|
|
|
|
l.log(INFO, format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Warn 警告日志
|
|
|
|
|
func (l *Logger) Warn(format string, args ...interface{}) {
|
|
|
|
|
l.log(WARN, format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Error 错误日志
|
|
|
|
|
func (l *Logger) Error(format string, args ...interface{}) {
|
|
|
|
|
l.log(ERROR, format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fatal 致命错误日志
|
|
|
|
|
func (l *Logger) Fatal(format string, args ...interface{}) {
|
|
|
|
|
l.log(FATAL, format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
// TelegramDebug Telegram调试日志
|
|
|
|
|
func (l *Logger) TelegramDebug(format string, args ...interface{}) {
|
|
|
|
|
l.log(DEBUG, "[TELEGRAM] "+format, args...)
|
2025-07-17 17:42:52 +08:00
|
|
|
}
|
|
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
// TelegramInfo Telegram信息日志
|
|
|
|
|
func (l *Logger) TelegramInfo(format string, args ...interface{}) {
|
|
|
|
|
l.log(INFO, "[TELEGRAM] "+format, args...)
|
2025-07-17 17:42:52 +08:00
|
|
|
}
|
|
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
// TelegramWarn Telegram警告日志
|
|
|
|
|
func (l *Logger) TelegramWarn(format string, args ...interface{}) {
|
|
|
|
|
l.log(WARN, "[TELEGRAM] "+format, args...)
|
2025-07-17 17:42:52 +08:00
|
|
|
}
|
|
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
// TelegramError Telegram错误日志
|
|
|
|
|
func (l *Logger) TelegramError(format string, args ...interface{}) {
|
|
|
|
|
l.log(ERROR, "[TELEGRAM] "+format, args...)
|
2025-10-28 11:07:00 +08:00
|
|
|
}
|
2025-07-17 17:42:52 +08:00
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
// DebugWithFields 带字段的调试日志
|
2025-10-28 11:07:00 +08:00
|
|
|
func (l *Logger) DebugWithFields(fields map[string]interface{}, format string, args ...interface{}) {
|
2025-11-07 18:50:08 +08:00
|
|
|
message := fmt.Sprintf(format, args...)
|
|
|
|
|
if len(fields) > 0 {
|
|
|
|
|
var fieldStrs []string
|
|
|
|
|
for k, v := range fields {
|
|
|
|
|
fieldStrs = append(fieldStrs, fmt.Sprintf("%s=%v", k, v))
|
|
|
|
|
}
|
|
|
|
|
message = fmt.Sprintf("%s [%s]", message, strings.Join(fieldStrs, ", "))
|
|
|
|
|
}
|
|
|
|
|
l.log(DEBUG, message)
|
2025-10-28 11:07:00 +08:00
|
|
|
}
|
|
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
// InfoWithFields 带字段的信息日志
|
2025-10-28 11:07:00 +08:00
|
|
|
func (l *Logger) InfoWithFields(fields map[string]interface{}, format string, args ...interface{}) {
|
2025-11-07 18:50:08 +08:00
|
|
|
message := fmt.Sprintf(format, args...)
|
|
|
|
|
if len(fields) > 0 {
|
|
|
|
|
var fieldStrs []string
|
|
|
|
|
for k, v := range fields {
|
|
|
|
|
fieldStrs = append(fieldStrs, fmt.Sprintf("%s=%v", k, v))
|
|
|
|
|
}
|
|
|
|
|
message = fmt.Sprintf("%s [%s]", message, strings.Join(fieldStrs, ", "))
|
|
|
|
|
}
|
|
|
|
|
l.log(INFO, message)
|
2025-10-28 11:07:00 +08:00
|
|
|
}
|
|
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
// ErrorWithFields 带字段的错误日志
|
2025-10-28 11:07:00 +08:00
|
|
|
func (l *Logger) ErrorWithFields(fields map[string]interface{}, format string, args ...interface{}) {
|
|
|
|
|
message := fmt.Sprintf(format, args...)
|
2025-11-07 18:50:08 +08:00
|
|
|
if len(fields) > 0 {
|
|
|
|
|
var fieldStrs []string
|
|
|
|
|
for k, v := range fields {
|
|
|
|
|
fieldStrs = append(fieldStrs, fmt.Sprintf("%s=%v", k, v))
|
2025-10-28 11:07:00 +08:00
|
|
|
}
|
2025-11-07 18:50:08 +08:00
|
|
|
message = fmt.Sprintf("%s [%s]", message, strings.Join(fieldStrs, ", "))
|
|
|
|
|
}
|
|
|
|
|
l.log(ERROR, message)
|
|
|
|
|
}
|
2025-10-28 11:07:00 +08:00
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
// Close 关闭日志文件
|
|
|
|
|
func (l *Logger) Close() {
|
|
|
|
|
l.mu.Lock()
|
|
|
|
|
defer l.mu.Unlock()
|
|
|
|
|
if l.file != nil {
|
|
|
|
|
l.file.Close()
|
2025-07-17 17:42:52 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 全局便捷函数
|
|
|
|
|
func Debug(format string, args ...interface{}) {
|
|
|
|
|
GetLogger().Debug(format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Info(format string, args ...interface{}) {
|
|
|
|
|
GetLogger().Info(format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Warn(format string, args ...interface{}) {
|
|
|
|
|
GetLogger().Warn(format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Error(format string, args ...interface{}) {
|
|
|
|
|
GetLogger().Error(format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Fatal(format string, args ...interface{}) {
|
|
|
|
|
GetLogger().Fatal(format, args...)
|
|
|
|
|
}
|
2025-10-28 11:07:00 +08:00
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
func TelegramDebug(format string, args ...interface{}) {
|
|
|
|
|
GetLogger().TelegramDebug(format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TelegramInfo(format string, args ...interface{}) {
|
|
|
|
|
GetLogger().TelegramInfo(format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TelegramWarn(format string, args ...interface{}) {
|
|
|
|
|
GetLogger().TelegramWarn(format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TelegramError(format string, args ...interface{}) {
|
|
|
|
|
GetLogger().TelegramError(format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-28 11:07:00 +08:00
|
|
|
func DebugWithFields(fields map[string]interface{}, format string, args ...interface{}) {
|
|
|
|
|
GetLogger().DebugWithFields(fields, format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func InfoWithFields(fields map[string]interface{}, format string, args ...interface{}) {
|
|
|
|
|
GetLogger().InfoWithFields(fields, format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ErrorWithFields(fields map[string]interface{}, format string, args ...interface{}) {
|
|
|
|
|
GetLogger().ErrorWithFields(fields, format, args...)
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-07 18:50:08 +08:00
|
|
|
// Min 返回两个整数中的较小值
|
|
|
|
|
func Min(a, b int) int {
|
|
|
|
|
if a < b {
|
|
|
|
|
return a
|
|
|
|
|
}
|
|
|
|
|
return b
|
2025-10-28 11:07:00 +08:00
|
|
|
}
|
2025-11-07 18:50:08 +08:00
|
|
|
|