282 lines
7.4 KiB
Go
282 lines
7.4 KiB
Go
package logger
|
|
|
|
import (
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// Logger 全局日志实例
|
|
var Logger *log.Logger
|
|
var logFile *os.File
|
|
var logFileName string
|
|
var mu sync.Mutex
|
|
|
|
// LoggerManager 日志管理器
|
|
type LoggerManager struct {
|
|
loggers map[string]*log.Logger
|
|
files map[string]*os.File
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
// GlobalLoggerManager 全局日志管理器
|
|
var GlobalLoggerManager = &LoggerManager{
|
|
loggers: make(map[string]*log.Logger),
|
|
files: make(map[string]*os.File),
|
|
}
|
|
|
|
// CreateLogger 创建带有指定路径的日志实例
|
|
func (lm *LoggerManager) CreateLogger(name string, logDir string) (*log.Logger, error) {
|
|
lm.mu.Lock()
|
|
defer lm.mu.Unlock()
|
|
|
|
// 确保日志目录存在
|
|
if err := os.MkdirAll(logDir, 0755); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// 按天生成日志文件名
|
|
logFileName := filepath.Join(logDir, name+"_"+time.Now().Format("20060102")+".log")
|
|
file, err := os.OpenFile(logFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
logger := log.New(file, "", log.LstdFlags)
|
|
lm.loggers[name] = logger
|
|
lm.files[name] = file
|
|
|
|
// 每天凌晨检查是否需要切换日志文件
|
|
go func() {
|
|
for {
|
|
// 每天检查一次(凌晨 00:05 执行)
|
|
now := time.Now()
|
|
next := time.Date(now.Year(), now.Month(), now.Day()+1, 0, 5, 0, 0, now.Location())
|
|
time.Sleep(time.Until(next))
|
|
|
|
lm.mu.Lock()
|
|
newFileName := filepath.Join(logDir, name+"_"+time.Now().Format("20060102")+".log")
|
|
if newFileName != logFileName {
|
|
newFile, err := os.OpenFile(newFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
log.Printf("Failed to switch the log file: %v", err)
|
|
lm.mu.Unlock()
|
|
continue
|
|
}
|
|
file.Close()
|
|
file = newFile
|
|
logFileName = newFileName
|
|
logger = log.New(newFile, "", log.LstdFlags)
|
|
lm.loggers[name] = logger
|
|
lm.files[name] = newFile
|
|
logger.Println("The log file has been switched:", newFileName)
|
|
}
|
|
lm.mu.Unlock()
|
|
}
|
|
}()
|
|
|
|
return logger, nil
|
|
}
|
|
|
|
// GetLogger 获取指定名称的日志实例
|
|
func (lm *LoggerManager) GetLogger(name string) *log.Logger {
|
|
lm.mu.RLock()
|
|
defer lm.mu.RUnlock()
|
|
return lm.loggers[name]
|
|
}
|
|
|
|
// CloseLogger 关闭指定名称的日志文件
|
|
func (lm *LoggerManager) CloseLogger(name string) {
|
|
lm.mu.Lock()
|
|
defer lm.mu.Unlock()
|
|
if file, exists := lm.files[name]; exists {
|
|
file.Close()
|
|
delete(lm.files, name)
|
|
delete(lm.loggers, name)
|
|
}
|
|
}
|
|
|
|
// CloseAllLoggers 关闭所有日志文件
|
|
func (lm *LoggerManager) CloseAllLoggers() {
|
|
lm.mu.Lock()
|
|
defer lm.mu.Unlock()
|
|
for name, file := range lm.files {
|
|
file.Close()
|
|
delete(lm.files, name)
|
|
delete(lm.loggers, name)
|
|
}
|
|
}
|
|
|
|
// InitLogger 初始化系统日志,创建 /data/logs/system 目录并按天命名文件
|
|
func InitLogger() error {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
|
|
// 创建 /data/logs/system 目录
|
|
logDir := "/data/logs/system"
|
|
if err := os.MkdirAll(logDir, 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
// 按天生成日志文件名:system_20260102.log
|
|
logFileName = filepath.Join(logDir, "system_"+time.Now().Format("20060102")+".log")
|
|
file, err := os.OpenFile(logFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
logFile = file
|
|
Logger = log.New(file, "", log.LstdFlags)
|
|
|
|
// 每天凌晨检查是否需要切换日志文件
|
|
go func() {
|
|
for {
|
|
// 每天检查一次(凌晨 00:05 执行)
|
|
now := time.Now()
|
|
next := time.Date(now.Year(), now.Month(), now.Day()+1, 0, 5, 0, 0, now.Location())
|
|
time.Sleep(time.Until(next))
|
|
|
|
mu.Lock()
|
|
newFileName := filepath.Join(logDir, "system_"+time.Now().Format("20060102")+".log")
|
|
if newFileName != logFileName {
|
|
newFile, err := os.OpenFile(newFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
log.Printf("Failed to switch the log file: %v", err)
|
|
mu.Unlock()
|
|
continue
|
|
}
|
|
logFile.Close()
|
|
logFile = newFile
|
|
logFileName = newFileName
|
|
Logger = log.New(newFile, "", log.LstdFlags)
|
|
Logger.Println("The log file has been switched:", newFileName)
|
|
}
|
|
mu.Unlock()
|
|
}
|
|
}()
|
|
return nil
|
|
}
|
|
|
|
// InitReporterLogger 初始化上报管理器专用日志,创建 /data/logs/reporter 目录并按天命名文件
|
|
func InitReporterLogger() error {
|
|
// 创建上报管理器专用日志
|
|
_, err := GlobalLoggerManager.CreateLogger("reporter", "/data/logs/reporter")
|
|
return err
|
|
}
|
|
|
|
// InitGPILogger 初始化GPIO监控专用日志,创建 /data/logs/reporter 目录并按天命名文件
|
|
func InitGPILogger() error {
|
|
// 创建GPIO监控专用日志
|
|
_, err := GlobalLoggerManager.CreateLogger("gpio", "/data/logs/reporter")
|
|
return err
|
|
}
|
|
|
|
// InitLoggerWithPath 初始化日志,使用指定的日志文件路径
|
|
func InitLoggerWithPath(logPath string) error {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
|
|
// 创建日志目录
|
|
logDir := filepath.Dir(logPath)
|
|
if err := os.MkdirAll(logDir, 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
// 打开指定的日志文件
|
|
logFileName = logPath
|
|
file, err := os.OpenFile(logFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
logFile = file
|
|
Logger = log.New(file, "", log.LstdFlags)
|
|
|
|
// 每天凌晨检查是否需要切换日志文件
|
|
go func() {
|
|
for {
|
|
// 每天检查一次(凌晨 00:05 执行)
|
|
now := time.Now()
|
|
next := time.Date(now.Year(), now.Month(), now.Day()+1, 0, 5, 0, 0, now.Location())
|
|
time.Sleep(time.Until(next))
|
|
|
|
mu.Lock()
|
|
// 生成新的日志文件名,保留原有文件名的前缀和添加日期后缀
|
|
baseName := filepath.Base(logPath)
|
|
ext := filepath.Ext(baseName)
|
|
nameWithoutExt := baseName[:len(baseName)-len(ext)]
|
|
newFileName := filepath.Join(logDir, nameWithoutExt+"_"+time.Now().Format("20060102")+ext)
|
|
if newFileName != logFileName {
|
|
newFile, err := os.OpenFile(newFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
log.Printf("Failed to switch the log file: %v", err)
|
|
mu.Unlock()
|
|
continue
|
|
}
|
|
logFile.Close()
|
|
logFile = newFile
|
|
logFileName = newFileName
|
|
Logger = log.New(newFile, "", log.LstdFlags)
|
|
Logger.Println("The log file has been switched:", newFileName)
|
|
}
|
|
mu.Unlock()
|
|
}
|
|
}()
|
|
return nil
|
|
}
|
|
|
|
// CloseLogger 关闭日志文件
|
|
func CloseLogger() {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
if logFile != nil {
|
|
logFile.Close()
|
|
logFile = nil
|
|
}
|
|
}
|
|
|
|
// CleanupOldLogs 删除超过30天的日志文件
|
|
func CleanupOldLogs() {
|
|
// 清理system目录的日志文件
|
|
cleanupLogDirectory("/data/logs/system")
|
|
|
|
// 清理reporter目录的日志文件
|
|
cleanupLogDirectory("/data/logs/reporter")
|
|
}
|
|
|
|
// cleanupLogDirectory 清理指定目录下超过30天的日志文件
|
|
func cleanupLogDirectory(logDir string) {
|
|
files, err := os.ReadDir(logDir)
|
|
if err != nil {
|
|
if Logger != nil {
|
|
Logger.Printf("Read the log directory %s Error: %v", logDir, err)
|
|
}
|
|
return
|
|
}
|
|
const maxAge = 30 * 24 * time.Hour // 30天
|
|
for _, file := range files {
|
|
if file.IsDir() {
|
|
continue
|
|
}
|
|
info, err := file.Info()
|
|
if err != nil {
|
|
if Logger != nil {
|
|
Logger.Printf("Obtain file information %s Error: %v", file.Name(), err)
|
|
}
|
|
continue
|
|
}
|
|
if time.Since(info.ModTime()) > maxAge {
|
|
filePath := filepath.Join(logDir, file.Name())
|
|
if err := os.Remove(filePath); err != nil {
|
|
if Logger != nil {
|
|
Logger.Printf("Delete the old log files %s Error: %v", filePath, err)
|
|
}
|
|
} else {
|
|
if Logger != nil {
|
|
Logger.Printf("Delete the old log files %s succeed", filePath)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|