github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/log/log.go (about) 1 package log 2 3 import ( 4 "context" 5 "io" 6 "os" 7 "time" 8 9 "github.com/inazumav/sing-box/option" 10 "github.com/sagernet/sing/common" 11 E "github.com/sagernet/sing/common/exceptions" 12 "github.com/sagernet/sing/service/filemanager" 13 ) 14 15 type factoryWithFile struct { 16 Factory 17 file *os.File 18 } 19 20 func (f *factoryWithFile) Close() error { 21 return common.Close( 22 f.Factory, 23 common.PtrOrNil(f.file), 24 ) 25 } 26 27 type observableFactoryWithFile struct { 28 ObservableFactory 29 file *os.File 30 } 31 32 func (f *observableFactoryWithFile) Close() error { 33 return common.Close( 34 f.ObservableFactory, 35 common.PtrOrNil(f.file), 36 ) 37 } 38 39 type Options struct { 40 Context context.Context 41 Options option.LogOptions 42 Observable bool 43 DefaultWriter io.Writer 44 BaseTime time.Time 45 PlatformWriter io.Writer 46 } 47 48 func New(options Options) (Factory, error) { 49 logOptions := options.Options 50 51 if logOptions.Disabled { 52 return NewNOPFactory(), nil 53 } 54 55 var logFile *os.File 56 var logWriter io.Writer 57 58 switch logOptions.Output { 59 case "": 60 logWriter = options.DefaultWriter 61 if logWriter == nil { 62 logWriter = os.Stderr 63 } 64 case "stderr": 65 logWriter = os.Stderr 66 case "stdout": 67 logWriter = os.Stdout 68 default: 69 var err error 70 logFile, err = filemanager.OpenFile(options.Context, logOptions.Output, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) 71 if err != nil { 72 return nil, err 73 } 74 logWriter = logFile 75 } 76 logFormatter := Formatter{ 77 BaseTime: options.BaseTime, 78 DisableColors: logOptions.DisableColor || logFile != nil, 79 DisableTimestamp: !logOptions.Timestamp && logFile != nil, 80 FullTimestamp: logOptions.Timestamp, 81 TimestampFormat: "-0700 2006-01-02 15:04:05", 82 } 83 var factory Factory 84 if options.Observable { 85 factory = NewObservableFactory(logFormatter, logWriter, options.PlatformWriter) 86 } else { 87 factory = NewFactory(logFormatter, logWriter, options.PlatformWriter) 88 } 89 if logOptions.Level != "" { 90 logLevel, err := ParseLevel(logOptions.Level) 91 if err != nil { 92 return nil, E.Cause(err, "parse log level") 93 } 94 factory.SetLevel(logLevel) 95 } else { 96 factory.SetLevel(LevelTrace) 97 } 98 if logFile != nil { 99 if options.Observable { 100 factory = &observableFactoryWithFile{ 101 ObservableFactory: factory.(ObservableFactory), 102 file: logFile, 103 } 104 } else { 105 factory = &factoryWithFile{ 106 Factory: factory, 107 file: logFile, 108 } 109 } 110 } 111 return factory, nil 112 }