208 lines
3.7 KiB
Go
208 lines
3.7 KiB
Go
package logger
|
||
|
||
import (
|
||
"fmt"
|
||
"log"
|
||
"os"
|
||
"strings"
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
type LogLevel int
|
||
|
||
const (
|
||
DEBUG LogLevel = iota
|
||
INFO
|
||
WARN
|
||
ERROR
|
||
)
|
||
|
||
var (
|
||
logLevel LogLevel = INFO
|
||
logFile *os.File
|
||
logger *log.Logger
|
||
mu sync.Mutex
|
||
maxSize int64 = 10 * 1024 * 1024 // 10MB
|
||
maxFiles int = 5
|
||
basePath string = "logs/licensing-cotton.log"
|
||
)
|
||
|
||
func init() {
|
||
// 创建日志目录
|
||
if err := os.MkdirAll("logs", 0755); err != nil {
|
||
log.Printf("无法创建日志目录: %v\n", err)
|
||
return
|
||
}
|
||
|
||
// 打开日志文件
|
||
if err := openLogFile(); err != nil {
|
||
log.Printf("无法打开日志文件: %v\n", err)
|
||
return
|
||
}
|
||
|
||
// 创建标准 logger
|
||
logger = log.New(logFile, "", 0)
|
||
}
|
||
|
||
// SetLevel 设置日志级别
|
||
func SetLevel(level string) {
|
||
switch strings.ToUpper(level) {
|
||
case "DEBUG":
|
||
logLevel = DEBUG
|
||
case "INFO":
|
||
logLevel = INFO
|
||
case "WARN":
|
||
logLevel = WARN
|
||
case "ERROR":
|
||
logLevel = ERROR
|
||
default:
|
||
logLevel = INFO
|
||
}
|
||
}
|
||
|
||
// SetLogPath 设置日志文件路径
|
||
func SetLogPath(path string) {
|
||
mu.Lock()
|
||
defer mu.Unlock()
|
||
basePath = path
|
||
}
|
||
|
||
// SetMaxSize 设置单个日志文件最大大小(字节)
|
||
func SetMaxSize(size int64) {
|
||
mu.Lock()
|
||
defer mu.Unlock()
|
||
maxSize = size
|
||
}
|
||
|
||
// SetMaxFiles 设置保留的日志文件数量
|
||
func SetMaxFiles(count int) {
|
||
mu.Lock()
|
||
defer mu.Unlock()
|
||
maxFiles = count
|
||
}
|
||
|
||
func openLogFile() error {
|
||
file, err := os.OpenFile(basePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
logFile = file
|
||
return nil
|
||
}
|
||
|
||
func rotateLogFile() error {
|
||
// 关闭当前文件
|
||
if logFile != nil {
|
||
logFile.Close()
|
||
}
|
||
|
||
// 轮转文件:最新的移动到 .1,.1 移动到 .2,以此类推
|
||
for i := maxFiles - 1; i >= 1; i-- {
|
||
oldPath := fmt.Sprintf("%s.%d", basePath, i)
|
||
newPath := fmt.Sprintf("%s.%d", basePath, i+1)
|
||
|
||
// 删除最旧的文件
|
||
if i == maxFiles-1 {
|
||
os.Remove(newPath)
|
||
}
|
||
|
||
// 重命名文件
|
||
if _, err := os.Stat(oldPath); err == nil {
|
||
os.Rename(oldPath, newPath)
|
||
}
|
||
}
|
||
|
||
// 将当前日志文件重命名为 .1
|
||
rotatedPath := fmt.Sprintf("%s.1", basePath)
|
||
os.Rename(basePath, rotatedPath)
|
||
|
||
// 打开新文件
|
||
return openLogFile()
|
||
}
|
||
|
||
func checkAndRotate() error {
|
||
if logFile == nil {
|
||
return openLogFile()
|
||
}
|
||
|
||
// 检查文件大小
|
||
stat, err := logFile.Stat()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
if stat.Size() >= maxSize {
|
||
return rotateLogFile()
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
func formatLog(level string, format string, args ...interface{}) string {
|
||
timestamp := time.Now().Format("2006-01-02 15:04:05")
|
||
message := fmt.Sprintf(format, args...)
|
||
return fmt.Sprintf("[%s] [%s] %s\n", timestamp, level, message)
|
||
}
|
||
|
||
func writeLog(level LogLevel, levelStr string, format string, args ...interface{}) {
|
||
if level < logLevel {
|
||
return
|
||
}
|
||
|
||
mu.Lock()
|
||
defer mu.Unlock()
|
||
|
||
// 检查并轮转日志文件
|
||
if err := checkAndRotate(); err != nil {
|
||
log.Printf("日志轮转失败: %v\n", err)
|
||
return
|
||
}
|
||
|
||
// 写入日志文件
|
||
if logger != nil {
|
||
logger.Printf(formatLog(levelStr, format, args...))
|
||
}
|
||
|
||
// 同时输出到标准输出
|
||
fmt.Printf(formatLog(levelStr, format, args...))
|
||
}
|
||
|
||
func Debug(format string, args ...interface{}) {
|
||
writeLog(DEBUG, "DEBUG", format, args...)
|
||
}
|
||
|
||
func Info(format string, args ...interface{}) {
|
||
writeLog(INFO, "INFO", format, args...)
|
||
}
|
||
|
||
func Warn(format string, args ...interface{}) {
|
||
writeLog(WARN, "WARN", format, args...)
|
||
}
|
||
|
||
func Error(format string, args ...interface{}) {
|
||
writeLog(ERROR, "ERROR", format, args...)
|
||
}
|
||
|
||
func Fatal(format string, args ...interface{}) {
|
||
mu.Lock()
|
||
defer mu.Unlock()
|
||
|
||
message := formatLog("FATAL", format, args...)
|
||
if logger != nil {
|
||
logger.Printf(message)
|
||
}
|
||
fmt.Printf(message)
|
||
os.Exit(1)
|
||
}
|
||
|
||
// Close 关闭日志文件
|
||
func Close() {
|
||
mu.Lock()
|
||
defer mu.Unlock()
|
||
if logFile != nil {
|
||
logFile.Close()
|
||
}
|
||
}
|
||
|