github.com/sagernet/sing-box@v1.2.7/log/observable.go (about) 1 package log 2 3 import ( 4 "context" 5 "io" 6 "os" 7 "time" 8 9 C "github.com/sagernet/sing-box/constant" 10 "github.com/sagernet/sing/common" 11 F "github.com/sagernet/sing/common/format" 12 "github.com/sagernet/sing/common/observable" 13 ) 14 15 var _ Factory = (*observableFactory)(nil) 16 17 type observableFactory struct { 18 formatter Formatter 19 platformFormatter Formatter 20 writer io.Writer 21 platformWriter io.Writer 22 level Level 23 subscriber *observable.Subscriber[Entry] 24 observer *observable.Observer[Entry] 25 } 26 27 func NewObservableFactory(formatter Formatter, writer io.Writer, platformWriter io.Writer) ObservableFactory { 28 factory := &observableFactory{ 29 formatter: formatter, 30 platformFormatter: Formatter{ 31 BaseTime: formatter.BaseTime, 32 DisableColors: C.IsDarwin || C.IsIos, 33 }, 34 writer: writer, 35 platformWriter: platformWriter, 36 level: LevelTrace, 37 subscriber: observable.NewSubscriber[Entry](128), 38 } 39 factory.observer = observable.NewObserver[Entry](factory.subscriber, 64) 40 return factory 41 } 42 43 func (f *observableFactory) Level() Level { 44 return f.level 45 } 46 47 func (f *observableFactory) SetLevel(level Level) { 48 f.level = level 49 } 50 51 func (f *observableFactory) Logger() ContextLogger { 52 return f.NewLogger("") 53 } 54 55 func (f *observableFactory) NewLogger(tag string) ContextLogger { 56 return &observableLogger{f, tag} 57 } 58 59 func (f *observableFactory) Subscribe() (subscription observable.Subscription[Entry], done <-chan struct{}, err error) { 60 return f.observer.Subscribe() 61 } 62 63 func (f *observableFactory) UnSubscribe(sub observable.Subscription[Entry]) { 64 f.observer.UnSubscribe(sub) 65 } 66 67 func (f *observableFactory) Close() error { 68 return common.Close( 69 f.observer, 70 ) 71 } 72 73 var _ ContextLogger = (*observableLogger)(nil) 74 75 type observableLogger struct { 76 *observableFactory 77 tag string 78 } 79 80 func (l *observableLogger) Log(ctx context.Context, level Level, args []any) { 81 level = OverrideLevelFromContext(level, ctx) 82 if level > l.level { 83 return 84 } 85 nowTime := time.Now() 86 message, messageSimple := l.formatter.FormatWithSimple(ctx, level, l.tag, F.ToString(args...), nowTime) 87 if level == LevelPanic { 88 panic(message) 89 } 90 l.writer.Write([]byte(message)) 91 if level == LevelFatal { 92 os.Exit(1) 93 } 94 l.subscriber.Emit(Entry{level, messageSimple}) 95 if l.platformWriter != nil { 96 l.platformWriter.Write([]byte(l.platformFormatter.Format(ctx, level, l.tag, F.ToString(args...), nowTime))) 97 } 98 } 99 100 func (l *observableLogger) Trace(args ...any) { 101 l.TraceContext(context.Background(), args...) 102 } 103 104 func (l *observableLogger) Debug(args ...any) { 105 l.DebugContext(context.Background(), args...) 106 } 107 108 func (l *observableLogger) Info(args ...any) { 109 l.InfoContext(context.Background(), args...) 110 } 111 112 func (l *observableLogger) Warn(args ...any) { 113 l.WarnContext(context.Background(), args...) 114 } 115 116 func (l *observableLogger) Error(args ...any) { 117 l.ErrorContext(context.Background(), args...) 118 } 119 120 func (l *observableLogger) Fatal(args ...any) { 121 l.FatalContext(context.Background(), args...) 122 } 123 124 func (l *observableLogger) Panic(args ...any) { 125 l.PanicContext(context.Background(), args...) 126 } 127 128 func (l *observableLogger) TraceContext(ctx context.Context, args ...any) { 129 l.Log(ctx, LevelTrace, args) 130 } 131 132 func (l *observableLogger) DebugContext(ctx context.Context, args ...any) { 133 l.Log(ctx, LevelDebug, args) 134 } 135 136 func (l *observableLogger) InfoContext(ctx context.Context, args ...any) { 137 l.Log(ctx, LevelInfo, args) 138 } 139 140 func (l *observableLogger) WarnContext(ctx context.Context, args ...any) { 141 l.Log(ctx, LevelWarn, args) 142 } 143 144 func (l *observableLogger) ErrorContext(ctx context.Context, args ...any) { 145 l.Log(ctx, LevelError, args) 146 } 147 148 func (l *observableLogger) FatalContext(ctx context.Context, args ...any) { 149 l.Log(ctx, LevelFatal, args) 150 } 151 152 func (l *observableLogger) PanicContext(ctx context.Context, args ...any) { 153 l.Log(ctx, LevelPanic, args) 154 }