starlog/archive.go

454 lines
13 KiB
Go
Raw Permalink Normal View History

2020-12-21 17:22:45 +08:00
package starlog
import (
"errors"
"os"
"path/filepath"
"time"
)
2024-08-18 17:33:43 +08:00
var archMap starMapKV
2020-12-22 11:07:20 +08:00
func init() {
2024-08-18 17:33:43 +08:00
archMap = newStarMap()
2020-12-22 11:07:20 +08:00
}
2020-12-21 17:22:45 +08:00
type Archive interface {
2024-03-10 15:39:05 +08:00
ShouldArchiveNow(*StarLogger, string, os.FileInfo) bool
NextLogFilePath(*StarLogger, string, os.FileInfo) string
ArchiveLogFilePath(*StarLogger, string, os.FileInfo) string
2020-12-21 17:22:45 +08:00
Interval() int64
2024-03-10 15:39:05 +08:00
HookBeforArchive() func(*StarLogger, string, string, os.FileInfo) error //archivePath;currentPath
HookAfterArchive() func(*StarLogger, string, string, os.FileInfo) error //archivePath;currentPath
2025-04-28 13:16:36 +08:00
DoArchive() func(*StarLogger, string, string, os.FileInfo) error
2020-12-21 17:22:45 +08:00
}
type logfileinfo struct {
fullpath string
pointer *os.File
}
func SetLogFile(path string, logger *StarLogger, appendMode bool) error {
var fileMode int
if appendMode {
2020-12-23 20:54:03 +08:00
fileMode = os.O_APPEND | os.O_CREATE | os.O_WRONLY
2020-12-21 17:22:45 +08:00
} else {
2020-12-29 14:05:14 +08:00
fileMode = os.O_CREATE | os.O_WRONLY | os.O_TRUNC
2020-12-21 17:22:45 +08:00
}
fullpath, err := filepath.Abs(path)
if err != nil {
return err
}
2024-03-10 15:39:05 +08:00
if !appendMode && Exists(fullpath) {
2020-12-21 17:22:45 +08:00
os.Remove(fullpath)
}
fp, err := os.OpenFile(fullpath, fileMode, 0644)
if err != nil {
return err
}
2020-12-22 11:07:20 +08:00
if archMap.MustGet(logger.logcore.id) != nil {
2020-12-21 17:22:45 +08:00
logger.SetSwitching(true)
2020-12-22 11:07:20 +08:00
err := archMap.MustGet(logger.logcore.id).(logfileinfo).pointer.Close()
2020-12-21 17:22:45 +08:00
if err != nil {
logger.logcore.output = nil
logger.SetSwitching(false)
return err
}
2020-12-22 11:07:20 +08:00
err = archMap.Delete(logger.logcore.id)
2020-12-21 17:22:45 +08:00
if err != nil {
logger.logcore.output = nil
logger.SetSwitching(false)
return err
}
}
2020-12-22 11:07:20 +08:00
err = archMap.Store(logger.logcore.id, logfileinfo{
2020-12-21 17:22:45 +08:00
fullpath: fullpath,
pointer: fp,
})
if err != nil {
fp.Close()
logger.logcore.output = nil
logger.SetSwitching(false)
return err
}
logger.SetSwitching(true)
logger.logcore.output = fp
logger.SetSwitching(false)
return nil
}
2020-12-22 11:07:20 +08:00
func CloseWithSwitching(logger *StarLogger) error {
if archMap.MustGet(logger.logcore.id) != nil {
2020-12-21 17:22:45 +08:00
logger.SetSwitching(true)
2020-12-23 20:54:03 +08:00
err := archMap.MustGet(logger.logcore.id).(logfileinfo).pointer.Close()
2020-12-21 17:22:45 +08:00
if err != nil {
logger.logcore.output = nil
return err
}
2020-12-22 11:07:20 +08:00
err = archMap.Delete(logger.logcore.id)
2020-12-21 17:22:45 +08:00
if err != nil {
return err
}
}
return nil
}
2020-12-22 11:07:20 +08:00
func Close(logger *StarLogger) error {
defer logger.SetSwitching(false)
return CloseWithSwitching(logger)
}
2020-12-21 17:22:45 +08:00
func GetLogFileInfo(logger *StarLogger) (os.FileInfo, error) {
2020-12-22 11:07:20 +08:00
if archMap.MustGet(logger.logcore.id) != nil {
return archMap.MustGet(logger.logcore.id).(logfileinfo).pointer.Stat()
2020-12-21 17:22:45 +08:00
}
return nil, errors.New("logger don't have a register logfile")
}
func StartArchive(logger *StarLogger, arch Archive) error {
2020-12-22 11:07:20 +08:00
if archMap.MustGet("arch"+logger.logcore.id) != nil {
2020-12-21 17:22:45 +08:00
return errors.New("already running")
}
stopChan := make(chan int)
2020-12-22 11:07:20 +08:00
archMap.Store("arch"+logger.logcore.id, stopChan)
2020-12-21 17:22:45 +08:00
go func(stopChan chan int, arch Archive, logger *StarLogger) {
for {
select {
case <-stopChan:
return
2024-03-10 15:39:05 +08:00
case <-time.After(time.Millisecond * time.Duration(1000*arch.Interval())):
2020-12-21 17:22:45 +08:00
}
fileinfo, err := GetLogFileInfo(logger)
if err != nil {
logger.Errorf("cannot get log file info,reason is %v\n", err)
continue
}
2020-12-22 11:07:20 +08:00
if archMap.MustGet(logger.logcore.id) == nil {
2020-12-21 17:22:45 +08:00
logger.Errorf("cannot get log core info from the map:no such keys\n")
continue
}
2020-12-22 11:07:20 +08:00
fullpath := archMap.MustGet(logger.logcore.id).(logfileinfo).fullpath
2024-03-10 15:39:05 +08:00
if !arch.ShouldArchiveNow(logger, fullpath, fileinfo) {
2020-12-21 17:22:45 +08:00
continue
}
2024-03-10 15:39:05 +08:00
newLogPath := arch.NextLogFilePath(logger, fullpath, fileinfo)
archiveLogPath := arch.ArchiveLogFilePath(logger, fullpath, fileinfo)
2020-12-21 17:22:45 +08:00
if arch.HookBeforArchive() != nil {
2024-03-10 15:39:05 +08:00
if err := arch.HookBeforArchive()(logger, archiveLogPath, fullpath, fileinfo); err != nil {
2020-12-21 17:22:45 +08:00
logger.Errorf("error occur while executing hook before archive,detail is %v\n", err)
continue
}
}
2024-03-10 15:39:05 +08:00
err = CloseWithSwitching(logger)
if err != nil {
continue
}
2025-04-28 13:16:36 +08:00
if arch.DoArchive() == nil {
err = os.Rename(fullpath, archiveLogPath)
if err != nil {
continue
}
} else {
err = arch.DoArchive()(logger, fullpath, archiveLogPath, fileinfo)
if err != nil {
logger.Errorf("error occur while executing archive log file,detail is %v\n", err)
continue
}
2024-03-10 15:39:05 +08:00
}
2020-12-21 17:22:45 +08:00
if err := SetLogFile(newLogPath, logger, false); err != nil {
logger.Errorf("error occur while executing coverting new log file,detail is %v\n", err)
continue
} else {
2024-03-10 15:39:05 +08:00
logger.Debugln("Archive Log Success")
2020-12-21 17:22:45 +08:00
}
fileinfo, err = GetLogFileInfo(logger)
if err != nil {
logger.Errorf("cannot get new log core info from the map:no such keys\n")
continue
}
if arch.HookAfterArchive() != nil {
2024-03-10 15:39:05 +08:00
if err := arch.HookAfterArchive()(logger, archiveLogPath, newLogPath, fileinfo); err != nil {
2020-12-21 17:22:45 +08:00
logger.Errorf("error occur while executing hook after archive,detail is %v\n", err)
continue
}
}
}
}(stopChan, arch, logger)
return nil
}
func IsArchiveRun(logger *StarLogger) bool {
2020-12-22 11:07:20 +08:00
if archMap.MustGet("arch"+logger.logcore.id) == nil {
2020-12-21 17:22:45 +08:00
return false
}
return true
}
func StopArchive(logger *StarLogger) {
2020-12-22 11:07:20 +08:00
if archMap.MustGet("arch"+logger.logcore.id) == nil {
2020-12-21 17:22:45 +08:00
return
}
2020-12-22 11:07:20 +08:00
archMap.MustGet("arch" + logger.logcore.id).(chan int) <- 1
2020-12-21 17:22:45 +08:00
}
type ArchiveByDate struct {
2024-03-10 15:39:05 +08:00
interval int64
checkInterval int64
baseFileStyle string
archiveStyle string
lastSwitchTime time.Time
changeArchiveName bool
hookBefore func(*StarLogger, string, string, os.FileInfo) error
hookAfter func(*StarLogger, string, string, os.FileInfo) error
2020-12-21 17:22:45 +08:00
}
2024-03-10 15:39:05 +08:00
func (abd *ArchiveByDate) ShouldArchiveNow(l *StarLogger, fullpath string, info os.FileInfo) bool {
if abd.lastSwitchTime.IsZero() {
abd.lastSwitchTime = GetFileCreationTime(info)
}
sub := time.Now().Unix() - abd.lastSwitchTime.Unix()
if sub >= abd.interval || abd.interval-sub <= abd.checkInterval/2 {
2020-12-21 17:22:45 +08:00
return true
}
2024-03-10 15:39:05 +08:00
2020-12-21 17:22:45 +08:00
return false
}
2024-03-10 15:39:05 +08:00
func (abd *ArchiveByDate) NextLogFilePath(l *StarLogger, oldpath string, info os.FileInfo) string {
var newName string
2020-12-21 17:22:45 +08:00
dir := filepath.Dir(oldpath)
2024-03-10 15:39:05 +08:00
if !abd.changeArchiveName {
2025-04-28 13:16:36 +08:00
base := filepath.Base(abd.baseFileStyle)
newName = base[:len(base)-len(filepath.Ext(base))] + time.Now().Format(abd.archiveStyle)
2024-03-10 15:39:05 +08:00
} else {
newName = abd.baseFileStyle
}
return filepath.Join(dir, newName)
}
func (abd *ArchiveByDate) ArchiveLogFilePath(l *StarLogger, oldpath string, info os.FileInfo) string {
var newName string
dir := filepath.Dir(oldpath)
if abd.changeArchiveName {
2025-04-28 13:16:36 +08:00
base := filepath.Base(abd.baseFileStyle)
newName = base[:len(base)-len(filepath.Ext(base))] + time.Now().Format(abd.archiveStyle)
2024-03-10 15:39:05 +08:00
} else {
newName = abd.baseFileStyle
}
2020-12-21 17:22:45 +08:00
return filepath.Join(dir, newName)
}
func (abd *ArchiveByDate) Interval() int64 {
return abd.checkInterval
}
2024-03-10 15:39:05 +08:00
func (abd *ArchiveByDate) HookBeforArchive() func(*StarLogger, string, string, os.FileInfo) error {
2020-12-21 17:22:45 +08:00
2024-03-10 15:39:05 +08:00
return abd.hookBefore
2020-12-21 17:22:45 +08:00
}
2024-03-10 15:39:05 +08:00
func (abd *ArchiveByDate) HookAfterArchive() func(*StarLogger, string, string, os.FileInfo) error {
return func(logger *StarLogger, s string, s2 string, info os.FileInfo) error {
abd.lastSwitchTime = time.Now()
if abd.hookAfter != nil {
return abd.hookAfter(logger, s, s2, info)
}
return nil
}
2020-12-21 17:22:45 +08:00
}
2025-04-28 13:16:36 +08:00
func (abd *ArchiveByDate) DoArchive() func(*StarLogger, string, string, os.FileInfo) error {
return nil
}
2024-03-10 15:39:05 +08:00
func (abd *ArchiveByDate) SetHookBeforArchive(f func(*StarLogger, string, string, os.FileInfo) error) {
abd.hookBefore = f
2020-12-21 17:22:45 +08:00
}
2024-03-10 15:39:05 +08:00
func (abd *ArchiveByDate) SetHookAfterArchive(f func(*StarLogger, string, string, os.FileInfo) error) {
2020-12-21 17:22:45 +08:00
abd.hookAfter = f
}
2024-03-10 15:39:05 +08:00
func NewArchiveByDate(archInterval int64, checkInterval int64, baseFileName string, archiveFileName string, changeArchiveName bool, hookbefore func(*StarLogger, string, string, os.FileInfo) error, hookafter func(*StarLogger, string, string, os.FileInfo) error) *ArchiveByDate {
2020-12-21 17:22:45 +08:00
return &ArchiveByDate{
2024-03-10 15:39:05 +08:00
interval: archInterval,
checkInterval: checkInterval,
changeArchiveName: changeArchiveName,
baseFileStyle: baseFileName,
archiveStyle: archiveFileName,
hookBefore: hookbefore,
hookAfter: hookafter,
2020-12-21 17:22:45 +08:00
}
}
type ArchiveBySize struct {
2024-03-10 15:39:05 +08:00
size int64
checkInterval int64
changeArchiveName bool
baseFileStyle string
archiveStyle string
hookBefore func(*StarLogger, string, string, os.FileInfo) error
hookAfter func(*StarLogger, string, string, os.FileInfo) error
2020-12-21 17:22:45 +08:00
}
2024-03-10 15:39:05 +08:00
func (abd *ArchiveBySize) ShouldArchiveNow(l *StarLogger, fullpath string, info os.FileInfo) bool {
2020-12-21 17:22:45 +08:00
if info.Size() > abd.size {
return true
}
return false
}
2024-03-10 15:39:05 +08:00
func (abd *ArchiveBySize) NextLogFilePath(l *StarLogger, oldpath string, info os.FileInfo) string {
var newName string
dir := filepath.Dir(oldpath)
if !abd.changeArchiveName {
2025-04-28 13:16:36 +08:00
base := filepath.Base(abd.baseFileStyle)
newName = base[:len(base)-len(filepath.Ext(base))] + time.Now().Format(abd.archiveStyle)
2024-03-10 15:39:05 +08:00
} else {
newName = abd.baseFileStyle
}
return filepath.Join(dir, newName)
}
func (abd *ArchiveBySize) ArchiveLogFilePath(l *StarLogger, oldpath string, info os.FileInfo) string {
var newName string
2020-12-21 17:22:45 +08:00
dir := filepath.Dir(oldpath)
2024-03-10 15:39:05 +08:00
if abd.changeArchiveName {
2025-04-28 13:16:36 +08:00
base := filepath.Base(abd.baseFileStyle)
newName = base[:len(base)-len(filepath.Ext(base))] + time.Now().Format(abd.archiveStyle)
2024-03-10 15:39:05 +08:00
} else {
newName = abd.baseFileStyle
}
2020-12-21 17:22:45 +08:00
return filepath.Join(dir, newName)
}
func (abd *ArchiveBySize) Interval() int64 {
return abd.checkInterval
}
2024-03-10 15:39:05 +08:00
func (abd *ArchiveBySize) HookBeforArchive() func(*StarLogger, string, string, os.FileInfo) error {
return abd.hookBefore
2020-12-21 17:22:45 +08:00
}
2024-03-10 15:39:05 +08:00
func (abd *ArchiveBySize) HookAfterArchive() func(*StarLogger, string, string, os.FileInfo) error {
2020-12-21 17:22:45 +08:00
return abd.hookAfter
}
2024-03-10 15:39:05 +08:00
func (abd *ArchiveBySize) SetHookBeforArchive(f func(*StarLogger, string, string, os.FileInfo) error) {
abd.hookBefore = f
2020-12-21 17:22:45 +08:00
}
2024-03-10 15:39:05 +08:00
func (abd *ArchiveBySize) SetHookAfterArchive(f func(*StarLogger, string, string, os.FileInfo) error) {
2020-12-21 17:22:45 +08:00
abd.hookAfter = f
}
2025-04-28 13:16:36 +08:00
func (abd *ArchiveBySize) DoArchive() func(*StarLogger, string, string, os.FileInfo) error {
return nil
}
2024-03-10 15:39:05 +08:00
func NewArchiveBySize(size int64, checkInterval int64, baseFileStyle, archiveFileStyle string, changeArchiveFileName bool, hookbefore func(*StarLogger, string, string, os.FileInfo) error, hookafter func(*StarLogger, string, string, os.FileInfo) error) *ArchiveBySize {
2020-12-21 17:22:45 +08:00
return &ArchiveBySize{
2024-03-10 15:39:05 +08:00
size: size,
checkInterval: checkInterval,
baseFileStyle: baseFileStyle,
archiveStyle: archiveFileStyle,
hookBefore: hookbefore,
hookAfter: hookafter,
changeArchiveName: changeArchiveFileName,
}
}
type ArchiveByDateSize struct {
interval int64
size int64
checkInterval int64
changeArchiveName bool
lastSwitchTime time.Time
baseFileStyle string
archiveStyle string
hookBefore func(*StarLogger, string, string, os.FileInfo) error
hookAfter func(*StarLogger, string, string, os.FileInfo) error
}
func (abd *ArchiveByDateSize) ShouldArchiveNow(l *StarLogger, fullpath string, info os.FileInfo) bool {
if abd.lastSwitchTime.IsZero() {
abd.lastSwitchTime = GetFileCreationTime(info)
}
if info.Size() > abd.size {
return true
}
sub := time.Now().Unix() - abd.lastSwitchTime.Unix()
if sub >= abd.interval || abd.interval-sub <= abd.checkInterval/2 {
return true
}
return false
}
func (abd *ArchiveByDateSize) NextLogFilePath(l *StarLogger, oldpath string, info os.FileInfo) string {
var newName string
dir := filepath.Dir(oldpath)
if !abd.changeArchiveName {
2025-04-28 13:16:36 +08:00
base := filepath.Base(abd.baseFileStyle)
newName = base[:len(base)-len(filepath.Ext(base))] + time.Now().Format(abd.archiveStyle)
2024-03-10 15:39:05 +08:00
} else {
newName = abd.baseFileStyle
}
return filepath.Join(dir, newName)
}
func (abd *ArchiveByDateSize) ArchiveLogFilePath(l *StarLogger, oldpath string, info os.FileInfo) string {
var newName string
dir := filepath.Dir(oldpath)
if abd.changeArchiveName {
2025-04-28 13:16:36 +08:00
base := filepath.Base(abd.baseFileStyle)
newName = base[:len(base)-len(filepath.Ext(base))] + time.Now().Format(abd.archiveStyle)
2024-03-10 15:39:05 +08:00
} else {
newName = abd.baseFileStyle
}
return filepath.Join(dir, newName)
}
func (abd *ArchiveByDateSize) Interval() int64 {
return abd.checkInterval
}
func (abd *ArchiveByDateSize) HookBeforArchive() func(*StarLogger, string, string, os.FileInfo) error {
return abd.hookBefore
}
func (abd *ArchiveByDateSize) HookAfterArchive() func(*StarLogger, string, string, os.FileInfo) error {
return func(logger *StarLogger, s string, s2 string, info os.FileInfo) error {
abd.lastSwitchTime = time.Now()
if abd.hookAfter != nil {
return abd.hookAfter(logger, s, s2, info)
}
return nil
}
}
func (abd *ArchiveByDateSize) SetHookBeforArchive(f func(*StarLogger, string, string, os.FileInfo) error) {
abd.hookBefore = f
}
func (abd *ArchiveByDateSize) SetHookAfterArchive(f func(*StarLogger, string, string, os.FileInfo) error) {
abd.hookAfter = f
}
2025-04-28 13:16:36 +08:00
func (abd *ArchiveByDateSize) DoArchive() func(*StarLogger, string, string, os.FileInfo) error {
return nil
}
2024-03-10 15:39:05 +08:00
func NewArchiveByDateSize(size int64, interval int64, checkInterval int64, baseFileStyle, archiveFileStyle string, changeArchiveFileName bool, hookbefore func(*StarLogger, string, string, os.FileInfo) error, hookafter func(*StarLogger, string, string, os.FileInfo) error) *ArchiveByDateSize {
return &ArchiveByDateSize{
size: size,
interval: interval,
checkInterval: checkInterval,
baseFileStyle: baseFileStyle,
archiveStyle: archiveFileStyle,
hookBefore: hookbefore,
hookAfter: hookafter,
changeArchiveName: changeArchiveFileName,
2020-12-21 17:22:45 +08:00
}
}