github.com/sagernet/sing-box@v1.9.0-rc.20/log/observable.go (about) 1 package log 2 3 import ( 4 "context" 5 "io" 6 "os" 7 "time" 8 9 "github.com/sagernet/sing/common" 10 F "github.com/sagernet/sing/common/format" 11 "github.com/sagernet/sing/common/observable" 12 "github.com/sagernet/sing/service/filemanager" 13 ) 14 15 var _ Factory = (*defaultFactory)(nil) 16 17 type defaultFactory struct { 18 ctx context.Context 19 formatter Formatter 20 platformFormatter Formatter 21 writer io.Writer 22 file *os.File 23 filePath string 24 platformWriter PlatformWriter 25 needObservable bool 26 level Level 27 subscriber *observable.Subscriber[Entry] 28 observer *observable.Observer[Entry] 29 } 30 31 func NewDefaultFactory( 32 ctx context.Context, 33 formatter Formatter, 34 writer io.Writer, 35 filePath string, 36 platformWriter PlatformWriter, 37 needObservable bool, 38 ) ObservableFactory { 39 factory := &defaultFactory{ 40 ctx: ctx, 41 formatter: formatter, 42 platformFormatter: Formatter{ 43 BaseTime: formatter.BaseTime, 44 DisableLineBreak: true, 45 }, 46 writer: writer, 47 filePath: filePath, 48 platformWriter: platformWriter, 49 needObservable: needObservable, 50 level: LevelTrace, 51 subscriber: observable.NewSubscriber[Entry](128), 52 } 53 if platformWriter != nil { 54 factory.platformFormatter.DisableColors = platformWriter.DisableColors() 55 } 56 if needObservable { 57 factory.observer = observable.NewObserver[Entry](factory.subscriber, 64) 58 } 59 return factory 60 } 61 62 func (f *defaultFactory) Start() error { 63 if f.filePath != "" { 64 logFile, err := filemanager.OpenFile(f.ctx, f.filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) 65 if err != nil { 66 return err 67 } 68 f.writer = logFile 69 f.file = logFile 70 } 71 return nil 72 } 73 74 func (f *defaultFactory) Close() error { 75 return common.Close( 76 common.PtrOrNil(f.file), 77 f.subscriber, 78 ) 79 } 80 81 func (f *defaultFactory) Level() Level { 82 return f.level 83 } 84 85 func (f *defaultFactory) SetLevel(level Level) { 86 f.level = level 87 } 88 89 func (f *defaultFactory) Logger() ContextLogger { 90 return f.NewLogger("") 91 } 92 93 func (f *defaultFactory) NewLogger(tag string) ContextLogger { 94 return &observableLogger{f, tag} 95 } 96 97 func (f *defaultFactory) Subscribe() (subscription observable.Subscription[Entry], done <-chan struct{}, err error) { 98 return f.observer.Subscribe() 99 } 100 101 func (f *defaultFactory) UnSubscribe(sub observable.Subscription[Entry]) { 102 f.observer.UnSubscribe(sub) 103 } 104 105 var _ ContextLogger = (*observableLogger)(nil) 106 107 type observableLogger struct { 108 *defaultFactory 109 tag string 110 } 111 112 func (l *observableLogger) Log(ctx context.Context, level Level, args []any) { 113 level = OverrideLevelFromContext(level, ctx) 114 if level > l.level { 115 return 116 } 117 nowTime := time.Now() 118 if l.needObservable { 119 message, messageSimple := l.formatter.FormatWithSimple(ctx, level, l.tag, F.ToString(args...), nowTime) 120 if level == LevelPanic { 121 panic(message) 122 } 123 l.writer.Write([]byte(message)) 124 if level == LevelFatal { 125 os.Exit(1) 126 } 127 l.subscriber.Emit(Entry{level, messageSimple}) 128 } else { 129 message := l.formatter.Format(ctx, level, l.tag, F.ToString(args...), nowTime) 130 if level == LevelPanic { 131 panic(message) 132 } 133 l.writer.Write([]byte(message)) 134 if level == LevelFatal { 135 os.Exit(1) 136 } 137 } 138 if l.platformWriter != nil { 139 l.platformWriter.WriteMessage(level, l.platformFormatter.Format(ctx, level, l.tag, F.ToString(args...), nowTime)) 140 } 141 } 142 143 func (l *observableLogger) Trace(args ...any) { 144 l.TraceContext(context.Background(), args...) 145 } 146 147 func (l *observableLogger) Debug(args ...any) { 148 l.DebugContext(context.Background(), args...) 149 } 150 151 func (l *observableLogger) Info(args ...any) { 152 l.InfoContext(context.Background(), args...) 153 } 154 155 func (l *observableLogger) Warn(args ...any) { 156 l.WarnContext(context.Background(), args...) 157 } 158 159 func (l *observableLogger) Error(args ...any) { 160 l.ErrorContext(context.Background(), args...) 161 } 162 163 func (l *observableLogger) Fatal(args ...any) { 164 l.FatalContext(context.Background(), args...) 165 } 166 167 func (l *observableLogger) Panic(args ...any) { 168 l.PanicContext(context.Background(), args...) 169 } 170 171 func (l *observableLogger) TraceContext(ctx context.Context, args ...any) { 172 l.Log(ctx, LevelTrace, args) 173 } 174 175 func (l *observableLogger) DebugContext(ctx context.Context, args ...any) { 176 l.Log(ctx, LevelDebug, args) 177 } 178 179 func (l *observableLogger) InfoContext(ctx context.Context, args ...any) { 180 l.Log(ctx, LevelInfo, args) 181 } 182 183 func (l *observableLogger) WarnContext(ctx context.Context, args ...any) { 184 l.Log(ctx, LevelWarn, args) 185 } 186 187 func (l *observableLogger) ErrorContext(ctx context.Context, args ...any) { 188 l.Log(ctx, LevelError, args) 189 } 190 191 func (l *observableLogger) FatalContext(ctx context.Context, args ...any) { 192 l.Log(ctx, LevelFatal, args) 193 } 194 195 func (l *observableLogger) PanicContext(ctx context.Context, args ...any) { 196 l.Log(ctx, LevelPanic, args) 197 }