starlog/lifecycle.go

123 lines
2.8 KiB
Go
Raw Normal View History

2026-03-19 16:37:57 +08:00
package starlog
import (
"context"
"fmt"
"io"
)
type sinkSyncer interface {
Sync() error
}
type writerSyncer interface {
Sync() error
}
type contextualCloser interface {
CloseWithContext(context.Context) error
}
2026-03-19 16:37:57 +08:00
func mergeLifecycleError(current error, next error) error {
if next == nil {
return current
}
if current == nil {
return next
}
return fmt.Errorf("%v; %w", current, next)
}
func WaitAsyncDrain(ctx context.Context) error {
return defaultAsyncRuntime().WaitDrain(ctx)
2026-03-19 16:37:57 +08:00
}
func (logger *StarLogger) Flush() error {
if logger == nil || logger.logcore == nil {
return nil
}
logger.logcore.mu.Lock()
previousSwitching := logger.logcore.switching
logger.logcore.switching = false
logger.logcore.writePendingLocked()
logger.logcore.switching = previousSwitching
logger.logcore.mu.Unlock()
return nil
}
func (logger *StarLogger) Sync() error {
if logger == nil || logger.logcore == nil {
return nil
}
if err := logger.Flush(); err != nil {
return err
}
logger.logcore.mu.Lock()
sink := logger.logcore.sink
writer := logger.logcore.output
logger.logcore.mu.Unlock()
var err error
if sink != nil {
if syncer, ok := sink.(sinkSyncer); ok {
err = mergeLifecycleError(err, syncer.Sync())
}
return err
}
if writer != nil {
if syncer, ok := writer.(writerSyncer); ok {
err = mergeLifecycleError(err, syncer.Sync())
}
}
return err
}
// Close flushes/syncs and closes archive-managed file/sink/writer resources.
// It does not wait for async handler queue; use Shutdown for graceful app exit.
func (logger *StarLogger) Close() error {
if logger == nil || logger.logcore == nil {
return nil
}
var err error
StopArchive(logger)
err = mergeLifecycleError(err, logger.Sync())
err = mergeLifecycleError(err, CloseLogFile(logger))
logger.logcore.mu.Lock()
sink := logger.logcore.sink
writer := logger.logcore.output
entryHandler := logger.logcore.entryHandler
logger.logcore.mu.Unlock()
if sink != nil {
err = mergeLifecycleError(err, sink.Close())
} else if writer != nil {
if closer, ok := writer.(io.Closer); ok {
err = mergeLifecycleError(err, closer.Close())
}
}
if entryHandler != nil {
if closer, ok := entryHandler.(contextualCloser); ok {
err = mergeLifecycleError(err, closer.CloseWithContext(withAsyncRuntime(context.Background(), logger.asyncRuntime())))
} else if closer, ok := entryHandler.(interface{ Close() error }); ok {
2026-03-19 16:37:57 +08:00
err = mergeLifecycleError(err, closer.Close())
}
}
logger.StopWrite()
return err
}
func (logger *StarLogger) Shutdown(ctx context.Context) error {
if logger == nil || logger.logcore == nil {
return nil
}
var err error
err = mergeLifecycleError(err, logger.Flush())
err = mergeLifecycleError(err, logger.asyncRuntime().WaitDrain(ctx))
logger.asyncRuntime().Stop()
2026-03-19 16:37:57 +08:00
err = mergeLifecycleError(err, logger.Close())
return err
}