log.go 2.4 KB

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