mirror of https://github.com/XTLS/Xray-core
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
2.9 KiB
148 lines
2.9 KiB
package log |
|
|
|
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen |
|
|
|
import ( |
|
"context" |
|
"sync" |
|
|
|
"github.com/xtls/xray-core/common" |
|
"github.com/xtls/xray-core/common/errors" |
|
"github.com/xtls/xray-core/common/log" |
|
) |
|
|
|
// Instance is a log.Handler that handles logs. |
|
type Instance struct { |
|
sync.RWMutex |
|
config *Config |
|
accessLogger log.Handler |
|
errorLogger log.Handler |
|
active bool |
|
dns bool |
|
} |
|
|
|
// New creates a new log.Instance based on the given config. |
|
func New(ctx context.Context, config *Config) (*Instance, error) { |
|
g := &Instance{ |
|
config: config, |
|
active: false, |
|
dns: config.EnableDnsLog, |
|
} |
|
log.RegisterHandler(g) |
|
|
|
// Start logger instantly on initialization |
|
// Other modules would log during initialization |
|
if err := g.startInternal(); err != nil { |
|
return nil, err |
|
} |
|
|
|
errors.LogDebug(ctx, "Logger started") |
|
return g, nil |
|
} |
|
|
|
func (g *Instance) initAccessLogger() error { |
|
handler, err := createHandler(g.config.AccessLogType, HandlerCreatorOptions{ |
|
Path: g.config.AccessLogPath, |
|
}) |
|
if err != nil { |
|
return err |
|
} |
|
g.accessLogger = handler |
|
return nil |
|
} |
|
|
|
func (g *Instance) initErrorLogger() error { |
|
handler, err := createHandler(g.config.ErrorLogType, HandlerCreatorOptions{ |
|
Path: g.config.ErrorLogPath, |
|
}) |
|
if err != nil { |
|
return err |
|
} |
|
g.errorLogger = handler |
|
return nil |
|
} |
|
|
|
// Type implements common.HasType. |
|
func (*Instance) Type() interface{} { |
|
return (*Instance)(nil) |
|
} |
|
|
|
func (g *Instance) startInternal() error { |
|
g.Lock() |
|
defer g.Unlock() |
|
|
|
if g.active { |
|
return nil |
|
} |
|
|
|
g.active = true |
|
|
|
if err := g.initAccessLogger(); err != nil { |
|
return errors.New("failed to initialize access logger").Base(err).AtWarning() |
|
} |
|
if err := g.initErrorLogger(); err != nil { |
|
return errors.New("failed to initialize error logger").Base(err).AtWarning() |
|
} |
|
|
|
return nil |
|
} |
|
|
|
// Start implements common.Runnable.Start(). |
|
func (g *Instance) Start() error { |
|
return g.startInternal() |
|
} |
|
|
|
// Handle implements log.Handler. |
|
func (g *Instance) Handle(msg log.Message) { |
|
g.RLock() |
|
defer g.RUnlock() |
|
|
|
if !g.active { |
|
return |
|
} |
|
|
|
switch msg := msg.(type) { |
|
case *log.AccessMessage: |
|
if g.accessLogger != nil { |
|
g.accessLogger.Handle(msg) |
|
} |
|
case *log.DNSLog: |
|
if g.dns && g.accessLogger != nil { |
|
g.accessLogger.Handle(msg) |
|
} |
|
case *log.GeneralMessage: |
|
if g.errorLogger != nil && msg.Severity <= g.config.ErrorLogLevel { |
|
g.errorLogger.Handle(msg) |
|
} |
|
default: |
|
// Swallow |
|
} |
|
} |
|
|
|
// Close implements common.Closable.Close(). |
|
func (g *Instance) Close() error { |
|
errors.LogDebug(context.Background(), "Logger closing") |
|
|
|
g.Lock() |
|
defer g.Unlock() |
|
|
|
if !g.active { |
|
return nil |
|
} |
|
|
|
g.active = false |
|
|
|
common.Close(g.accessLogger) |
|
g.accessLogger = nil |
|
|
|
common.Close(g.errorLogger) |
|
g.errorLogger = nil |
|
|
|
return nil |
|
} |
|
|
|
func init() { |
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { |
|
return New(ctx, config.(*Config)) |
|
})) |
|
}
|
|
|