github.com/xtls/xray-core@v1.8.12-0.20240518155711-3168d27b0bdb/app/log/log.go (about) 1 package log 2 3 //go:generate go run github.com/xtls/xray-core/common/errors/errorgen 4 5 import ( 6 "context" 7 "sync" 8 9 "github.com/xtls/xray-core/common" 10 "github.com/xtls/xray-core/common/log" 11 ) 12 13 // Instance is a log.Handler that handles logs. 14 type Instance struct { 15 sync.RWMutex 16 config *Config 17 accessLogger log.Handler 18 errorLogger log.Handler 19 active bool 20 dns bool 21 } 22 23 // New creates a new log.Instance based on the given config. 24 func New(ctx context.Context, config *Config) (*Instance, error) { 25 g := &Instance{ 26 config: config, 27 active: false, 28 dns: config.EnableDnsLog, 29 } 30 log.RegisterHandler(g) 31 32 // start logger instantly on inited 33 // other modules would log during init 34 if err := g.startInternal(); err != nil { 35 return nil, err 36 } 37 38 newError("Logger started").AtDebug().WriteToLog() 39 return g, nil 40 } 41 42 func (g *Instance) initAccessLogger() error { 43 handler, err := createHandler(g.config.AccessLogType, HandlerCreatorOptions{ 44 Path: g.config.AccessLogPath, 45 }) 46 if err != nil { 47 return err 48 } 49 g.accessLogger = handler 50 return nil 51 } 52 53 func (g *Instance) initErrorLogger() error { 54 handler, err := createHandler(g.config.ErrorLogType, HandlerCreatorOptions{ 55 Path: g.config.ErrorLogPath, 56 }) 57 if err != nil { 58 return err 59 } 60 g.errorLogger = handler 61 return nil 62 } 63 64 // Type implements common.HasType. 65 func (*Instance) Type() interface{} { 66 return (*Instance)(nil) 67 } 68 69 func (g *Instance) startInternal() error { 70 g.Lock() 71 defer g.Unlock() 72 73 if g.active { 74 return nil 75 } 76 77 g.active = true 78 79 if err := g.initAccessLogger(); err != nil { 80 return newError("failed to initialize access logger").Base(err).AtWarning() 81 } 82 if err := g.initErrorLogger(); err != nil { 83 return newError("failed to initialize error logger").Base(err).AtWarning() 84 } 85 86 return nil 87 } 88 89 // Start implements common.Runnable.Start(). 90 func (g *Instance) Start() error { 91 return g.startInternal() 92 } 93 94 // Handle implements log.Handler. 95 func (g *Instance) Handle(msg log.Message) { 96 g.RLock() 97 defer g.RUnlock() 98 99 if !g.active { 100 return 101 } 102 103 switch msg := msg.(type) { 104 case *log.AccessMessage: 105 if g.accessLogger != nil { 106 g.accessLogger.Handle(msg) 107 } 108 case *log.DNSLog: 109 if g.dns && g.accessLogger != nil { 110 g.accessLogger.Handle(msg) 111 } 112 case *log.GeneralMessage: 113 if g.errorLogger != nil && msg.Severity <= g.config.ErrorLogLevel { 114 g.errorLogger.Handle(msg) 115 } 116 default: 117 // Swallow 118 } 119 } 120 121 // Close implements common.Closable.Close(). 122 func (g *Instance) Close() error { 123 newError("Logger closing").AtDebug().WriteToLog() 124 125 g.Lock() 126 defer g.Unlock() 127 128 if !g.active { 129 return nil 130 } 131 132 g.active = false 133 134 common.Close(g.accessLogger) 135 g.accessLogger = nil 136 137 common.Close(g.errorLogger) 138 g.errorLogger = nil 139 140 return nil 141 } 142 143 func init() { 144 common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { 145 return New(ctx, config.(*Config)) 146 })) 147 }