trpc.group/trpc-go/trpc-go@v1.0.3/docs/developer_guide/develop_plugins/log.zh_CN.md (about) 1 [English](log.md) | 中文 2 3 # 怎么为 log 类型的插件开发一个 Writer 插件 4 5 `log` 包提供了一个名为 “default” 的 log 插件, 该插件支持以插件的形式配置多个 Writer。 6 本指南将在 “default” log 插件的基础上,介绍如何开发一个依赖配置进行加载的 Writer 插件。 7 下面以 `log` 包提供的名为 “console” 的 Writer 为例,来介绍相关开发步骤。 8 9 ## 1. 确定插件的配置 10 11 下面是在 "trpc_go.yaml" 配置文件中为名字是 “default” 的 log 插件设置名字为 “console” 的 Writer 插件的配置示例: 12 13 ```yaml 14 plugins: 15 log: 16 default: 17 - writer: console 18 level: debug 19 formatter: console 20 ``` 21 22 完整的配置如下: 23 24 ```go 25 // Config is the log config. Each log may have multiple outputs. 26 type Config []OutputConfig 27 28 // OutputConfig is the output config, includes console, file and remote. 29 type OutputConfig struct { 30 // Writer is the output of log, such as console or file. 31 Writer string `yaml:"writer"` 32 WriteConfig WriteConfig `yaml:"writer_config"` 33 34 // Formatter is the format of log, such as console or json. 35 Formatter string `yaml:"formatter"` 36 FormatConfig FormatConfig `yaml:"formatter_config"` 37 38 // RemoteConfig is the remote config. It's defined by business and should be registered by 39 // third-party modules. 40 RemoteConfig yaml.Node `yaml:"remote_config"` 41 42 // Level controls the log level, like debug, info or error. 43 Level string `yaml:"level"` 44 45 // CallerSkip controls the nesting depth of log function. 46 CallerSkip int `yaml:"caller_skip"` 47 48 // EnableColor determines if the output is colored. The default value is false. 49 EnableColor bool `yaml:"enable_color"` 50 } 51 52 // WriteConfig is the local file config. 53 type WriteConfig struct { 54 // LogPath is the log path like /usr/local/trpc/log/. 55 LogPath string `yaml:"log_path"` 56 // Filename is the file name like trpc.log. 57 Filename string `yaml:"filename"` 58 // WriteMode is the log write mod. 1: sync, 2: async, 3: fast(maybe dropped), default as 3. 59 WriteMode int `yaml:"write_mode"` 60 // RollType is the log rolling type. Split files by size/time, default by size. 61 RollType string `yaml:"roll_type"` 62 // MaxAge is the max expire times(day). 63 MaxAge int `yaml:"max_age"` 64 // MaxBackups is the max backup files. 65 MaxBackups int `yaml:"max_backups"` 66 // Compress defines whether log should be compressed. 67 Compress bool `yaml:"compress"` 68 // MaxSize is the max size of log file(MB). 69 MaxSize int `yaml:"max_size"` 70 71 // TimeUnit splits files by time unit, like year/month/hour/minute, default day. 72 // It takes effect only when split by time. 73 TimeUnit TimeUnit `yaml:"time_unit"` 74 } 75 76 // FormatConfig is the log format config. 77 type FormatConfig struct { 78 // TimeFmt is the time format of log output, default as "2006-01-02 15:04:05.000" on empty. 79 TimeFmt string `yaml:"time_fmt"` 80 81 // TimeKey is the time key of log output, default as "T". 82 TimeKey string `yaml:"time_key"` 83 // LevelKey is the level key of log output, default as "L". 84 LevelKey string `yaml:"level_key"` 85 // NameKey is the name key of log output, default as "N". 86 NameKey string `yaml:"name_key"` 87 // CallerKey is the caller key of log output, default as "C". 88 CallerKey string `yaml:"caller_key"` 89 // FunctionKey is the function key of log output, default as "", which means not to print 90 // function name. 91 FunctionKey string `yaml:"function_key"` 92 // MessageKey is the message key of log output, default as "M". 93 MessageKey string `yaml:"message_key"` 94 // StackTraceKey is the stack trace key of log output, default as "S". 95 StacktraceKey string `yaml:"stacktrace_key"` 96 } 97 ``` 98 99 ```go 100 const ( 101 pluginType = "log" 102 OutputConsole = "console" 103 ) 104 ``` 105 106 ## 2. 实现 `plugin.Factory` 接口 107 108 ```go 109 // ConsoleWriterFactory is the console writer instance. 110 type ConsoleWriterFactory struct { 111 } 112 113 // Type returns the log plugin type. 114 func (f *ConsoleWriterFactory) Type() string { 115 return pluginType 116 } 117 118 // Setup starts, loads and registers console output writer. 119 func (f *ConsoleWriterFactory) Setup(name string, dec plugin.Decoder) error { 120 if dec == nil { 121 return errors.New("console writer decoder empty") 122 } 123 decoder, ok := dec.(*Decoder) 124 if !ok { 125 return errors.New("console writer log decoder type invalid") 126 } 127 cfg := &OutputConfig{} 128 if err := decoder.Decode(&cfg); err != nil { 129 return err 130 } 131 decoder.Core, decoder.ZapLevel = newConsoleCore(cfg) 132 return nil 133 } 134 135 func newConsoleCore(c *OutputConfig) (zapcore.Core, zap.AtomicLevel) { 136 lvl := zap.NewAtomicLevelAt(Levels[c.Level]) 137 return zapcore.NewCore( 138 newEncoder(c), 139 zapcore.Lock(os.Stdout), 140 lvl), lvl 141 } 142 ``` 143 144 ## 3. 调用 `log.RegisterWriter` 把插件自己注册到 `log` 包 145 146 ```go 147 DefaultConsoleWriterFactory = &ConsoleWriterFactory{} 148 RegisterWriter(OutputConsole, DefaultConsoleWriterFactory) 149 ```