github.com/v2fly/v2ray-core/v4@v4.45.2/app/log/log.go (about)

     1  //go:build !confonly
     2  // +build !confonly
     3  
     4  package log
     5  
     6  //go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
     7  
     8  import (
     9  	"context"
    10  	"sync"
    11  
    12  	"github.com/v2fly/v2ray-core/v4/common"
    13  	"github.com/v2fly/v2ray-core/v4/common/log"
    14  )
    15  
    16  // Instance is a log.Handler that handles logs.
    17  type Instance struct {
    18  	sync.RWMutex
    19  	config       *Config
    20  	accessLogger log.Handler
    21  	errorLogger  log.Handler
    22  	active       bool
    23  }
    24  
    25  // New creates a new log.Instance based on the given config.
    26  func New(ctx context.Context, config *Config) (*Instance, error) {
    27  	g := &Instance{
    28  		config: config,
    29  		active: false,
    30  	}
    31  	log.RegisterHandler(g)
    32  
    33  	// start logger instantly on inited
    34  	// other modules would log during init
    35  	if err := g.startInternal(); err != nil {
    36  		return nil, err
    37  	}
    38  
    39  	newError("Logger started").AtDebug().WriteToLog()
    40  	return g, nil
    41  }
    42  
    43  func (g *Instance) initAccessLogger() error {
    44  	handler, err := createHandler(g.config.AccessLogType, HandlerCreatorOptions{
    45  		Path: g.config.AccessLogPath,
    46  	})
    47  	if err != nil {
    48  		return err
    49  	}
    50  	g.accessLogger = handler
    51  	return nil
    52  }
    53  
    54  func (g *Instance) initErrorLogger() error {
    55  	handler, err := createHandler(g.config.ErrorLogType, HandlerCreatorOptions{
    56  		Path: g.config.ErrorLogPath,
    57  	})
    58  	if err != nil {
    59  		return err
    60  	}
    61  	g.errorLogger = handler
    62  	return nil
    63  }
    64  
    65  // Type implements common.HasType.
    66  func (*Instance) Type() interface{} {
    67  	return (*Instance)(nil)
    68  }
    69  
    70  func (g *Instance) startInternal() error {
    71  	g.Lock()
    72  	defer g.Unlock()
    73  
    74  	if g.active {
    75  		return nil
    76  	}
    77  
    78  	g.active = true
    79  
    80  	if err := g.initAccessLogger(); err != nil {
    81  		return newError("failed to initialize access logger").Base(err).AtWarning()
    82  	}
    83  	if err := g.initErrorLogger(); err != nil {
    84  		return newError("failed to initialize error logger").Base(err).AtWarning()
    85  	}
    86  
    87  	return nil
    88  }
    89  
    90  // Start implements common.Runnable.Start().
    91  func (g *Instance) Start() error {
    92  	return g.startInternal()
    93  }
    94  
    95  // Handle implements log.Handler.
    96  func (g *Instance) Handle(msg log.Message) {
    97  	g.RLock()
    98  	defer g.RUnlock()
    99  
   100  	if !g.active {
   101  		return
   102  	}
   103  
   104  	switch msg := msg.(type) {
   105  	case *log.AccessMessage:
   106  		if g.accessLogger != nil {
   107  			g.accessLogger.Handle(msg)
   108  		}
   109  	case *log.GeneralMessage:
   110  		if g.errorLogger != nil && msg.Severity <= g.config.ErrorLogLevel {
   111  			g.errorLogger.Handle(msg)
   112  		}
   113  	default:
   114  		// Swallow
   115  	}
   116  }
   117  
   118  // Close implements common.Closable.Close().
   119  func (g *Instance) Close() error {
   120  	newError("Logger closing").AtDebug().WriteToLog()
   121  
   122  	g.Lock()
   123  	defer g.Unlock()
   124  
   125  	if !g.active {
   126  		return nil
   127  	}
   128  
   129  	g.active = false
   130  
   131  	common.Close(g.accessLogger)
   132  	g.accessLogger = nil
   133  
   134  	common.Close(g.errorLogger)
   135  	g.errorLogger = nil
   136  
   137  	return nil
   138  }
   139  
   140  func init() {
   141  	common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
   142  		return New(ctx, config.(*Config))
   143  	}))
   144  }