2020-12-21 17:22:45 +08:00
|
|
|
package starlog
|
|
|
|
|
|
|
|
|
|
import (
|
2026-03-19 16:37:57 +08:00
|
|
|
"context"
|
2020-12-21 17:22:45 +08:00
|
|
|
"errors"
|
|
|
|
|
"os"
|
|
|
|
|
"path/filepath"
|
|
|
|
|
"time"
|
|
|
|
|
|
2026-03-19 16:37:57 +08:00
|
|
|
"b612.me/starlog/internal/archivex"
|
|
|
|
|
)
|
2020-12-22 11:07:20 +08:00
|
|
|
|
2026-03-19 16:37:57 +08:00
|
|
|
var archiveStore = archivex.NewStore()
|
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
|
2026-03-19 16:37:57 +08:00
|
|
|
// Deprecated: use HookBeforeArchive on concrete implementations.
|
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
|
|
|
}
|
|
|
|
|
|
2026-03-19 16:37:57 +08:00
|
|
|
type archiveStrategy struct {
|
|
|
|
|
interval int64
|
|
|
|
|
shouldRotate func(string, os.FileInfo, *Entry) bool
|
|
|
|
|
nextLogPath func(string, os.FileInfo, time.Time) string
|
|
|
|
|
archivePath func(string, os.FileInfo, time.Time) string
|
|
|
|
|
beforeHook func(*StarLogger, string, string, os.FileInfo) error
|
|
|
|
|
afterHook func(*StarLogger, string, string, os.FileInfo) error
|
|
|
|
|
doArchive func(*StarLogger, string, string, os.FileInfo) error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type archiveBeforeHookProvider interface {
|
|
|
|
|
HookBeforeArchive() func(*StarLogger, string, string, os.FileInfo) error
|
2020-12-21 17:22:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
2026-03-19 16:37:57 +08:00
|
|
|
if current, ok := archiveStore.GetFile(logger.logcore.id); ok {
|
2020-12-21 17:22:45 +08:00
|
|
|
logger.SetSwitching(true)
|
2026-03-19 16:37:57 +08:00
|
|
|
err := current.Pointer.Close()
|
2020-12-21 17:22:45 +08:00
|
|
|
if err != nil {
|
2026-03-19 16:37:57 +08:00
|
|
|
logger.SetWriter(nil)
|
2020-12-21 17:22:45 +08:00
|
|
|
logger.SetSwitching(false)
|
|
|
|
|
return err
|
|
|
|
|
}
|
2026-03-19 16:37:57 +08:00
|
|
|
err = archiveStore.DeleteFile(logger.logcore.id)
|
2020-12-21 17:22:45 +08:00
|
|
|
if err != nil {
|
2026-03-19 16:37:57 +08:00
|
|
|
logger.SetWriter(nil)
|
2020-12-21 17:22:45 +08:00
|
|
|
logger.SetSwitching(false)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-19 16:37:57 +08:00
|
|
|
err = archiveStore.SetFile(logger.logcore.id, archivex.FileRecord{
|
|
|
|
|
FullPath: fullpath,
|
|
|
|
|
Pointer: fp,
|
2020-12-21 17:22:45 +08:00
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
fp.Close()
|
2026-03-19 16:37:57 +08:00
|
|
|
logger.SetWriter(nil)
|
2020-12-21 17:22:45 +08:00
|
|
|
logger.SetSwitching(false)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
logger.SetSwitching(true)
|
2026-03-19 16:37:57 +08:00
|
|
|
logger.SetWriter(fp)
|
2020-12-21 17:22:45 +08:00
|
|
|
logger.SetSwitching(false)
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-19 16:37:57 +08:00
|
|
|
func CloseLogFileWithSwitching(logger *StarLogger) error {
|
|
|
|
|
if current, ok := archiveStore.GetFile(logger.logcore.id); ok {
|
2020-12-21 17:22:45 +08:00
|
|
|
logger.SetSwitching(true)
|
2026-03-19 16:37:57 +08:00
|
|
|
err := current.Pointer.Close()
|
2020-12-21 17:22:45 +08:00
|
|
|
if err != nil {
|
2026-03-19 16:37:57 +08:00
|
|
|
logger.SetWriter(nil)
|
2020-12-21 17:22:45 +08:00
|
|
|
return err
|
|
|
|
|
}
|
2026-03-19 16:37:57 +08:00
|
|
|
err = archiveStore.DeleteFile(logger.logcore.id)
|
2020-12-21 17:22:45 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2026-03-19 16:37:57 +08:00
|
|
|
logger.logcore.mu.Lock()
|
|
|
|
|
if logger.logcore.output == current.Pointer {
|
|
|
|
|
logger.logcore.output = nil
|
|
|
|
|
}
|
|
|
|
|
logger.logcore.mu.Unlock()
|
2020-12-21 17:22:45 +08:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-19 16:37:57 +08:00
|
|
|
func CloseLogFile(logger *StarLogger) error {
|
2020-12-22 11:07:20 +08:00
|
|
|
defer logger.SetSwitching(false)
|
2026-03-19 16:37:57 +08:00
|
|
|
return CloseLogFileWithSwitching(logger)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Deprecated: use CloseLogFileWithSwitching.
|
|
|
|
|
func CloseWithSwitching(logger *StarLogger) error {
|
|
|
|
|
return CloseLogFileWithSwitching(logger)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Deprecated: use (*StarLogger).Close or CloseLogFile.
|
|
|
|
|
func Close(logger *StarLogger) error {
|
|
|
|
|
return CloseLogFile(logger)
|
2020-12-22 11:07:20 +08:00
|
|
|
}
|
|
|
|
|
|
2020-12-21 17:22:45 +08:00
|
|
|
func GetLogFileInfo(logger *StarLogger) (os.FileInfo, error) {
|
2026-03-19 16:37:57 +08:00
|
|
|
if current, ok := archiveStore.GetFile(logger.logcore.id); ok {
|
|
|
|
|
return current.Pointer.Stat()
|
2020-12-21 17:22:45 +08:00
|
|
|
}
|
|
|
|
|
return nil, errors.New("logger don't have a register logfile")
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-19 16:37:57 +08:00
|
|
|
func resolveBeforeHook(arch Archive) func(*StarLogger, string, string, os.FileInfo) error {
|
|
|
|
|
if arch == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
if hookProvider, ok := arch.(archiveBeforeHookProvider); ok {
|
|
|
|
|
return hookProvider.HookBeforeArchive()
|
|
|
|
|
}
|
|
|
|
|
return arch.HookBeforArchive()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func startArchiveWithStrategy(logger *StarLogger, strategy archiveStrategy) error {
|
|
|
|
|
archiveKey := "arch" + logger.logcore.id
|
|
|
|
|
if _, ok := archiveStore.GetRunner(archiveKey); ok {
|
2020-12-21 17:22:45 +08:00
|
|
|
return errors.New("already running")
|
|
|
|
|
}
|
2026-03-19 16:37:57 +08:00
|
|
|
interval := strategy.interval
|
|
|
|
|
if interval <= 0 {
|
|
|
|
|
interval = 1
|
|
|
|
|
}
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
|
runner := &archivex.Runner{
|
|
|
|
|
Cancel: cancel,
|
|
|
|
|
Done: make(chan struct{}),
|
|
|
|
|
}
|
|
|
|
|
if err := archiveStore.SetRunner(archiveKey, runner); err != nil {
|
|
|
|
|
cancel()
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
go func(ctx context.Context, runner *archivex.Runner, logger *StarLogger) {
|
|
|
|
|
defer close(runner.Done)
|
|
|
|
|
defer archiveStore.DeleteRunner(archiveKey)
|
|
|
|
|
ticker := time.NewTicker(time.Second * time.Duration(interval))
|
|
|
|
|
defer ticker.Stop()
|
2020-12-21 17:22:45 +08:00
|
|
|
for {
|
|
|
|
|
select {
|
2026-03-19 16:37:57 +08:00
|
|
|
case <-ctx.Done():
|
2020-12-21 17:22:45 +08:00
|
|
|
return
|
2026-03-19 16:37:57 +08:00
|
|
|
case <-ticker.C:
|
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
|
|
|
|
|
}
|
2026-03-19 16:37:57 +08:00
|
|
|
current, ok := archiveStore.GetFile(logger.logcore.id)
|
|
|
|
|
if !ok {
|
2020-12-21 17:22:45 +08:00
|
|
|
logger.Errorf("cannot get log core info from the map:no such keys\n")
|
|
|
|
|
continue
|
|
|
|
|
}
|
2026-03-19 16:37:57 +08:00
|
|
|
fullpath := current.FullPath
|
|
|
|
|
now := time.Now()
|
|
|
|
|
entry := &Entry{
|
|
|
|
|
Time: now,
|
|
|
|
|
LoggerName: logger.GetName(),
|
|
|
|
|
}
|
|
|
|
|
if strategy.shouldRotate == nil || !strategy.shouldRotate(fullpath, fileinfo, entry) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
newLogPath := fullpath
|
|
|
|
|
if strategy.nextLogPath != nil {
|
|
|
|
|
newLogPath = strategy.nextLogPath(fullpath, fileinfo, now)
|
|
|
|
|
}
|
|
|
|
|
if newLogPath == "" {
|
|
|
|
|
newLogPath = fullpath
|
|
|
|
|
}
|
|
|
|
|
archiveLogPath := fullpath
|
|
|
|
|
if strategy.archivePath != nil {
|
|
|
|
|
archiveLogPath = strategy.archivePath(fullpath, fileinfo, now)
|
|
|
|
|
}
|
|
|
|
|
if archiveLogPath == "" {
|
|
|
|
|
logger.Errorf("archive path cannot be empty\n")
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if strategy.doArchive == nil && archiveLogPath == fullpath {
|
|
|
|
|
logger.Errorf("archive path equals current path, skip rotate\n")
|
2020-12-21 17:22:45 +08:00
|
|
|
continue
|
|
|
|
|
}
|
2026-03-19 16:37:57 +08:00
|
|
|
if strategy.beforeHook != nil {
|
|
|
|
|
if err := strategy.beforeHook(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
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-03-19 16:37:57 +08:00
|
|
|
err = CloseLogFileWithSwitching(logger)
|
2024-03-10 15:39:05 +08:00
|
|
|
if err != nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2026-03-19 16:37:57 +08:00
|
|
|
if strategy.doArchive == nil {
|
2025-04-28 13:16:36 +08:00
|
|
|
err = os.Rename(fullpath, archiveLogPath)
|
|
|
|
|
if err != nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2026-03-19 16:37:57 +08:00
|
|
|
err = strategy.doArchive(logger, fullpath, archiveLogPath, fileinfo)
|
2025-04-28 13:16:36 +08:00
|
|
|
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
|
|
|
|
|
}
|
2026-03-19 16:37:57 +08:00
|
|
|
if strategy.afterHook != nil {
|
|
|
|
|
if err := strategy.afterHook(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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-03-19 16:37:57 +08:00
|
|
|
}(ctx, runner, logger)
|
2020-12-21 17:22:45 +08:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-19 16:37:57 +08:00
|
|
|
func buildRotateStrategy(policy RotatePolicy, checkInterval int64) archiveStrategy {
|
|
|
|
|
return archiveStrategy{
|
|
|
|
|
interval: checkInterval,
|
|
|
|
|
shouldRotate: func(fullpath string, info os.FileInfo, entry *Entry) bool {
|
|
|
|
|
return policy.ShouldRotate(info, entry)
|
|
|
|
|
},
|
|
|
|
|
nextLogPath: func(oldpath string, info os.FileInfo, now time.Time) string {
|
|
|
|
|
return oldpath
|
|
|
|
|
},
|
|
|
|
|
archivePath: func(oldpath string, info os.FileInfo, now time.Time) string {
|
|
|
|
|
return resolveRotateArchivePath(policy, oldpath, now)
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func buildRotateArchiveStrategy(archive *RotatePolicyArchive) archiveStrategy {
|
|
|
|
|
strategy := buildRotateStrategy(archive.policy, archive.checkInterval)
|
|
|
|
|
strategy.beforeHook = archive.HookBeforeArchive()
|
|
|
|
|
strategy.afterHook = archive.HookAfterArchive()
|
|
|
|
|
if archive.DoArchive() != nil {
|
|
|
|
|
strategy.doArchive = archive.DoArchive()
|
|
|
|
|
}
|
|
|
|
|
if archive.Interval() > 0 {
|
|
|
|
|
strategy.interval = archive.Interval()
|
|
|
|
|
}
|
|
|
|
|
return strategy
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func buildLegacyArchiveStrategy(logger *StarLogger, arch Archive) archiveStrategy {
|
|
|
|
|
return archiveStrategy{
|
|
|
|
|
interval: arch.Interval(),
|
|
|
|
|
shouldRotate: func(fullpath string, info os.FileInfo, entry *Entry) bool {
|
|
|
|
|
return arch.ShouldArchiveNow(logger, fullpath, info)
|
|
|
|
|
},
|
|
|
|
|
nextLogPath: func(oldpath string, info os.FileInfo, now time.Time) string {
|
|
|
|
|
return arch.NextLogFilePath(logger, oldpath, info)
|
|
|
|
|
},
|
|
|
|
|
archivePath: func(oldpath string, info os.FileInfo, now time.Time) string {
|
|
|
|
|
return arch.ArchiveLogFilePath(logger, oldpath, info)
|
|
|
|
|
},
|
|
|
|
|
beforeHook: resolveBeforeHook(arch),
|
|
|
|
|
afterHook: arch.HookAfterArchive(),
|
|
|
|
|
doArchive: arch.DoArchive(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func StartRotatePolicy(logger *StarLogger, policy RotatePolicy, checkInterval int64) error {
|
|
|
|
|
if policy == nil {
|
|
|
|
|
return errors.New("rotate policy is nil")
|
|
|
|
|
}
|
|
|
|
|
return startArchiveWithStrategy(logger, buildRotateStrategy(policy, checkInterval))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Deprecated: prefer StartRotatePolicy or StartManagedRotatePolicy.
|
|
|
|
|
func StartArchive(logger *StarLogger, arch Archive) error {
|
|
|
|
|
if arch == nil {
|
|
|
|
|
return errors.New("archive is nil")
|
|
|
|
|
}
|
|
|
|
|
if rotateArchive, ok := arch.(*RotatePolicyArchive); ok && rotateArchive != nil && rotateArchive.policy != nil {
|
|
|
|
|
return startArchiveWithStrategy(logger, buildRotateArchiveStrategy(rotateArchive))
|
2020-12-21 17:22:45 +08:00
|
|
|
}
|
2026-03-19 16:37:57 +08:00
|
|
|
return startArchiveWithStrategy(logger, buildLegacyArchiveStrategy(logger, arch))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func IsArchiveRun(logger *StarLogger) bool {
|
|
|
|
|
_, ok := archiveStore.GetRunner("arch" + logger.logcore.id)
|
|
|
|
|
return ok
|
2020-12-21 17:22:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func StopArchive(logger *StarLogger) {
|
2026-03-19 16:37:57 +08:00
|
|
|
archiveKey := "arch" + logger.logcore.id
|
|
|
|
|
runner, ok := archiveStore.GetRunner(archiveKey)
|
|
|
|
|
if !ok || runner == nil {
|
2020-12-21 17:22:45 +08:00
|
|
|
return
|
|
|
|
|
}
|
2026-03-19 16:37:57 +08:00
|
|
|
runner.Cancel()
|
|
|
|
|
<-runner.Done
|
|
|
|
|
_ = archiveStore.DeleteRunner(archiveKey)
|
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 {
|
2026-03-19 16:37:57 +08:00
|
|
|
return abd.HookBeforeArchive()
|
|
|
|
|
}
|
2020-12-21 17:22:45 +08:00
|
|
|
|
2026-03-19 16:37:57 +08:00
|
|
|
func (abd *ArchiveByDate) HookBeforeArchive() func(*StarLogger, string, string, os.FileInfo) error {
|
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) {
|
2026-03-19 16:37:57 +08:00
|
|
|
abd.SetHookBeforeArchive(f)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (abd *ArchiveByDate) SetHookBeforeArchive(f func(*StarLogger, string, string, os.FileInfo) error) {
|
2024-03-10 15:39:05 +08:00
|
|
|
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 {
|
2026-03-19 16:37:57 +08:00
|
|
|
return abd.HookBeforeArchive()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (abd *ArchiveBySize) HookBeforeArchive() func(*StarLogger, string, string, os.FileInfo) error {
|
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 *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) {
|
2026-03-19 16:37:57 +08:00
|
|
|
abd.SetHookBeforeArchive(f)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (abd *ArchiveBySize) SetHookBeforeArchive(f func(*StarLogger, string, string, os.FileInfo) error) {
|
2024-03-10 15:39:05 +08:00
|
|
|
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 {
|
2026-03-19 16:37:57 +08:00
|
|
|
return abd.HookBeforeArchive()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (abd *ArchiveByDateSize) HookBeforeArchive() func(*StarLogger, string, string, os.FileInfo) error {
|
2024-03-10 15:39:05 +08:00
|
|
|
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) {
|
2026-03-19 16:37:57 +08:00
|
|
|
abd.SetHookBeforeArchive(f)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (abd *ArchiveByDateSize) SetHookBeforeArchive(f func(*StarLogger, string, string, os.FileInfo) error) {
|
2024-03-10 15:39:05 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
}
|