github.com/eagleql/xray-core@v1.4.4/app/log/log.go (about)

     1  package log
     2  
     3  //go:generate go run github.com/eagleql/xray-core/common/errors/errorgen
     4  
     5  import (
     6  	"context"
     7  	"sync"
     8  
     9  	"github.com/eagleql/xray-core/common"
    10  	"github.com/eagleql/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  }