mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-02-16 14:24:31 +00:00
Refactor log factory constructor
This commit is contained in:
parent
0be3cdc8fb
commit
28aa4c4d1f
94
box.go
94
box.go
|
@ -9,7 +9,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
|
||||||
"github.com/sagernet/sing-box/experimental"
|
"github.com/sagernet/sing-box/experimental"
|
||||||
"github.com/sagernet/sing-box/experimental/libbox/platform"
|
"github.com/sagernet/sing-box/experimental/libbox/platform"
|
||||||
"github.com/sagernet/sing-box/inbound"
|
"github.com/sagernet/sing-box/inbound"
|
||||||
|
@ -31,18 +30,25 @@ type Box struct {
|
||||||
outbounds []adapter.Outbound
|
outbounds []adapter.Outbound
|
||||||
logFactory log.Factory
|
logFactory log.Factory
|
||||||
logger log.ContextLogger
|
logger log.ContextLogger
|
||||||
logFile *os.File
|
|
||||||
preServices map[string]adapter.Service
|
preServices map[string]adapter.Service
|
||||||
postServices map[string]adapter.Service
|
postServices map[string]adapter.Service
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(ctx context.Context, options option.Options, platformInterface platform.Interface) (*Box, error) {
|
type Options struct {
|
||||||
createdAt := time.Now()
|
option.Options
|
||||||
|
Context context.Context
|
||||||
|
PlatformInterface platform.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(options Options) (*Box, error) {
|
||||||
|
ctx := options.Context
|
||||||
|
if ctx == nil {
|
||||||
|
ctx = context.Background()
|
||||||
|
}
|
||||||
|
createdAt := time.Now()
|
||||||
experimentalOptions := common.PtrValueOrDefault(options.Experimental)
|
experimentalOptions := common.PtrValueOrDefault(options.Experimental)
|
||||||
applyDebugOptions(common.PtrValueOrDefault(experimentalOptions.Debug))
|
applyDebugOptions(common.PtrValueOrDefault(experimentalOptions.Debug))
|
||||||
|
|
||||||
var needClashAPI bool
|
var needClashAPI bool
|
||||||
var needV2RayAPI bool
|
var needV2RayAPI bool
|
||||||
if experimentalOptions.ClashAPI != nil && experimentalOptions.ClashAPI.ExternalController != "" {
|
if experimentalOptions.ClashAPI != nil && experimentalOptions.ClashAPI.ExternalController != "" {
|
||||||
|
@ -51,60 +57,20 @@ func New(ctx context.Context, options option.Options, platformInterface platform
|
||||||
if experimentalOptions.V2RayAPI != nil && experimentalOptions.V2RayAPI.Listen != "" {
|
if experimentalOptions.V2RayAPI != nil && experimentalOptions.V2RayAPI.Listen != "" {
|
||||||
needV2RayAPI = true
|
needV2RayAPI = true
|
||||||
}
|
}
|
||||||
|
var defaultLogWriter io.Writer
|
||||||
logOptions := common.PtrValueOrDefault(options.Log)
|
if options.PlatformInterface != nil {
|
||||||
|
defaultLogWriter = io.Discard
|
||||||
var logFactory log.Factory
|
}
|
||||||
var observableLogFactory log.ObservableFactory
|
logFactory, err := log.New(log.Options{
|
||||||
var logFile *os.File
|
Options: common.PtrValueOrDefault(options.Log),
|
||||||
var logWriter io.Writer
|
Observable: needClashAPI,
|
||||||
if logOptions.Disabled {
|
DefaultWriter: defaultLogWriter,
|
||||||
observableLogFactory = log.NewNOPFactory()
|
BaseTime: createdAt,
|
||||||
logFactory = observableLogFactory
|
PlatformWriter: options.PlatformInterface,
|
||||||
} else {
|
})
|
||||||
switch logOptions.Output {
|
if err != nil {
|
||||||
case "":
|
return nil, E.Cause(err, "create log factory")
|
||||||
if platformInterface != nil {
|
|
||||||
logWriter = io.Discard
|
|
||||||
} else {
|
|
||||||
logWriter = os.Stdout
|
|
||||||
}
|
|
||||||
case "stderr":
|
|
||||||
logWriter = os.Stderr
|
|
||||||
case "stdout":
|
|
||||||
logWriter = os.Stdout
|
|
||||||
default:
|
|
||||||
var err error
|
|
||||||
logFile, err = os.OpenFile(C.BasePath(logOptions.Output), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
logWriter = logFile
|
|
||||||
}
|
|
||||||
logFormatter := log.Formatter{
|
|
||||||
BaseTime: createdAt,
|
|
||||||
DisableColors: logOptions.DisableColor || logFile != nil,
|
|
||||||
DisableTimestamp: !logOptions.Timestamp && logFile != nil,
|
|
||||||
FullTimestamp: logOptions.Timestamp,
|
|
||||||
TimestampFormat: "-0700 2006-01-02 15:04:05",
|
|
||||||
}
|
|
||||||
if needClashAPI {
|
|
||||||
observableLogFactory = log.NewObservableFactory(logFormatter, logWriter, platformInterface)
|
|
||||||
logFactory = observableLogFactory
|
|
||||||
} else {
|
|
||||||
logFactory = log.NewFactory(logFormatter, logWriter, platformInterface)
|
|
||||||
}
|
|
||||||
if logOptions.Level != "" {
|
|
||||||
logLevel, err := log.ParseLevel(logOptions.Level)
|
|
||||||
if err != nil {
|
|
||||||
return nil, E.Cause(err, "parse log level")
|
|
||||||
}
|
|
||||||
logFactory.SetLevel(logLevel)
|
|
||||||
} else {
|
|
||||||
logFactory.SetLevel(log.LevelTrace)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
router, err := route.NewRouter(
|
router, err := route.NewRouter(
|
||||||
ctx,
|
ctx,
|
||||||
logFactory,
|
logFactory,
|
||||||
|
@ -112,7 +78,7 @@ func New(ctx context.Context, options option.Options, platformInterface platform
|
||||||
common.PtrValueOrDefault(options.DNS),
|
common.PtrValueOrDefault(options.DNS),
|
||||||
common.PtrValueOrDefault(options.NTP),
|
common.PtrValueOrDefault(options.NTP),
|
||||||
options.Inbounds,
|
options.Inbounds,
|
||||||
platformInterface,
|
options.PlatformInterface,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "parse route options")
|
return nil, E.Cause(err, "parse route options")
|
||||||
|
@ -132,7 +98,7 @@ func New(ctx context.Context, options option.Options, platformInterface platform
|
||||||
router,
|
router,
|
||||||
logFactory.NewLogger(F.ToString("inbound/", inboundOptions.Type, "[", tag, "]")),
|
logFactory.NewLogger(F.ToString("inbound/", inboundOptions.Type, "[", tag, "]")),
|
||||||
inboundOptions,
|
inboundOptions,
|
||||||
platformInterface,
|
options.PlatformInterface,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "parse inbound[", i, "]")
|
return nil, E.Cause(err, "parse inbound[", i, "]")
|
||||||
|
@ -169,7 +135,7 @@ func New(ctx context.Context, options option.Options, platformInterface platform
|
||||||
preServices := make(map[string]adapter.Service)
|
preServices := make(map[string]adapter.Service)
|
||||||
postServices := make(map[string]adapter.Service)
|
postServices := make(map[string]adapter.Service)
|
||||||
if needClashAPI {
|
if needClashAPI {
|
||||||
clashServer, err := experimental.NewClashServer(router, observableLogFactory, common.PtrValueOrDefault(options.Experimental.ClashAPI))
|
clashServer, err := experimental.NewClashServer(router, logFactory.(log.ObservableFactory), common.PtrValueOrDefault(options.Experimental.ClashAPI))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "create clash api server")
|
return nil, E.Cause(err, "create clash api server")
|
||||||
}
|
}
|
||||||
|
@ -191,7 +157,6 @@ func New(ctx context.Context, options option.Options, platformInterface platform
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
logFactory: logFactory,
|
logFactory: logFactory,
|
||||||
logger: logFactory.Logger(),
|
logger: logFactory.Logger(),
|
||||||
logFile: logFile,
|
|
||||||
preServices: preServices,
|
preServices: preServices,
|
||||||
postServices: postServices,
|
postServices: postServices,
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
|
@ -330,11 +295,6 @@ func (s *Box) Close() error {
|
||||||
return E.Cause(err, "close log factory")
|
return E.Cause(err, "close log factory")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if s.logFile != nil {
|
|
||||||
errors = E.Append(errors, s.logFile.Close(), func(err error) error {
|
|
||||||
return E.Cause(err, "close log file")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,10 @@ func check() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
instance, err := box.New(ctx, options, nil)
|
instance, err := box.New(box.Options{
|
||||||
|
Context: ctx,
|
||||||
|
Options: options,
|
||||||
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
instance.Close()
|
instance.Close()
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,10 @@ func create() (*box.Box, context.CancelFunc, error) {
|
||||||
options.Log.DisableColor = true
|
options.Log.DisableColor = true
|
||||||
}
|
}
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
instance, err := box.New(ctx, options, nil)
|
instance, err := box.New(box.Options{
|
||||||
|
Context: ctx,
|
||||||
|
Options: options,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cancel()
|
cancel()
|
||||||
return nil, nil, E.Cause(err, "create service")
|
return nil, nil, E.Cause(err, "create service")
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing-box"
|
"github.com/sagernet/sing-box"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
@ -27,7 +25,7 @@ func createPreStartedClient() (*box.Box, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
instance, err := box.New(context.Background(), options, nil)
|
instance, err := box.New(box.Options{Options: options})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "create service")
|
return nil, E.Cause(err, "create service")
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,10 @@ func CheckConfig(configContent string) error {
|
||||||
}
|
}
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
instance, err := box.New(ctx, options, nil)
|
instance, err := box.New(box.Options{
|
||||||
|
Context: ctx,
|
||||||
|
Options: options,
|
||||||
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
instance.Close()
|
instance.Close()
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,11 @@ func NewService(configContent string, platformInterface PlatformInterface) (*Box
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
instance, err := box.New(ctx, options, &platformInterfaceWrapper{platformInterface, platformInterface.UseProcFS()})
|
instance, err := box.New(box.Options{
|
||||||
|
Context: ctx,
|
||||||
|
Options: options,
|
||||||
|
PlatformInterface: &platformInterfaceWrapper{platformInterface, platformInterface.UseProcFS()},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cancel()
|
cancel()
|
||||||
return nil, E.Cause(err, "create service")
|
return nil, E.Cause(err, "create service")
|
||||||
|
|
|
@ -49,6 +49,10 @@ func (f *simpleFactory) NewLogger(tag string) ContextLogger {
|
||||||
return &simpleLogger{f, tag}
|
return &simpleLogger{f, tag}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *simpleFactory) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var _ ContextLogger = (*simpleLogger)(nil)
|
var _ ContextLogger = (*simpleLogger)(nil)
|
||||||
|
|
||||||
type simpleLogger struct {
|
type simpleLogger struct {
|
||||||
|
|
|
@ -15,6 +15,7 @@ type Factory interface {
|
||||||
SetLevel(level Level)
|
SetLevel(level Level)
|
||||||
Logger() ContextLogger
|
Logger() ContextLogger
|
||||||
NewLogger(tag string) ContextLogger
|
NewLogger(tag string) ContextLogger
|
||||||
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
type ObservableFactory interface {
|
type ObservableFactory interface {
|
||||||
|
|
110
log/log.go
Normal file
110
log/log.go
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type factoryWithFile struct {
|
||||||
|
Factory
|
||||||
|
file *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *factoryWithFile) Close() error {
|
||||||
|
return common.Close(
|
||||||
|
f.Factory,
|
||||||
|
common.PtrOrNil(f.file),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type observableFactoryWithFile struct {
|
||||||
|
ObservableFactory
|
||||||
|
file *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *observableFactoryWithFile) Close() error {
|
||||||
|
return common.Close(
|
||||||
|
f.ObservableFactory,
|
||||||
|
common.PtrOrNil(f.file),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Options struct {
|
||||||
|
Options option.LogOptions
|
||||||
|
Observable bool
|
||||||
|
DefaultWriter io.Writer
|
||||||
|
BaseTime time.Time
|
||||||
|
PlatformWriter io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(options Options) (Factory, error) {
|
||||||
|
logOptions := options.Options
|
||||||
|
|
||||||
|
if logOptions.Disabled {
|
||||||
|
return NewNOPFactory(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var logFile *os.File
|
||||||
|
var logWriter io.Writer
|
||||||
|
|
||||||
|
switch logOptions.Output {
|
||||||
|
case "":
|
||||||
|
logWriter = options.DefaultWriter
|
||||||
|
if logWriter == nil {
|
||||||
|
logWriter = os.Stderr
|
||||||
|
}
|
||||||
|
case "stderr":
|
||||||
|
logWriter = os.Stderr
|
||||||
|
case "stdout":
|
||||||
|
logWriter = os.Stdout
|
||||||
|
default:
|
||||||
|
var err error
|
||||||
|
logFile, err = os.OpenFile(C.BasePath(logOptions.Output), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
logWriter = logFile
|
||||||
|
}
|
||||||
|
logFormatter := Formatter{
|
||||||
|
BaseTime: options.BaseTime,
|
||||||
|
DisableColors: logOptions.DisableColor || logFile != nil,
|
||||||
|
DisableTimestamp: !logOptions.Timestamp && logFile != nil,
|
||||||
|
FullTimestamp: logOptions.Timestamp,
|
||||||
|
TimestampFormat: "-0700 2006-01-02 15:04:05",
|
||||||
|
}
|
||||||
|
var factory Factory
|
||||||
|
if options.Observable {
|
||||||
|
factory = NewObservableFactory(logFormatter, logWriter, options.PlatformWriter)
|
||||||
|
} else {
|
||||||
|
factory = NewFactory(logFormatter, logWriter, options.PlatformWriter)
|
||||||
|
}
|
||||||
|
if logOptions.Level != "" {
|
||||||
|
logLevel, err := ParseLevel(logOptions.Level)
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "parse log level")
|
||||||
|
}
|
||||||
|
factory.SetLevel(logLevel)
|
||||||
|
} else {
|
||||||
|
factory.SetLevel(LevelTrace)
|
||||||
|
}
|
||||||
|
if logFile != nil {
|
||||||
|
if options.Observable {
|
||||||
|
factory = &observableFactoryWithFile{
|
||||||
|
ObservableFactory: factory.(ObservableFactory),
|
||||||
|
file: logFile,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
factory = &factoryWithFile{
|
||||||
|
Factory: factory,
|
||||||
|
file: logFile,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return factory, nil
|
||||||
|
}
|
|
@ -72,6 +72,10 @@ func (f *nopFactory) FatalContext(ctx context.Context, args ...any) {
|
||||||
func (f *nopFactory) PanicContext(ctx context.Context, args ...any) {
|
func (f *nopFactory) PanicContext(ctx context.Context, args ...any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *nopFactory) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (f *nopFactory) Subscribe() (subscription observable.Subscription[Entry], done <-chan struct{}, err error) {
|
func (f *nopFactory) Subscribe() (subscription observable.Subscription[Entry], done <-chan struct{}, err error) {
|
||||||
return nil, nil, os.ErrInvalid
|
return nil, nil, os.ErrInvalid
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue