trpc.group/trpc-go/trpc-go@v1.0.3/log/logger_factory.go (about)

     1  //
     2  //
     3  // Tencent is pleased to support the open source community by making tRPC available.
     4  //
     5  // Copyright (C) 2023 THL A29 Limited, a Tencent company.
     6  // All rights reserved.
     7  //
     8  // If you have downloaded a copy of the tRPC source code from Tencent,
     9  // please note that tRPC source code is licensed under the  Apache 2.0 License,
    10  // A copy of the Apache 2.0 License is included in this file.
    11  //
    12  //
    13  
    14  package log
    15  
    16  import (
    17  	"errors"
    18  	"fmt"
    19  	"sync"
    20  
    21  	"go.uber.org/zap"
    22  	"go.uber.org/zap/zapcore"
    23  
    24  	"trpc.group/trpc-go/trpc-go/plugin"
    25  )
    26  
    27  func init() {
    28  	RegisterWriter(OutputConsole, DefaultConsoleWriterFactory)
    29  	RegisterWriter(OutputFile, DefaultFileWriterFactory)
    30  	Register(defaultLoggerName, NewZapLog(defaultConfig))
    31  	plugin.Register(defaultLoggerName, DefaultLogFactory)
    32  }
    33  
    34  const (
    35  	pluginType        = "log"
    36  	defaultLoggerName = "default"
    37  )
    38  
    39  var (
    40  	// DefaultLogger the default Logger. The initial output is console. When frame start, it is
    41  	// over write by configuration.
    42  	DefaultLogger Logger
    43  	// DefaultLogFactory is the default log loader. Users may replace it with their own
    44  	// implementation.
    45  	DefaultLogFactory = &Factory{}
    46  
    47  	mu      sync.RWMutex
    48  	loggers = make(map[string]Logger)
    49  )
    50  
    51  // Register registers Logger. It supports multiple Logger implementation.
    52  func Register(name string, logger Logger) {
    53  	mu.Lock()
    54  	defer mu.Unlock()
    55  	if logger == nil {
    56  		panic("log: Register logger is nil")
    57  	}
    58  	if _, dup := loggers[name]; dup && name != defaultLoggerName {
    59  		panic("log: Register called twiced for logger name " + name)
    60  	}
    61  	loggers[name] = logger
    62  	if name == defaultLoggerName {
    63  		DefaultLogger = logger
    64  	}
    65  }
    66  
    67  // GetDefaultLogger gets the default Logger.
    68  // To configure it, set key in configuration file to default.
    69  // The console output is the default value.
    70  func GetDefaultLogger() Logger {
    71  	mu.RLock()
    72  	l := DefaultLogger
    73  	mu.RUnlock()
    74  	return l
    75  }
    76  
    77  // SetLogger sets the default Logger.
    78  func SetLogger(logger Logger) {
    79  	mu.Lock()
    80  	DefaultLogger = logger
    81  	mu.Unlock()
    82  }
    83  
    84  // Get returns the Logger implementation by log name.
    85  // log.Debug use DefaultLogger to print logs. You may also use log.Get("name").Debug.
    86  func Get(name string) Logger {
    87  	mu.RLock()
    88  	l := loggers[name]
    89  	mu.RUnlock()
    90  	return l
    91  }
    92  
    93  // Sync syncs all registered loggers.
    94  func Sync() {
    95  	mu.RLock()
    96  	defer mu.RUnlock()
    97  	for _, logger := range loggers {
    98  		_ = logger.Sync()
    99  	}
   100  }
   101  
   102  // Decoder decodes the log.
   103  type Decoder struct {
   104  	OutputConfig *OutputConfig
   105  	Core         zapcore.Core
   106  	ZapLevel     zap.AtomicLevel
   107  }
   108  
   109  // Decode decodes writer configuration, copy one.
   110  func (d *Decoder) Decode(cfg interface{}) error {
   111  	output, ok := cfg.(**OutputConfig)
   112  	if !ok {
   113  		return fmt.Errorf("decoder config type:%T invalid, not **OutputConfig", cfg)
   114  	}
   115  	*output = d.OutputConfig
   116  	return nil
   117  }
   118  
   119  // Factory is the log plugin factory.
   120  // When server start, the configuration is feed to Factory to generate a log instance.
   121  type Factory struct{}
   122  
   123  // Type returns the log plugin type.
   124  func (f *Factory) Type() string {
   125  	return pluginType
   126  }
   127  
   128  // Setup starts, load and register logs.
   129  func (f *Factory) Setup(name string, dec plugin.Decoder) error {
   130  	if dec == nil {
   131  		return errors.New("log config decoder empty")
   132  	}
   133  	cfg, callerSkip, err := f.setupConfig(dec)
   134  	if err != nil {
   135  		return err
   136  	}
   137  	logger := NewZapLogWithCallerSkip(cfg, callerSkip)
   138  	if logger == nil {
   139  		return errors.New("new zap logger fail")
   140  	}
   141  	Register(name, logger)
   142  	return nil
   143  }
   144  
   145  func (f *Factory) setupConfig(configDec plugin.Decoder) (Config, int, error) {
   146  	cfg := Config{}
   147  	if err := configDec.Decode(&cfg); err != nil {
   148  		return nil, 0, err
   149  	}
   150  	if len(cfg) == 0 {
   151  		return nil, 0, errors.New("log config output empty")
   152  	}
   153  
   154  	// If caller skip is not configured, use 2 as default.
   155  	callerSkip := 2
   156  	for i := 0; i < len(cfg); i++ {
   157  		if cfg[i].CallerSkip != 0 {
   158  			callerSkip = cfg[i].CallerSkip
   159  		}
   160  	}
   161  	return cfg, callerSkip, nil
   162  }