Avoid opening log output before start &
Replace tracing logs with task monitor
This commit is contained in:
137
log/default.go
137
log/default.go
@@ -1,137 +0,0 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
)
|
||||
|
||||
var _ Factory = (*simpleFactory)(nil)
|
||||
|
||||
type simpleFactory struct {
|
||||
formatter Formatter
|
||||
platformFormatter Formatter
|
||||
writer io.Writer
|
||||
platformWriter PlatformWriter
|
||||
level Level
|
||||
}
|
||||
|
||||
func NewFactory(formatter Formatter, writer io.Writer, platformWriter PlatformWriter) Factory {
|
||||
return &simpleFactory{
|
||||
formatter: formatter,
|
||||
platformFormatter: Formatter{
|
||||
BaseTime: formatter.BaseTime,
|
||||
DisableColors: C.IsDarwin || C.IsIos,
|
||||
DisableLineBreak: true,
|
||||
},
|
||||
writer: writer,
|
||||
platformWriter: platformWriter,
|
||||
level: LevelTrace,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *simpleFactory) Level() Level {
|
||||
return f.level
|
||||
}
|
||||
|
||||
func (f *simpleFactory) SetLevel(level Level) {
|
||||
f.level = level
|
||||
}
|
||||
|
||||
func (f *simpleFactory) Logger() ContextLogger {
|
||||
return f.NewLogger("")
|
||||
}
|
||||
|
||||
func (f *simpleFactory) NewLogger(tag string) ContextLogger {
|
||||
return &simpleLogger{f, tag}
|
||||
}
|
||||
|
||||
func (f *simpleFactory) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ ContextLogger = (*simpleLogger)(nil)
|
||||
|
||||
type simpleLogger struct {
|
||||
*simpleFactory
|
||||
tag string
|
||||
}
|
||||
|
||||
func (l *simpleLogger) Log(ctx context.Context, level Level, args []any) {
|
||||
level = OverrideLevelFromContext(level, ctx)
|
||||
if level > l.level {
|
||||
return
|
||||
}
|
||||
nowTime := time.Now()
|
||||
message := l.formatter.Format(ctx, level, l.tag, F.ToString(args...), nowTime)
|
||||
if level == LevelPanic {
|
||||
panic(message)
|
||||
}
|
||||
l.writer.Write([]byte(message))
|
||||
if level == LevelFatal {
|
||||
os.Exit(1)
|
||||
}
|
||||
if l.platformWriter != nil {
|
||||
l.platformWriter.WriteMessage(level, l.platformFormatter.Format(ctx, level, l.tag, F.ToString(args...), nowTime))
|
||||
}
|
||||
}
|
||||
|
||||
func (l *simpleLogger) Trace(args ...any) {
|
||||
l.TraceContext(context.Background(), args...)
|
||||
}
|
||||
|
||||
func (l *simpleLogger) Debug(args ...any) {
|
||||
l.DebugContext(context.Background(), args...)
|
||||
}
|
||||
|
||||
func (l *simpleLogger) Info(args ...any) {
|
||||
l.InfoContext(context.Background(), args...)
|
||||
}
|
||||
|
||||
func (l *simpleLogger) Warn(args ...any) {
|
||||
l.WarnContext(context.Background(), args...)
|
||||
}
|
||||
|
||||
func (l *simpleLogger) Error(args ...any) {
|
||||
l.ErrorContext(context.Background(), args...)
|
||||
}
|
||||
|
||||
func (l *simpleLogger) Fatal(args ...any) {
|
||||
l.FatalContext(context.Background(), args...)
|
||||
}
|
||||
|
||||
func (l *simpleLogger) Panic(args ...any) {
|
||||
l.PanicContext(context.Background(), args...)
|
||||
}
|
||||
|
||||
func (l *simpleLogger) TraceContext(ctx context.Context, args ...any) {
|
||||
l.Log(ctx, LevelTrace, args)
|
||||
}
|
||||
|
||||
func (l *simpleLogger) DebugContext(ctx context.Context, args ...any) {
|
||||
l.Log(ctx, LevelDebug, args)
|
||||
}
|
||||
|
||||
func (l *simpleLogger) InfoContext(ctx context.Context, args ...any) {
|
||||
l.Log(ctx, LevelInfo, args)
|
||||
}
|
||||
|
||||
func (l *simpleLogger) WarnContext(ctx context.Context, args ...any) {
|
||||
l.Log(ctx, LevelWarn, args)
|
||||
}
|
||||
|
||||
func (l *simpleLogger) ErrorContext(ctx context.Context, args ...any) {
|
||||
l.Log(ctx, LevelError, args)
|
||||
}
|
||||
|
||||
func (l *simpleLogger) FatalContext(ctx context.Context, args ...any) {
|
||||
l.Log(ctx, LevelFatal, args)
|
||||
}
|
||||
|
||||
func (l *simpleLogger) PanicContext(ctx context.Context, args ...any) {
|
||||
l.Log(ctx, LevelPanic, args)
|
||||
}
|
||||
@@ -9,7 +9,14 @@ import (
|
||||
var std ContextLogger
|
||||
|
||||
func init() {
|
||||
std = NewFactory(Formatter{BaseTime: time.Now()}, os.Stderr, nil).Logger()
|
||||
std = NewDefaultFactory(
|
||||
context.Background(),
|
||||
Formatter{BaseTime: time.Now()},
|
||||
os.Stderr,
|
||||
"",
|
||||
nil,
|
||||
false,
|
||||
).Logger()
|
||||
}
|
||||
|
||||
func StdLogger() ContextLogger {
|
||||
|
||||
@@ -11,11 +11,12 @@ type (
|
||||
)
|
||||
|
||||
type Factory interface {
|
||||
Start() error
|
||||
Close() error
|
||||
Level() Level
|
||||
SetLevel(level Level)
|
||||
Logger() ContextLogger
|
||||
NewLogger(tag string) ContextLogger
|
||||
Close() error
|
||||
}
|
||||
|
||||
type ObservableFactory interface {
|
||||
|
||||
66
log/log.go
66
log/log.go
@@ -7,35 +7,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/service/filemanager"
|
||||
)
|
||||
|
||||
type factoryWithFile struct {
|
||||
Factory
|
||||
file *os.File
|
||||
}
|
||||
|
||||
func (f *factoryWithFile) Close() error {
|
||||
return common.Close(
|
||||
f.Factory,
|
||||
common.PtrOrNil(f.file),
|
||||
)
|
||||
}
|
||||
|
||||
type observableFactoryWithFile struct {
|
||||
ObservableFactory
|
||||
file *os.File
|
||||
}
|
||||
|
||||
func (f *observableFactoryWithFile) Close() error {
|
||||
return common.Close(
|
||||
f.ObservableFactory,
|
||||
common.PtrOrNil(f.file),
|
||||
)
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
Context context.Context
|
||||
Options option.LogOptions
|
||||
@@ -52,8 +26,8 @@ func New(options Options) (Factory, error) {
|
||||
return NewNOPFactory(), nil
|
||||
}
|
||||
|
||||
var logFile *os.File
|
||||
var logWriter io.Writer
|
||||
var logFilePath string
|
||||
|
||||
switch logOptions.Output {
|
||||
case "":
|
||||
@@ -66,26 +40,23 @@ func New(options Options) (Factory, error) {
|
||||
case "stdout":
|
||||
logWriter = os.Stdout
|
||||
default:
|
||||
var err error
|
||||
logFile, err = filemanager.OpenFile(options.Context, logOptions.Output, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logWriter = logFile
|
||||
logFilePath = logOptions.Output
|
||||
}
|
||||
logFormatter := Formatter{
|
||||
BaseTime: options.BaseTime,
|
||||
DisableColors: logOptions.DisableColor || logFile != nil,
|
||||
DisableTimestamp: !logOptions.Timestamp && logFile != nil,
|
||||
DisableColors: logOptions.DisableColor || logFilePath != "",
|
||||
DisableTimestamp: !logOptions.Timestamp && logFilePath != "",
|
||||
FullTimestamp: logOptions.Timestamp,
|
||||
TimestampFormat: "-0700 2006-01-02 15:04:05",
|
||||
}
|
||||
var factory Factory
|
||||
if options.Observable {
|
||||
factory = NewObservableFactory(logFormatter, logWriter, options.PlatformWriter)
|
||||
} else {
|
||||
factory = NewFactory(logFormatter, logWriter, options.PlatformWriter)
|
||||
}
|
||||
factory := NewDefaultFactory(
|
||||
options.Context,
|
||||
logFormatter,
|
||||
logWriter,
|
||||
logFilePath,
|
||||
options.PlatformWriter,
|
||||
options.Observable,
|
||||
)
|
||||
if logOptions.Level != "" {
|
||||
logLevel, err := ParseLevel(logOptions.Level)
|
||||
if err != nil {
|
||||
@@ -95,18 +66,5 @@ func New(options Options) (Factory, error) {
|
||||
} else {
|
||||
factory.SetLevel(LevelTrace)
|
||||
}
|
||||
if logFile != nil {
|
||||
if options.Observable {
|
||||
factory = &observableFactoryWithFile{
|
||||
ObservableFactory: factory.(ObservableFactory),
|
||||
file: logFile,
|
||||
}
|
||||
} else {
|
||||
factory = &factoryWithFile{
|
||||
Factory: factory,
|
||||
file: logFile,
|
||||
}
|
||||
}
|
||||
}
|
||||
return factory, nil
|
||||
}
|
||||
|
||||
12
log/nop.go
12
log/nop.go
@@ -15,6 +15,14 @@ func NewNOPFactory() ObservableFactory {
|
||||
return (*nopFactory)(nil)
|
||||
}
|
||||
|
||||
func (f *nopFactory) Start() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *nopFactory) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *nopFactory) Level() Level {
|
||||
return LevelTrace
|
||||
}
|
||||
@@ -72,10 +80,6 @@ func (f *nopFactory) FatalContext(ctx context.Context, args ...any) {
|
||||
func (f *nopFactory) PanicContext(ctx context.Context, args ...any) {
|
||||
}
|
||||
|
||||
func (f *nopFactory) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *nopFactory) Subscribe() (subscription observable.Subscription[Entry], done <-chan struct{}, err error) {
|
||||
return nil, nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
@@ -9,29 +9,44 @@ import (
|
||||
"github.com/sagernet/sing/common"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
"github.com/sagernet/sing/common/observable"
|
||||
"github.com/sagernet/sing/service/filemanager"
|
||||
)
|
||||
|
||||
var _ Factory = (*observableFactory)(nil)
|
||||
var _ Factory = (*defaultFactory)(nil)
|
||||
|
||||
type observableFactory struct {
|
||||
type defaultFactory struct {
|
||||
ctx context.Context
|
||||
formatter Formatter
|
||||
platformFormatter Formatter
|
||||
writer io.Writer
|
||||
file *os.File
|
||||
filePath string
|
||||
platformWriter PlatformWriter
|
||||
needObservable bool
|
||||
level Level
|
||||
subscriber *observable.Subscriber[Entry]
|
||||
observer *observable.Observer[Entry]
|
||||
}
|
||||
|
||||
func NewObservableFactory(formatter Formatter, writer io.Writer, platformWriter PlatformWriter) ObservableFactory {
|
||||
factory := &observableFactory{
|
||||
func NewDefaultFactory(
|
||||
ctx context.Context,
|
||||
formatter Formatter,
|
||||
writer io.Writer,
|
||||
filePath string,
|
||||
platformWriter PlatformWriter,
|
||||
needObservable bool,
|
||||
) ObservableFactory {
|
||||
factory := &defaultFactory{
|
||||
ctx: ctx,
|
||||
formatter: formatter,
|
||||
platformFormatter: Formatter{
|
||||
BaseTime: formatter.BaseTime,
|
||||
DisableLineBreak: true,
|
||||
},
|
||||
writer: writer,
|
||||
filePath: filePath,
|
||||
platformWriter: platformWriter,
|
||||
needObservable: needObservable,
|
||||
level: LevelTrace,
|
||||
subscriber: observable.NewSubscriber[Entry](128),
|
||||
}
|
||||
@@ -42,40 +57,53 @@ func NewObservableFactory(formatter Formatter, writer io.Writer, platformWriter
|
||||
return factory
|
||||
}
|
||||
|
||||
func (f *observableFactory) Level() Level {
|
||||
func (f *defaultFactory) Start() error {
|
||||
if f.filePath != "" {
|
||||
logFile, err := filemanager.OpenFile(f.ctx, f.filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.writer = logFile
|
||||
f.file = logFile
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *defaultFactory) Close() error {
|
||||
return common.Close(
|
||||
common.PtrOrNil(f.file),
|
||||
f.observer,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *defaultFactory) Level() Level {
|
||||
return f.level
|
||||
}
|
||||
|
||||
func (f *observableFactory) SetLevel(level Level) {
|
||||
func (f *defaultFactory) SetLevel(level Level) {
|
||||
f.level = level
|
||||
}
|
||||
|
||||
func (f *observableFactory) Logger() ContextLogger {
|
||||
func (f *defaultFactory) Logger() ContextLogger {
|
||||
return f.NewLogger("")
|
||||
}
|
||||
|
||||
func (f *observableFactory) NewLogger(tag string) ContextLogger {
|
||||
func (f *defaultFactory) NewLogger(tag string) ContextLogger {
|
||||
return &observableLogger{f, tag}
|
||||
}
|
||||
|
||||
func (f *observableFactory) Subscribe() (subscription observable.Subscription[Entry], done <-chan struct{}, err error) {
|
||||
func (f *defaultFactory) Subscribe() (subscription observable.Subscription[Entry], done <-chan struct{}, err error) {
|
||||
return f.observer.Subscribe()
|
||||
}
|
||||
|
||||
func (f *observableFactory) UnSubscribe(sub observable.Subscription[Entry]) {
|
||||
func (f *defaultFactory) UnSubscribe(sub observable.Subscription[Entry]) {
|
||||
f.observer.UnSubscribe(sub)
|
||||
}
|
||||
|
||||
func (f *observableFactory) Close() error {
|
||||
return common.Close(
|
||||
f.observer,
|
||||
)
|
||||
}
|
||||
|
||||
var _ ContextLogger = (*observableLogger)(nil)
|
||||
|
||||
type observableLogger struct {
|
||||
*observableFactory
|
||||
*defaultFactory
|
||||
tag string
|
||||
}
|
||||
|
||||
@@ -85,15 +113,26 @@ func (l *observableLogger) Log(ctx context.Context, level Level, args []any) {
|
||||
return
|
||||
}
|
||||
nowTime := time.Now()
|
||||
message, messageSimple := l.formatter.FormatWithSimple(ctx, level, l.tag, F.ToString(args...), nowTime)
|
||||
if level == LevelPanic {
|
||||
panic(message)
|
||||
if l.needObservable {
|
||||
message, messageSimple := l.formatter.FormatWithSimple(ctx, level, l.tag, F.ToString(args...), nowTime)
|
||||
if level == LevelPanic {
|
||||
panic(message)
|
||||
}
|
||||
l.writer.Write([]byte(message))
|
||||
if level == LevelFatal {
|
||||
os.Exit(1)
|
||||
}
|
||||
l.subscriber.Emit(Entry{level, messageSimple})
|
||||
} else {
|
||||
message := l.formatter.Format(ctx, level, l.tag, F.ToString(args...), nowTime)
|
||||
if level == LevelPanic {
|
||||
panic(message)
|
||||
}
|
||||
l.writer.Write([]byte(message))
|
||||
if level == LevelFatal {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
l.writer.Write([]byte(message))
|
||||
if level == LevelFatal {
|
||||
os.Exit(1)
|
||||
}
|
||||
l.subscriber.Emit(Entry{level, messageSimple})
|
||||
if l.platformWriter != nil {
|
||||
l.platformWriter.WriteMessage(level, l.platformFormatter.Format(ctx, level, l.tag, F.ToString(args...), nowTime))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user