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  }