trpc.group/trpc-go/trpc-go@v1.0.3/log/README.md (about) 1 English | [中文](README.zh_CN.md) 2 3 # log 4 5 ## Overview 6 7 Here is the simplest program that uses the `log` package: 8 9 ```go 10 // The code below is located in example/main.go 11 package main 12 13 import "trpc.group/trpc-go/trpc-go/log" 14 15 func main() { 16 log.Info("hello, world") 17 } 18 ``` 19 20 As of this writing, it prints: 21 22 ``` 23 2023-09-07 11:46:40.905 INFO example/main.go:6 hello, world 24 ``` 25 26 The `Info` function prints out a message with a log level of Info using the default Logger in the `log` package. 27 Depending on the importance and urgency of the output message, the log package supports five other logging levels (Trace, Debug, Warn, Error, and Fatal) in addition to the Info level mentioned above. 28 The log contains the message "hello, world" and the log level "INFO", but also the print time "2023-09-07 11:46:40.905" and the call stack "example/main.go:6". 29 30 You can also use `Infof` to output the same log level, `Infof` is more flexible and allows you to print messages in the format you want. 31 32 `Infof` is more flexible, allowing you to print messages in the format you want. 33 ```go 34 log.Infof("hello, %s", "world") 35 ``` 36 37 In addition, you can pass a series of key-value pairs to the `With` function to create a new `Logger` from the default `Logger`. 38 The new `Logger` will output the key-value pairs to the end of the message when it prints the log. 39 40 ```go 41 logger := log.With(log.Field{Key: "user", Value: os.Getenv("USER")}) 42 logger.Info("hello, world") 43 ``` 44 45 The output now looks like this: 46 47 ``` 48 2023-09-07 15:05:21.168 INFO example/main.go:12 hello, world {"user": "goodliu"} 49 ``` 50 51 As mentioned before, the `Info` function uses the default `Logger`. 52 You can explicitly get this Logger and call its methods: 53 ```go 54 dl := log.GetDefaultLogger() 55 l := dl.With(log.Field{Key: "user", Value: os.Getenv("USER")}) 56 l.Info("hello, world") 57 ``` 58 59 ## Main Types 60 61 The `log` package contains two main types: 62 63 - `Logger` is the front end, providing output methods similar to `Info` and `Infof`, which you can use to generate logs. 64 - `Writer` is the back end, processing the logs generated by `Logger` and writing them to various logging service systems, such as the console, local files, and remote servers. 65 66 The `log` package supports setting up multiple independent Loggers, each of which can be configured with multiple independent Writers. 67 As shown in the diagram, this example contains three Loggers: "Default Logger", "Other Logger-1", and "Other Logger-2", with "Default Logger" being the default Logger built into the log package. 68 "Default Logger" contains three different Writers: "Console Writer", "File Writer", and "Remote Writer", with "Console Writer" being the default Writer of "Default Logger". 69 `Logger` and `Writer` are both designed as customizable plug-ins, and you can refer to [here](https://github.com/trpc-group/trpc-go/blob/main/docs/developer_guide/develop_plugins/log.md) for information on how to develop them. 70 71 ```ascii 72 +------------------+ 73 | +--------------+ | 74 | |Console Writer| | 75 | +--------------+ | 76 | +-----------+ | 77 +----------------+ | | File Witer| | 78 +-------------> Default Logger +--------> +-----------+ | 79 | +----------------+ | +-------------+ | 80 | | |Remote Writer| | 81 | | +-------------+ | 82 | +------------------+ 83 | +-------------+ 84 | | +--------+ | 85 | | |Writer-A| | 86 +----+----+ +----------------+ | +--------+ | 87 | Loggers +--------> Other Logger-1 +-------->| +--------+ | 88 +----+----+ +----------------+ | |Writer-B| | 89 | | +--------+ | 90 | +-------------+ 91 | +----------------+ +---------+ 92 +-------------> Other Logger-2 +----------> Writer-C| 93 +----------------+ +---------+ 94 ``` 95 96 First, we will introduce how to configure `Logger` and `Writer` in the configuration file. 97 And then we will introduce `Writer` and `Logger` separately in a bottom-up manner. 98 99 ## Configure `Logger` and `Writer` 100 101 Since both Logger and Writer are implemented as plugins, their related configurations need to be placed under the `plugins` field. 102 103 ```yaml 104 plugins: 105 log: 106 default: 107 - writer: console 108 ... 109 - writer: file 110 ... 111 logger1: 112 - writer: console 113 ... 114 - writer: atta 115 ... 116 logger2: 117 - writer: file 118 ... 119 - writer: file 120 ... 121 ``` 122 123 The above configuration includes three Loggers named "default", "logger1", and "logger2". 124 The "default" Logger is the system default Logger, which is configured with Writers named "console", "file", and "remote". When no logging configuration is done, the logs are written to the console by default, with a log level of Debug and a text format printing method. 125 The corresponding configuration file is: 126 127 ```yaml 128 plugins: 129 log: 130 default: 131 - writer: console 132 level: debug 133 formatter: console 134 ``` 135 136 For the configuration parameters of Writer, the design is as follows: 137 138 | configuration item | configuration item | type | default value | configuration explanation | 139 | ----------------------- | ------------------ | :----: | :-----------: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 140 | writer | writer | string | | Mandatory Log Writer plug-in name, the framework supports "file, console" by default | 141 | writer | writer_config | object | nil | only need to be set when the log Writer is "file" | 142 | writer | formatter | string | "" | Log printing format, supports "console" and "json", and defaults to "console" when it is empty | 143 | writer | formatter_config | object | nil | zapcore Encoder configuration when log output, when it is empty, refer to the default value of formatter_config | 144 | writer | remote_config | Object | nil | Remote log format The configuration format can be set at will by the third-party component. | 145 | writer | level | string | | Mandatory When the log level is greater than or equal to the set level, output to the writer backend Value range: trace, debug, info, warn, error, fatal | 146 | writer | caller_skip | int | 2 | Used to control the nesting depth of the log function, if not filled or 0 is entered, the default is 2 | 147 | writer.formatter_config | time_fmt | string | "" | Log output time format, empty default is "2006-01-02 15:04:05.000" | 148 | writer.formatter_config | time_key | string | "" | The name of the key when the log output time is output in Json, the default is "T", use "none" to disable this field | 149 | writer.formatter_config | level_key | string | "" | The name of the key when the log level is output in Json, the default is "L", use "none" to disable this field | 150 | writer.formatter_config | name_key | string | "" | The name of the key when the log name is output in Json, the default is "N", use "none" to disable this field | 151 | writer.formatter_config | caller_key | string | "" | The name of the log output caller's key when outputting in Json, default is "C", use "none" to disable this field | 152 | writer.formatter_config | message_key | string | "" | The name of the key when the log output message body is output in Json, the default is "M", use "none" to disable this field | 153 | writer.formatter_config | stacktrace_key | string | "" | The name of the key when the log output stack is output in Json, default is "S", use "none" to disable this field | 154 | writer.writer_config | log_path | string | | Mandatory Log path name, for example: /usr/local/trpc/log/ | 155 | writer.writer_config | filename | string | | Mandatory Log file name, for example: trpc.log | 156 | writer.writer_config | write_mode | int | 0 | Log writing mode, 1-synchronous, 2-asynchronous, 3-extreme speed (asynchronous discard), do not configure the default extreme speed mode, that is, asynchronous discard | 157 | writer.writer_config | roll_type | string | "" | File roll type, "size" splits files by size, "time" splits files by time, and defaults to split by size when it is empty | 158 | writer.writer_config | max_age | int | 0 | The maximum log retention time, 0 means do not clean up old files | 159 | writer.writer_config | time_unit | string | "" | Only valid when split by time, the time unit of split files by time, support year/month/day/hour/minute, the default value is day | 160 | writer.writer_config | max_backups | int | 0 | The maximum number of files in the log, 0 means not to delete redundant files | 161 | writer.writer_config | compress | bool | false | Whether to compress the log file, default is not compressed | 162 | writer.writer_config | max_size | string | "" | Only valid when splitting by size, the maximum size of the log file (in MB), 0 means not rolling by size | 163 164 ## Multiple Writers 165 166 Multiple Writers can provide the following features: 167 168 - Support for logging to multiple output backends simultaneously, such as printing to the console and saving to a local log file at the same time. 169 - Support for setting log levels individually for each output backend, for example, printing debug-level logs to the console and saving warning-level logs to a log file. 170 - Support for setting log formats (console, JSON, etc.) and log field names individually for each output backend. 171 - Support for log file rolling, including splitting log files by size or time, for file type backends. 172 173 It should be emphasized here that **settings of log are configured at the Writer level**. 174 You need to configure each output separately. 175 For example, if you want to print debug-level logs to the console and save warning-level logs to a log file, you must configure both the console and file Writers separately. 176 177 The system defaults to supporting two Writers: **"console"** and **"file"**. 178 179 ### Write logs to the console 180 181 When the writer is set to "console", it means that the log will be written to the console. 182 Here's an example configuration: 183 184 ```yaml 185 plugins: 186 log: # All log configuration 187 default: # default log configuration, log.Debug("xxx") 188 - writer: console # Console standard output default 189 level: debug # Standard output log level 190 formatter: json # Standard output log format 191 formatter_config: 192 time_fmt: 2006-01-02 15:04:05 # Log time format. "2006-01-02 15:04:05" is the regular time format, "seconds" is the second-level timestamp, "milliseconds" is the millisecond timestamp, "nanoseconds" is the nanosecond timestamp 193 time_key: Time # Log time field name, default "T" if not filled, use "none" to disable this field 194 level_key: Level # Log level field name, default "L" if not filled, use "none" to disable this field 195 name_key: Name # log name field name, default "N" if not filled, use "none" to disable this field 196 caller_key: Caller # log caller field name, default "C" if not filled, use "none" to disable this field 197 message_key: Message # Log message body field name, default "M" if not filled, use "none" to disable this field 198 stacktrace_key: StackTrace # Log stack field name, default "S" if not filled, use "none" to disable this field 199 ``` 200 201 ### Write logs to a local file. 202 203 When the writer is set to "file", it means that the log is written to a local log file. 204 The configuration example of log file rolling storage according to time is as follows: 205 206 ```yaml 207 plugins: 208 log: # All log configuration 209 default: # default log configuration, log.Debug("xxx") 210 - writer: file # Local file log 211 level: info # Local file rolling log level 212 formatter: json # Standard output log format 213 formatter_config: 214 time_fmt: 2006-01-02 15:04:05 # Log time format. "2006-01-02 15:04:05" is the regular time format, "seconds" is the second-level timestamp, "milliseconds" is the millisecond timestamp, "nanoseconds" is the nanosecond timestamp 215 time_key: Time # Log time field name, default "T" if not filled, use "none" to disable this field 216 level_key: Level # Log level field name, default "L" if not filled, use "none" to disable this field 217 name_key: Name # log name field name, default "N" if not filled, use "none" to disable this field 218 caller_key: Caller # log caller field name, default "C" if not filled, use "none" to disable this field 219 message_key: Message # Log message body field name, default "M" if not filled, use "none" to disable this field 220 stacktrace_key: StackTrace # Log stack field name, default "S" if not filled, use "none" to disable this field 221 writer_config: 222 log_path: /tmp/log/ 223 filename: trpc_size.log # Local file rolling log storage path 224 write_mode: 2 # log write mode, 1-synchronous, 2-asynchronous, 3-extreme speed (asynchronous discard), do not configure the default asynchronous mode 225 roll_type: time # File roll type, time is roll by time 226 max_age: 7 # Maximum log retention days 227 max_backups: 10 # Maximum number of log files 228 time_unit: day # Rolling time interval, support: minute/hour/day/month/year 229 ``` 230 231 An example configuration of rolling logs based on file size is as follows: 232 233 ```yaml 234 plugins: 235 log: # All log configuration 236 default: # default log configuration, log.Debug("xxx") 237 - writer: file # Local file log 238 level: info # Local file rolling log level 239 formatter: json # Standard output log format 240 formatter_config: 241 time_fmt: 2006-01-02 15:04:05 # Log time format. "2006-01-02 15:04:05" is the regular time format, "seconds" is the second-level timestamp, "milliseconds" is the millisecond timestamp, "nanoseconds" is the nanosecond timestamp 242 time_key: Time # Log time field name, default "T" if not filled, use "none" to disable this field 243 level_key: Level # Log level field name, default "L" if not filled, use "none" to disable this field 244 name_key: Name # log name field name, default "N" if not filled, use "none" to disable this field 245 caller_key: Caller # log caller field name, default "C" if not filled, use "none" to disable this field 246 message_key: Message # Log message body field name, default "M" if not filled, use "none" to disable this field 247 stacktrace_key: StackTrace # Log stack field name, default "S" if not filled, use "none" to disable this field 248 writer_config: 249 log_path: /tmp/log/ 250 filename: trpc_size.log # Local file rolling log storage path 251 write_mode: 2 # log write mode, 1-synchronous, 2-asynchronous, 3-extreme speed (asynchronous discard), do not configure the default asynchronous mode 252 roll_type: size # File roll type, size is roll by size 253 max_age: 7 # Maximum log retention days 254 max_backups: 10 # Maximum number of log files 255 compress: false # Whether the log file is compressed 256 max_size: 10 # The size of the local file rolling log, in MB 257 ``` 258 259 ### Write logs to a remote location 260 261 To write logs to a remote location, you need to set the `remote_config` field. 262 The default Logger configuration for two remote Writers is shown below: 263 264 ```yaml 265 plugins: 266 log: # log configuration supports multiple logs, you can log through log.Get("xxx").Debug 267 default: # Default log configuration, each log can support multiple writers 268 - writer: remote-writer1 # remote writer named remote-writer1 269 level: debug # log level of remote log 270 remote_config: # remote log configuration, a custom structure for each independent remote log 271 # relevant configuration 272 - writer: remote-writer2 # remote writer named remote-writer2 273 level: info # log level of remote log 274 remote_config: # remote log configuration, a custom structure for each independent remote log 275 # relevant configuration 276 ``` 277 278 ## Multiple Loggers 279 280 `log` package supports multiple loggers at the same time. 281 Each logger can set different log levels, print formats, and writers. 282 You can set different loggers for different application scenarios, for example: 283 284 - Different application modules use different log files for storage. 285 - Different events, based on the degree of attention of the event, collect logs using different log levels. 286 287 The multi-loggers function greatly increases the flexibility of log usage. 288 289 ### Configure logger 290 291 Configure your logger in a configuration file, for example, configuring a logger named "custom": 292 293 ```yaml 294 plugins: 295 log: # All log configuration 296 default: # Default log configuration ,log.Debug("xxx") 297 - writer: console # console stdout default 298 level: debug # The level of standard output logging 299 custom: # Your custom logger configuration, the name can be set at will, each service can have multiple loggers, you can use log.Get("custom").Debug("xxx") to log 300 - writer: file # Your custom core configuration, the name can be set at will 301 caller_skip: 1 # The call site used to locate the log 302 level: debug # Your custom core output level 303 writer_config: # Local file output specific configuration 304 filename: ../log/trpc1.log # The path where the local file rolling log is stored 305 ``` 306 307 For questions about `caller_skip` in the configuration file, see Chapter Explanation about `caller_skip`. 308 309 310 ### Register the logger plugin 311 312 Register the logging plugin at the main function entry point: 313 314 ```go 315 import ( 316 "trpc.group/trpc-go/trpc-go/log" 317 "trpc.group/trpc-go/trpc-go/plugin" 318 ) 319 func main() { 320 // Note: plugin.Register should be executed before trpc.NewServer. 321 plugin.Register("custom", log.DefaultLogFactory) 322 s := trpc.NewServer() 323 } 324 ``` 325 326 ### Get logger 327 328 The log package provides the following two ways for you to get a Logger: 329 330 #### Method 1: Specify logger directly 331 332 ```go 333 // use a logger named "custom" 334 // Note: log.Get should be executed after trpc.NewServer, as plugin loading happens within trpc.NewServer. 335 log.Get("custom").Debug("message") 336 ``` 337 338 #### Method 2: Specify a logger for the context and use the context type log interface 339 340 ```go 341 // Set the logger of the ctx context to custom 342 trpc.Message(ctx).WithLogger(log.Get("custom")) 343 // Use the logging interface of type "Context" 344 log.DebugContext(ctx, "custom log msg") 345 ``` 346 347 ### Log Levels 348 349 According to the importance and urgency of the output messages, the log package provides six levels of logging, which are divided as follows from lowest to highest: 350 351 1. Trace: This is the lowest level, usually used to record all running information of the program, including some details and debugging information. This level of logging is usually only used in the development and debugging phase because it may generate a large amount of log data. 352 2. Debug: This level is mainly used in the debugging process to provide detailed information about program execution, helping you find the cause of problems. 353 3. Info: This level is used to record the general operation of the program, such as user login, system status updates, etc. These pieces of information are helpful in understanding the system's running status and performance. 354 4. Warn: The warning level indicates possible problems that will not immediately affect the program's functionality, but may cause errors in the future. This level of logging can help you discover and prevent problems in advance. 355 5. Error: The error level indicates serious problems that may prevent the program from executing certain functions. This level of logging requires immediate attention and handling. 356 6. Fatal: The fatal error level indicates very serious errors that may cause the program to crash. This is the highest log level, indicating a serious problem that needs to be addressed immediately. 357 358 7. Using log levels correctly can help you better understand and debug your application program. 359 360 ### Log printing interface 361 362 The `log` package provides 3 sets of log printing interfaces: 363 364 - Log function of Default Logger: the most frequently used method. 365 Directly use the default Logger for log printing, which is convenient and simple. 366 - Log function based on Context Logger: Provide a specified logger for a specific scenario and save it in the context, and then use the current context logger for log printing. This method is especially suitable for the RPC call mode: when the service receives the RPC request, set the logger for ctx and attach the field information related to this request, and the subsequent log report of this RPC call will bring the previously set field information 367 - Log function of the specified Logger: it can be used for users to select logger by themselves, and call the interface function of logger to realize log printing. 368 369 370 #### Log function of Default Logger 371 372 The name of the default logger is fixed as "default", the default print level is debug, print console, and the print format is text format. 373 Configuration can be modified in the framework file plugins.log. 374 The function to print logs using the default Logger is as follows, and the function style is consistent with "fmt.Print()" and "fmt.Printf()". 375 376 ```go 377 // Provide "fmt.Print()" style function interface for the default Logger 378 func Trace(args ... interface{}) 379 func Debug(args...interface{}) 380 func Info(args...interface{}) 381 func Warn(args...interface{}) 382 func Error(args...interface{}) 383 func Fatal(args ... interface{}) 384 385 // Provide "fmt.Printf()" style function interface for the default Logger 386 // Formatted printing follows the fmt.Printf() standard 387 func Tracef(format string, args ... interface{}) 388 func Debugf(format string, args ... interface{}) 389 func Infof(format string, args...interface{}) 390 func Warnf(format string, args...interface{}) 391 func Errorf(format string, args...interface{}) 392 func Fatalf(format string, args ... interface{}) 393 ``` 394 395 At the same time, the system also provides management functions of the default Logger, including obtaining, setting the default logger, and setting the printing level of the logger. 396 397 ```go 398 // Get Logger by name 399 func Get(name string) Logger 400 // Set the specified Logger as the default Logger 401 func SetLogger(logger Logger) 402 // Set the log level of the specified writer under the default Logger, and the output is the subscript of the writer array "0" "1" "2" 403 func SetLevel(output string, level Level) 404 // Get the log level of the specified writer under the default Logger, and the output is the subscript of the writer array "0" "1" "2" 405 func GetLevel(output string) Level 406 ``` 407 408 #### Log function based on Context Logger 409 410 For the use of context type logs, each context logger must exclusively have one logger to ensure that the configuration of the context logger will not be tampered with. The framework provides `WithFields()` and `WithFieldsContext()` to inherit the parent logger configuration and generate a new logger. 411 412 ```go 413 // Based on the default Logger, create a new Logger and add fields to the log printing of the new Logger. 414 // fields fields must appear in pairs, for example: logger := log.WithFields("key1","value1") 415 func WithFields(fields ... string) Logger 416 // Based on the Logger under the current context, create a new Logger and add fields to the log printing of the new Logger. 417 // fields fields must appear in pairs, for example: logger := log.WithFields("key1","value1") 418 func WithFieldsContext(ctx context.Context, fields...string) Logger { 419 ``` 420 421 Then set the Logger for the context by the following function: 422 423 ```go 424 logger := ... 425 trpc.Message(ctx).WithLogger(logger) 426 ``` 427 428 The log printing function at the context level is similar to the default logger printing function: 429 430 ```go 431 // Provide "fmt.Print()" style function to Context Logger 432 func TraceContext(args...interface{}) 433 func DebugContext(args...interface{}) 434 func InfoContext(args...interface{}) 435 func WarnContext(args ... interface{}) 436 func ErrorContext(args ... interface{}) 437 func FatalContext(args ... interface{}) 438 439 // Provide "fmt.Printf()" style function to Context Logger 440 // Formatted printing follows the fmt.Printf() standard 441 func TraceContextf(format string, args ... interface{}) 442 func DebugContextf(format string, args ... interface{}) 443 func InfoContextf(format string, args...interface{}) 444 func WarnContextf(format string, args...interface{}) 445 func ErrorContextf(format string, args ... interface{}) 446 func FatalContextf(format string, args ... interface{}) 447 ``` 448 449 #### Log function of the specified Logger 450 451 At the same time, the framework also provides functions for users to choose loggers by themselves. 452 For each Logger implements the Logger Interface. 453 The interface is defined as: 454 455 ```go 456 type Logger interface { 457 // The interface provides "fmt.Print()" style functions 458 Trace(args...interface{}) 459 Debug(args...interface{}) 460 Info(args...interface{}) 461 Warn(args ... interface{}) 462 Error(args...interface{}) 463 Fatal(args...interface{}) 464 465 // The interface provides "fmt.Printf()" style functions 466 Tracef(format string, args...interface{}) 467 Debugf(format string, args...interface{}) 468 Infof(format string, args...interface{}) 469 Warnf(format string, args ... interface{}) 470 Errorf(format string, args...interface{}) 471 Fatalf(format string, args ... interface{}) 472 473 // SetLevel sets the output log level 474 SetLevel(output string, level Level) 475 // GetLevel to get the output log level 476 GetLevel(output string) Level 477 478 // WithFields set some your custom data into each log: such as uid, imei and other fields must appear in pairs of kv 479 WithFields(fields...string) Logger 480 } 481 ``` 482 483 Users can directly use the above interface functions to print logs, for example 484 485 ```go 486 log.Get("custom").Debug("message") 487 log.Get("custom").Debugf("hello %s", "world") 488 ``` 489 490 ## Framework Logs 491 492 1. The framework should log as little as possible and throw error up to user for handling. 493 2. Some underlying severe errors may print trace logs. 494 To enable trace log, you need to set `TRPC_LOG_TRACE` environment variable: 495 496 ```bash 497 export TRPC_LOG_TRACE=1 498 ``` 499 500 ### Enabling `trace` level logging 501 502 To enable `trace` level logging, you must first ensure that the log level is set to `debug` or `trace` in the configuration. 503 Then, you can enable `trace` through either environment variables: 504 505 - Setting through environment variables 506 507 Add the following to the script that executes the server binary: 508 509 ```shell 510 export TRPC_LOG_TRACE=1 511 ./server -conf path/to/trpc_go.yaml 512 ``` 513 514 - Setting through code 515 516 Add the following code: 517 518 ```go 519 import "trpc.group/trpc-go/trpc-go/log" 520 521 func init() { 522 log.EnableTrace() 523 } 524 ``` 525 526 It is recommended to use the environment variable method as it is more flexible. 527 528 ## Notes about `caller_skip` 529 530 Depending on how the `logger` is used, the `caller_skip` setting is also different: 531 532 ### Usage 1: Use Default Logger 533 534 ```go 535 log.Debug("default logger") // use the default logger 536 ``` 537 538 At this time, the configuration used by the log is `default`: 539 540 ```yaml 541 default: # default log configuration, log.Debug("xxx") 542 - writer: console # Console standard output default 543 level: debug # Standard output log level 544 - writer: file # Local file log 545 level: debug # Local file rolling log level 546 formatter: json # Standard output log format 547 writer_config: # Local file output specific configuration 548 filename: ../log/trpc_time.log # Local file rolling log storage path 549 write_mode: 2 # log write mode, 1-synchronous, 2-asynchronous, 3-extreme speed (asynchronous discard), do not configure the default asynchronous mode 550 roll_type: time # File roll type, time is roll by time 551 max_age: 7 # Maximum log retention days 552 max_backups: 10 # Maximum number of log files 553 compress: false # Whether the log file is compressed 554 max_size: 10 # The size of the local file rolling log, in MB 555 time_unit: day # Rolling time interval, support: minute/hour/day/month/year 556 ``` 557 558 At this time, there is no need to pay attention to or set the value of `caller_skip`, the default value is 2, which means that there are two layers on `zap.Logger.Debug` (`trpc.log.Debug -> trpc.log.zapLog. Debug -> zap.Logger.Debug`) 559 560 ### Usage 2: Put the custom logger into the context 561 562 ```go 563 trpc.Message(ctx).WithLogger(log.Get("custom")) 564 log.DebugContext(ctx, "custom log msg") 565 ``` 566 567 At this time, there is no need to pay attention to or set the value of `caller_skip`, the value is 2 by default, which means that there are two layers on `zap.Logger.Debug` (`trpc.log.DebugContext -> trpc.log.zapLog .Debug -> zap.Logger.Debug`). 568 569 The configuration example is as follows: 570 571 ```yaml 572 custom: # Your custom logger configuration, the name can be set at will, each service can have multiple loggers, you can use log.Get("custom").Debug("xxx") to log 573 - writer: file # Your core configuration, the name can be set at will 574 level: debug # Your custom core output level 575 writer_config: # Local file output specific configuration 576 filename: ../log/trpc1.log # Local file rolling log storage path 577 ``` 578 579 ### Do not use custom logger in context: 580 581 ```go 582 log.Get("custom").Debug("message") 583 ``` 584 585 At this time, you need to set the `caller_skip` value of `custom` logger to 1, because `log.Get("custom")` directly returns `trpc.log.zapLog`, call `trpc.log.zapLog.Debug` Only one layer on top of `zap.Logger.Debug` (`trpc.log.zapLog.Debug -> zap.Logger.Debug`). 586 587 The configuration example is as follows: 588 589 ```yaml 590 custom: # Your custom logger configuration, the name can be set at will, each service can have multiple loggers, you can use log.Get("custom").Debug("xxx") to log 591 - writer: file # Your core configuration, the name can be set at will 592 caller_skip: 1 # Caller for locating the log 593 level: debug # Your custom core output level 594 writer_config: # Local file output specific configuration 595 filename: ../log/trpc1.log # Local file rolling log storage path 596 ``` 597 598 Pay attention to the location of `caller_skip` (not in `writer_config`), and when there are `caller_skip` for multiple `writer`s, the value of `caller_skip` of the logger is subject to the last one, for example: 599 600 ```yaml 601 custom: # Your custom logger configuration, the name can be set at will, each service can have multiple loggers, you can use log.Get("custom").Debug("xxx") to log 602 - writer: file # Your core configuration, the name can be set at will 603 caller_skip: 1 # Caller for locating the log 604 level: debug # Your custom core output level 605 writer_config: # Local file output specific configuration 606 filename: ../log/trpc1.log # Local file rolling log storage path 607 - writer: file # Local file log 608 caller_skip: 2 # The calling place used to locate the log 609 level: debug # Local file rolling log level 610 writer_config: # Local file output specific configuration 611 filename: ../log/trpc2.log # Local file rolling log storage path 612 ``` 613 614 Finally, the `caller_skip` value of the `custom` logger will be set to 2. 615 616 **Note:** The above usage 2 and usage 3 are in conflict, only one of them can be used at the same time.