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.