trpc.group/trpc-go/trpc-go@v1.0.3/log/README.zh_CN.md (about)

     1  [English](README.md) | 中文
     2  
     3  # log
     4  
     5  ## 概述
     6  
     7  下面是一个使用 `log` 包的最简单的程序:
     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  截至撰写本文时,它打印:
    21  
    22  ```
    23  2023-09-07 11:46:40.905 INFO    example/main.go:6       hello, world
    24  ```
    25  
    26  `Info` 函数使用 `log` 包中默认的 Logger 打印出一条日志级别为 Info 的消息。
    27  根据输出消息的重要性和紧急性, log 包除了支持上述的 Info 级别的日志外,还有提供其他五种日志级别(Trace、Debug、Warn、Error 和 Fatal)。
    28  该日志除了包含消息-"hello, world"和日志级别-"INFO"外,还包含打印时间-"2023-09-07 11:46:40.905",调用栈-"example/main.go:6"。
    29  
    30  你也可以使用 `Infof` 输出相同的日志级别的日志, `Infof` 更为灵活,允许你以想要的格式打印消息。
    31  
    32  ```go
    33  log.Infof("hello, %s", "world")
    34  ```
    35  
    36  除此之外,你可以传递一系列键值对给 `With` 函数从默认的 Logger 中创建出新的 Logger。
    37  新的 Logger 在打印日志时,会把键值对输出到消息的后面。
    38  
    39  ```go
    40  logger := log.With(log.Field{Key:"user", Value: os.Getenv("USER")})
    41  logger.Info("hello, world")
    42  ```
    43  
    44  现在的输出如下所示:
    45  
    46  ```
    47  2023-09-07 15:05:21.168 INFO    example/main.go:12      hello, world    {"user": "goodliu"}
    48  ```
    49  
    50  正如之前提到的,`Info` 函数使用默认的 Logger,你可以显式地获取这个 Logger,并调用它的方法:
    51  
    52  ```go
    53  dl := log.GetDefaultLogger()
    54  l := dl.With(log.Field{Key: "user", Value: os.Getenv("USER")})
    55  l.Info("hello, world")
    56  ```
    57  
    58  ## 主要类型
    59  
    60  `log` 包包含两种主要类型:
    61  
    62  - `Logger` 是前端,提供类似于 `Info`和 `Infof` 的输出方法,你可以使用这些方法产生日志。
    63  - `Writer` 是后端,处理 `Logger` 产生的日志,将日志写入到各种日志服务系统中,如控制台、本地文件和远端。
    64  
    65  `log` 包支持设置多个互相独立的 `Logger`,每个 `Logger` 又支持设置多个互相独立的 `Writer`。
    66  如图所示,在这个示例图中包含三个 `Logger`, “Default Logger”,“Other Logger-1“ 和  ”Other Logger-2“,其中的 ”Default Logger“ 是 log 包中内置默认的 `Logger`。
    67  ”Default Logger“ 包含三个不同的 `Writer`, "Console Writer",“File Writer” 和 “Remote Writer”,其中的 "Console Writer" 是 ”Default Logger“ 默认的 `Writer`。
    68  `Logger` 和 `Writer` 都被设计为定制化开发的插件,关于如何开发它们,可以参考[这里](/docs/developer_guide/develop_plugins/log.zh_CN.md) 。
    69  
    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  下面将先介绍如何在配置文件中配置 `Logger` 和 `Writer` ,然后再以自下而上地方式分别介绍 `Writer` 和 `Logger`。
    97  
    98  ## 配置 `Logger` 和 `Writer`
    99  
   100  因为 `Logger` 和 `Writer` 都是采用插件的方式来实现的,所以相关配置都需要放到“plugins”字段下面。
   101  
   102  ```yaml
   103  plugins:
   104    log:
   105      default:
   106        - writer: console
   107          ...
   108        - writer: file
   109          ...
   110        - writer: remote
   111          ...
   112      logger1:
   113        - writer: writer-a
   114          ...
   115        - writer: writer-b
   116          ...
   117      logger2:
   118        - writer: writer-c
   119          ...
   120  ```
   121  
   122  上面配置了三个名字为 “default”,“logger1”,和 “logger2” 的 `Logger`。
   123  其中的 “default” 是系统默认的 `Logger`,它配置了名字为 “console”,“file” 和 “remote” 的 `Writer`。
   124  在不做任何日志配置时,日志默认写入到 ”console“,日志级别为 Debug,打印方式为文本格式,其对应的配置文件为:
   125  
   126  ```yaml
   127  plugins:
   128    log:
   129      default:
   130        - writer: console
   131          level: debug
   132          formatter: console
   133  ```
   134  
   135  对于 `Writer` 的配置参数,设计如下:
   136  
   137  | 配置项                  | 配置项           |  类型  | 默认值 | 配置解释                                                                  |
   138  | ----------------------- | ---------------- | :----: | :----: |-----------------------------------------------------------------------|
   139  | writer                  | writer           | string |        | 必填 日志 Writer 插件的名字,框架默认支持“file,console”                               |
   140  | writer                  | writer_config    |  对象  |  nil   | 当日志 Writer 为“file”时才需要设置                                              |
   141  | writer                  | formatter        | string |   “”   | 日志打印格式,支持“console”和“json”,为空时默认设置为“console”                           |
   142  | writer                  | formatter_config |  对象  |  nil   | 日志输出时 zapcore Encoder 配置,为空时为参考 formatter_config 的默认值                 |
   143  | writer                  | remote_config    |  对象  |  nil   | 远程日志格式 配置格式你随便定 由第三方组件自己注册,具体配置参考各日志插件文档                              |
   144  | writer                  | level            | string |        | 必填 日志级别大于等于设置级别时,输出到 writer 后端 取值范围:trace,debug,info,warn,error,fatal |
   145  | writer                  | caller_skip      |  int   |   2    | 用于控制 log 函数嵌套深度,不填或者输入 0 时,默认为 2                                      |
   146  | writer.formatter_config | time_fmt         | string |   ""   | 日志输出时间格式,空默认为"2006-01-02 15:04:05.000"                                |
   147  | writer.formatter_config | time_key         | string |   ""   | 日志输出时间在以 Json 输出时的 key 的名称,默认为"T", 用 "none" 来禁用这一字段                   |
   148  | writer.formatter_config | level_key        | string |   ""   | 日志级别在以 Json 输出时的 key 的名称,默认为"L", 用 "none" 来禁用这一字段                     |
   149  | writer.formatter_config | name_key         | string |   ""   | 日志名称在以 Json 输出时的 key 的名称,默认为"N", 用 "none" 来禁用这一字段                     |
   150  | writer.formatter_config | caller_key       | string |   ""   | 日志输出调用者在以 Json 输出时的 key 的名称,默认为"C", 用 "none" 来禁用这一字段                  |
   151  | writer.formatter_config | message_key      | string |   ""   | 日志输出消息体在以 Json 输出时的 key 的名称,默认为"M", 用 "none" 来禁用这一字段                  |
   152  | writer.formatter_config | stacktrace_key   | string |   ""   | 日志输出堆栈在以 Json 输出时的 key 的名称,默认为"S", 用 "none" 来禁用这一字段                   |
   153  | writer.writer_config    | log_path         | string |        | 必填 日志路径名,例如:/usr/local/trpc/log/                                      |
   154  | writer.writer_config    | filename         | string |        | 必填 日志文件名,例如:trpc.log                                                  |
   155  | writer.writer_config    | write_mode       |  int   |   0    | 日志写入模式,1-同步,2-异步,3-极速 (异步丢弃), 不配置默认极速模式,即异步丢弃                         |
   156  | writer.writer_config    | roll_type        | string |   ""   | 文件滚动类型,"size"按大小分割文件,"time"按时间分割文件,为空时默认按大小分割                         |
   157  | writer.writer_config    | max_age          |  int   |   0    | 日志最大保留时间,为 0 表示不清理旧文件                                                 |
   158  | writer.writer_config    | max_backups      |  int   |   0    | 日志最大文件数,为 0 表示不删除多余文件                                                 |
   159  | writer.writer_config    | compress         |  bool  | false  | 日志文件是否压缩,默认不压缩                                                        |
   160  | writer.writer_config    | max_size         | string |   ""   | 按大小分割时才有效,日志文件最大大小(单位 MB),为 0 表示不按大小滚动                                |
   161  | writer.writer_config    | time_unit        | string |   ""   | 按时间分割时才有效,按时间分割文件的时间单位,支持 year/month/day/hour/minute, 默认值为 day        |
   162  
   163  ## 多 Writer
   164  
   165  多 Writer 可以提供如下功能:
   166  
   167  - 支持日志同时上报到多个输出后端,比如同时打印到 console 和本地日志文件
   168  - 支持每个输出后端单独设置日志级别,比如 debug 级别以上日志打 console,warn 级别以上日志保存到日志文件
   169  - 支持每个输出后端单独设置日志格式(console,json 等),日志字段名称
   170  - 支持“file”类型后端滚动日志功能,包括按文件大小或者时间来分割日志文件
   171  
   172  这里需要强调的是:**日志的打印设置是以 Writer 粒度来配置的**。
   173  你需要为每个输出端做配置,比如:Debug 级别以上日志打 console,Warn 级别以上日志保存到日志文件,那就必须要分别配置 console 和 file 这两个 Writer。
   174  
   175  系统默认支持 **"console"** 和 **"file"** 两种 Writer。
   176  
   177  ### 将日志写入到控制台
   178  
   179  当 writer 设置为 ”console“ 时,日志会被写入到控制台。
   180  配置参考示例如下:
   181  
   182  ```yaml
   183  plugins:
   184    log:  # 所有日志配置
   185      default:  # 默认日志配置,log.Debug("xxx")
   186        - writer: console  # 控制台标准输出 默认
   187          level: debug  # 标准输出日志的级别
   188          formatter: json  # 标准输出日志的格式
   189          formatter_config:
   190            time_fmt: 2006-01-02 15:04:05  # 日志时间格式。"2006-01-02 15:04:05"为常规时间格式,"seconds"为秒级时间戳,"milliseconds"为毫秒时间戳,"nanoseconds"为纳秒时间戳
   191            time_key: Time  # 日志时间字段名称,不填默认"T",填 "none" 可禁用此字段
   192            level_key: Level  # 日志级别字段名称,不填默认"L",填 "none" 可禁用此字段
   193            name_key: Name  # 日志名称字段名称,不填默认"N",填 "none" 可禁用此字段
   194            caller_key: Caller  # 日志调用方字段名称,不填默认"C",填 "none" 可禁用此字段
   195            message_key: Message  # 日志消息体字段名称,不填默认"M",填 "none" 可禁用此字段
   196            stacktrace_key: StackTrace  # 日志堆栈字段名称,不填默认"S",填 "none" 可禁用此字段
   197  ```
   198  
   199  ### 将日志写入到本地
   200  
   201  当 writer 设置为“file”时,日志会被写入到本地日志文件。
   202  
   203  日志按时间进行文件滚动存放的配置示例如下:
   204  
   205  ```yaml
   206  plugins:
   207    log:  # 所有日志配置
   208      default:  # 默认日志配置,log.Debug("xxx")
   209        - writer: file  # 本地文件日志
   210          level: info  # 本地文件滚动日志的级别
   211          formatter: json  # 标准输出日志的格式
   212          formatter_config:
   213            time_fmt: 2006-01-02 15:04:05  # 日志时间格式。"2006-01-02 15:04:05"为常规时间格式,"seconds"为秒级时间戳,"milliseconds"为毫秒时间戳,"nanoseconds"为纳秒时间戳
   214            time_key: Time  # 日志时间字段名称,不填默认"T",填 "none" 可禁用此字段
   215            level_key: Level  # 日志级别字段名称,不填默认"L",填 "none" 可禁用此字段
   216            name_key: Name  # 日志名称字段名称,不填默认"N",填 "none" 可禁用此字段
   217            caller_key: Caller  # 日志调用方字段名称,不填默认"C",填 "none" 可禁用此字段
   218            message_key: Message  # 日志消息体字段名称,不填默认"M",填 "none" 可禁用此字段
   219            stacktrace_key: StackTrace  # 日志堆栈字段名称,不填默认"S",填 "none" 可禁用此字段
   220          writer_config:
   221            log_path: /tmp/log/
   222            filename: trpc_size.log  # 本地文件滚动日志存放的路径
   223            write_mode: 2  # 日志写入模式,1-同步,2-异步,3-极速 (异步丢弃), 不配置默认异步模式
   224            roll_type: time  # 文件滚动类型,time 为按时间滚动
   225            max_age: 7  # 最大日志保留天数
   226            max_backups: 10  # 最大日志文件数
   227            time_unit: day  # 滚动时间间隔,支持:minute/hour/day/month/year
   228  ```
   229  
   230  日志按文件大小进行文件滚动存放的配置示例如下:
   231  
   232  ```yaml
   233  plugins:
   234    log:  # 所有日志配置
   235      default:  # 默认日志配置,log.Debug("xxx")
   236        - writer: file  # 本地文件日志
   237          level: info  # 本地文件滚动日志的级别
   238          formatter: json  # 标准输出日志的格式
   239          formatter_config:
   240            time_fmt: 2006-01-02 15:04:05  # 日志时间格式。"2006-01-02 15:04:05"为常规时间格式,"seconds"为秒级时间戳,"milliseconds"为毫秒时间戳,"nanoseconds"为纳秒时间戳
   241            time_key: Time  # 日志时间字段名称,不填默认"T",填 "none" 可禁用此字段
   242            level_key: Level  # 日志级别字段名称,不填默认"L",填 "none" 可禁用此字段
   243            name_key: Name  # 日志名称字段名称,不填默认"N",填 "none" 可禁用此字段
   244            caller_key: Caller  # 日志调用方字段名称,不填默认"C",填 "none" 可禁用此字段
   245            message_key: Message  # 日志消息体字段名称,不填默认"M",填 "none" 可禁用此字段
   246            stacktrace_key: StackTrace  # 日志堆栈字段名称,不填默认"S",填 "none" 可禁用此字段
   247          writer_config:
   248            log_path: /tmp/log/
   249            filename: trpc_size.log  # 本地文件滚动日志存放的路径
   250            write_mode: 2  # 日志写入模式,1-同步,2-异步,3-极速 (异步丢弃), 不配置默认异步模式
   251            roll_type: size  # 文件滚动类型,size 为按大小滚动
   252            max_age: 7  # 最大日志保留天数
   253            max_backups: 10  # 最大日志文件数
   254            compress: false  # 日志文件是否压缩
   255            max_size: 10  # 本地文件滚动日志的大小 单位 MB
   256  ```
   257  
   258  ### 将日志写入到远端
   259  
   260  将日志写入到远端需要设置“remote_config”字段。
   261  默认 `Logger` 配置两个远端 `Writer` 的配置示例如下:
   262  
   263  ```yaml
   264  plugins:
   265    log: #日志配置 支持多个日志 可通过 log.Get("xxx").Debug 打日志
   266      default: # 默认日志的配置,每个日志可支持多个 Writer
   267        - writer: remote-writer1  # 名字为 remote-writer1 的 remote writer
   268          level: debug # 远程日志的级别
   269          remote_config:  # 远程日志配置,你自定义的结构,每一种远程日志都有自己独立的配置
   270            # 相关配置
   271        - writer: remote-writer2 # 名字为 remote-writer2 的 remote writer
   272          level: info # 远程日志的级别
   273          remote_config:  # 远程日志配置,你自定义的结构,每一种远程日志都有自己独立的配置
   274            # 相关配置
   275  ```
   276  
   277  ## 多 Logger
   278  
   279  `log` 包支持同时多个 logger,每个 logger 可以设置不同的日志级别,打印格式,和 writers。
   280  你可以为不同的应用场景设置不同的 logger,例如:
   281  
   282  - 不同的应用模块使用不同的日志文件存储
   283  - 不同的事件,基于事件的关注度不同,采用不同的日志级别收集日志
   284  
   285  多 logger 功能大大增加了日志使用的灵活性。
   286  
   287  ### 配置 Logger
   288  
   289  在配置文件中配置你的 logger,比如配置名为 “custom” 的 logger:
   290  
   291  ```yaml
   292  plugins:
   293    log:  # 所有日志配置
   294      default:  # 默认日志配置,log.Debug("xxx")
   295        - writer: console  # 控制台标准输出 默认
   296          level: debug  # 标准输出日志的级别
   297      custom:  # 你自定义的 Logger 配置,名字随便定,每个服务可以有多个 Logger,可使用 log.Get("custom").Debug("xxx") 打日志
   298        - writer: file  # 你自定义的core配置,名字随便定
   299          caller_skip: 1  # 用于定位日志的调用处
   300          level: debug  # 你自定义core输出的级别
   301          writer_config:  # 本地文件输出具体配置
   302            filename: ../log/trpc1.log  # 本地文件滚动日志存放的路径
   303  ```
   304  
   305  配置文件中对于 `caller_skip` 的疑问见「关于 `caller_skip` 的说明」这一节。
   306  
   307  ### 注册 Logger 插件
   308  
   309  在 `main` 函数入口注册日志插件:
   310  
   311  ```go
   312  import (
   313      "trpc.group/trpc-go/trpc-go/log"
   314      "trpc.group/trpc-go/trpc-go/plugin"
   315  )
   316  func main() {
   317      // 注意:plugin.Register 要在 trpc.NewServer 之前执行
   318      plugin.Register("custom", log.DefaultLogFactory)
   319      s := trpc.NewServer()
   320  }
   321  ```
   322  
   323  ### 获取 Logger
   324  
   325  `log` 包提供了以下两种方式供你获取 `Logger`:
   326  
   327  #### 方法一:直接指定 Logger
   328  
   329  ```go
   330  // 使用名称为“custom”的 Logger
   331  // 注意:log.Get 得在 trpc.NewServer 之后执行,因为插件的加载是在 trpc.NewServer 中进行的
   332  log.Get("custom").Debug("message")
   333  ```
   334  
   335  #### 方法二:为 Context 指定 Logger,使用 Context 类型日志接口
   336  
   337  ```go
   338  // 设置 ctx 的 Logger 为 custom
   339  trpc.Message(ctx).WithLogger(log.Get("custom"))
   340  // 使用“Context”类型的日志接口
   341  log.DebugContext(ctx, "custom log msg")
   342  ```
   343  
   344  ### 日志级别
   345  
   346  根据输出消息的重要性和紧急性, log 包提供六种日志打印级别,并按由低到高的顺序进行了如下划分:
   347  
   348  1. Trace:这是最低的级别,通常用于记录程序的所有运行信息,包括一些细节信息和调试信息。
   349     这个级别的日志通常只在开发和调试阶段使用,因为它可能会生成大量的日志数据。
   350  2. Debug:这个级别主要用于调试过程中,提供程序运行的详细信息,帮助你找出问题的原因。
   351  3. Info: 这个级别用于记录程序的常规操作,比如用户登录、系统状态更新等。
   352     这些信息对于了解系统的运行状态和性能很有帮助。
   353  4. Warn:警告级别表示可能的问题,这些问题不会立即影响程序的功能,但可能会在未来引发错误。
   354     这个级别的日志可以帮助你提前发现和预防问题。
   355  5. Error:错误级别表示严重的问题,这些问题可能会阻止程序执行某些功能。
   356     这个级别的日志需要立即关注和处理。
   357  6. Fatal:致命错误级别表示非常严重的错误,这些错误可能会导致程序崩溃。
   358     这是最高的日志级别,表示需要立即处理的严重问题。
   359  
   360  正确地使用日志级别可以帮助你更好地理解和调试你的应用程序。
   361  
   362  ### 日志打印接口
   363  
   364  `log` 包提供了3组日志打印接口:
   365  
   366  - 默认 Logger 的日志函数:使用最频繁的一种方式。直接使用默认 `Logger` 进行日志打印,方便简单。
   367  - 基于 Context Logger 的日志函数:为特定场景提供指定 `Logger`,并保存在 Context 里,后续使用当前 Context `Logger` 进行日志打印。
   368    这种方式特别适合 RPC 调用模式:当服务收到 RPC 请求时,为 ctx 设置 `Logger`,并附加此次请求相关的 field 信息,此 RPC 调用的后续日志上报都会带上之前设定的 field 信息。
   369  - 指定的 Logger 的日志函数:可以用于用户自行选择 `Logger`,并调用 `Logger` 的接口函数实现日志打印。
   370  
   371  #### 默认 Logger 的日志函数
   372  
   373  默认 Logger 的名称固定为“default”,默认打印级别为 debug,打印 console,打印格式为文本格式。配置可以通过在框架文件中 plugins.log 中修改。
   374  使用默认 Logger 打印日志的函数如下,函数风格与“fmt.Print()”和"fmt.Printf()"保持一致。
   375  
   376  ```go
   377  // 对默认 Logger 提供“fmt.Print()”风格的函数接口
   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  // 对默认 Logger 提供“fmt.Printf()”风格的函数接口
   386  // 格式化打印遵循 fmt.Printf() 标准
   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  同时系统也提供了默认 Logger 的管理函数,包括获取,设置默认 Logger,设置 Logger 的打印级别。
   396  
   397  ```go
   398  // 通过名称获取 Logger
   399  func Get(name string) Logger
   400  // 设置指定 Logger 为默认 Logger
   401  func SetLogger(logger Logger)
   402  // 设置默认 Logger 下指定 writer 的日志级别,output 为 writer 数组下标 "0" "1" "2"
   403  func SetLevel(output string, level Level)
   404  // 获取默认 Logger 下指定 writer 的日志级别,output 为 writer 数组下标 "0" "1" "2"
   405  func GetLevel(output string) Level
   406  ```
   407  
   408  #### 基于 Context Logger 的日志函数
   409  
   410  基于 Context Logger 的日志函数,每个 Context Logger 必须独占一个 Logger,确保 Context Logger 的配置不被串改。
   411  `log` 提供了 `With` 和 `WithContext` 来继承父 Logger 配置,并生成新的 Logger。
   412  
   413  ```go
   414  // With adds user defined fields to Logger. Field support multiple values.
   415  func With(fields ...Field) Logger
   416  // WithContext adds user defined fields to the Logger of context.
   417  // Fields support multiple values.
   418  func WithContext(ctx context.Context, fields ...Field) Logger
   419  ```
   420  
   421  然后通过下面函数为 context 设置 Logger:
   422  
   423  ```go
   424  logger := ...
   425  trpc.Message(ctx).WithLogger(logger)
   426  ```
   427  
   428  context 级别的日志打印函数和默认 Logger 打印日志的函数类似:
   429  
   430  ```go
   431  // 对 Context Logger 提供“fmt.Print()”风格的函数
   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  // 对 Context Logger 提供“fmt.Printf()”风格的函数
   440  // 格式化打印遵循 fmt.Printf() 标准
   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  #### 指定的 Logger 的日志函数
   450  
   451  同时,`log` 也提供了函数供用户自行选择 Logger。
   452  对于每一个 Logger 都实现了 Logger Interface。
   453  接口定义为:
   454  
   455  ```go
   456  type Logger interface {
   457      // 接口提供“fmt.Print()”风格的函数
   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      // 接口提供“fmt.Printf()”风格的函数
   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 设置输出端日志级别
   474      SetLevel(output string, level Level)
   475      // GetLevel 获取输出端日志级别
   476      GetLevel(output string) Level
   477  
   478      // WithFields 设置一些你自定义数据到每条 log 里:比如 uid,imei 等 fields 必须 kv 成对出现
   479      WithFields(fields ...string) Logger
   480  }
   481  ```
   482  
   483  用户可以直接使用上面接口函数进行日志打印,例如
   484  
   485  ```go
   486  log.Get("custom").Debug("message")
   487  log.Get("custom").Debugf("hello %s", "world")
   488  ```
   489  
   490  ## 框架日志
   491  
   492  1. 框架以尽量不打日志为原则,将错误一直往上抛交给用户自己处理
   493  2. 底层严重问题才会打印 trace 日志,需要设置环境变量才会开启:export TRPC_LOG_TRACE=1
   494  
   495  ### `trace` 级别日志的开启
   496  
   497  要开启日志的 `trace` 级别,首先要保证配置上的日志级别设置为 `debug` 或 `trace`,然后通过环境变量来开启 `trace`:
   498  
   499  - 通过环境变量设置
   500  
   501  在执行服务二进制的脚本中添加
   502  
   503  ```shell
   504  export TRPC_LOG_TRACE=1
   505  ./server -conf path/to/trpc_go.yaml
   506  ```
   507  
   508  - 通过代码进行设置
   509  
   510  添加以下代码即可:
   511  
   512  ```go
   513  import "trpc.group/trpc-go/trpc-go/log"
   514  
   515  func init() {
   516      log.EnableTrace()
   517  }
   518  ```
   519  
   520  推荐使用环境变量的方式,更灵活一点。
   521  
   522  ## 关于 `caller_skip` 的说明
   523  
   524  使用 `Logger` 的方式不同,`caller_skip` 的设置也有所不同:
   525  
   526  ### 用法1: 使用 Default Logger
   527  
   528  ```go
   529  log.Debug("default logger") // 使用默认的 logger
   530  ```
   531  
   532  此时该 Logger 使用的配置为 `default`:
   533  
   534  ```yaml
   535  default:  # 默认日志配置,log.Debug("xxx")
   536    - writer: console  # 控制台标准输出 默认
   537      level: debug  # 标准输出日志的级别
   538    - writer: file  # 本地文件日志
   539      level: debug  # 本地文件滚动日志的级别
   540      formatter: json  # 标准输出日志的格式
   541      writer_config:  # 本地文件输出具体配置
   542        filename: ../log/trpc_time.log  # 本地文件滚动日志存放的路径
   543        write_mode: 2  # 日志写入模式,1-同步,2-异步,3-极速 (异步丢弃), 不配置默认异步模式
   544        roll_type: time  # 文件滚动类型,time 为按时间滚动
   545        max_age: 7  # 最大日志保留天数
   546        max_backups: 10  # 最大日志文件数
   547        compress: false  # 日志文件是否压缩
   548        max_size: 10  # 本地文件滚动日志的大小 单位 MB
   549        time_unit: day  # 滚动时间间隔,支持:minute/hour/day/month/year
   550  ```
   551  
   552  此时不需要关注或者去设置 `caller_skip` 的值,该值默认为 2,意思是在 `zap.Logger.Debug` 上套了两层(`trpc.log.Debug -> trpc.log.zapLog.Debug -> zap.Logger.Debug`)
   553  
   554  ### 用法2: 将自定义的 Logger 放到 context
   555  
   556  ```go
   557  trpc.Message(ctx).WithLogger(log.Get("custom"))
   558  log.DebugContext(ctx, "custom log msg")
   559  ```
   560  
   561  此时也不需要关注或者去设置 `caller_skip` 的值,该值默认为 2,意思是在 `zap.Logger.Debug` 上套了两层(`trpc.log.DebugContext -> trpc.log.zapLog.Debug -> zap.Logger.Debug`)
   562  
   563  配置例子如下:
   564  
   565  ```yaml
   566  custom:  # 你的 Logger 配置,名字随便定,每个服务可以有多个 Logger,可使用 log.Get("custom").Debug("xxx") 打日志
   567    - writer: file  # 你的 core 配置,名字随便定
   568      level: debug  # 你的 core 输出的级别
   569      writer_config:  # 本地文件输出具体配置
   570        filename: ../log/trpc1.log  # 本地文件滚动日志存放的路径
   571  ```
   572  
   573  ### 用法3: 不在 context 中使用自定义的 Logger
   574  
   575  ```go
   576  log.Get("custom").Debug("message")
   577  ```
   578  
   579  此时需要将 `custom` Logger 的 `caller_skip` 值设置为 1,因为 `log.Get("custom")` 直接返回的是 `trpc.log.zapLog`,调用 `trpc.log.zapLog.Debug` 只在 `zap.Logger.Debug` 上套了一层(`trpc.log.zapLog.Debug -> zap.Logger.Debug`)
   580  
   581  配置例子如下:
   582  
   583  ```yaml
   584  custom:  # 你自定义的 Logger 配置,名字随便定,每个服务可以有多个 Logger,可使用 log.Get("custom").Debug("xxx") 打日志
   585    - writer: file  # 你自定义的 core 配置,名字随便定
   586      caller_skip: 1  # 用于定位日志的调用处
   587      level: debug  # 你自定义 core 输出的级别
   588      writer_config:  # 本地文件输出具体配置
   589        filename: ../log/trpc1.log  # 本地文件滚动日志存放的路径
   590  ```
   591  
   592  要注意 `caller_skip` 放置的位置(不要放在 `writer_config` 里面),并且对于多个 `writer` 都有 `caller_skip` 时,该 Logger 的 `caller_skip` 的值以最后一个为准,比如:
   593  
   594  ```yaml
   595  custom:  # 你自定义的 Logger 配置,名字随便定,每个服务可以有多个 Logger,可使用 log.Get("custom").Debug("xxx") 打日志
   596    - writer: file  # 你自定义的 core 配置,名字随便定
   597      caller_skip: 1  # 用于定位日志的调用处
   598      level: debug  # 你自定义的 core 输出的级别
   599      writer_config:  # 本地文件输出具体配置
   600        filename: ../log/trpc1.log  # 本地文件滚动日志存放的路径
   601    - writer: file  # 本地文件日志
   602      caller_skip: 2  # 用于定位日志的调用处
   603      level: debug  # 本地文件滚动日志的级别
   604      writer_config:  # 本地文件输出具体配置
   605        filename: ../log/trpc2.log  # 本地文件滚动日志存放的路径
   606  ```
   607  
   608  最终 `custom` 这个 Logger 的 `caller_skip` 值会被设置为 2。
   609  
   610  **注意:** 上述用法 2 和用法 3 是冲突的,只能同时用其中的一种。