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 }