GoFrame 框架:日志配置管理

发表于:2022-5-09 09:35

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:尹东勋    来源:稀土掘金

  安装
  go get github.com/rookie-ninja/rk-boot/gf
  
  简述概念
  rk-boot 使用如下两个库管理日志。
  ·zap 管理日志实例
  · lumberjack 管理日志滚动
  rk-boot 定义了两种日志类型,会在后面详细介绍,这里先做个简短介绍。
  · ZapLogger: 标准日志,用于记录 Error, Info 等。
  · EventLogger: JSON 或者 Console 格式,用于记录 Event,例如 RPC 请求。
  快速开始
  在这个例子中,我们会试着改变 zap 日志的路径和格式。
  1.创建 boot.yaml
  ---
  zapLogger:
    - name: zap-log                        # Required
      zap:
        encoding: json                     # Optional, options: console, json
        outputPaths: ["logs/zap.log"]      # Optional
  gf:
    - name: greeter
      port: 8080
      enabled: true
  
  2.创建 main.go
  往 zap-log 日志实例中写个日志。
  // Copyright (c) 2021 rookie-ninja
  //
  // Use of this source code is governed by an Apache-style
  // license that can be found in the LICENSE file.
  package main
  import (
  "context"
  "github.com/rookie-ninja/rk-boot"
  _ "github.com/rookie-ninja/rk-boot/gf"
  )
  func main() {
  // Create a new boot instance.
  boot := rkboot.NewBoot()
  // Bootstrap
  boot.Bootstrap(context.Background())
  // Write zap log
  boot.GetZapLoggerEntry("zap-log").GetLogger().Info("This is zap-log")
  // Wait for shutdown sig
  boot.WaitForShutdownSig(context.Background())
  }
  
  3.验证
  文件夹结构
  ├── boot.yaml
  ├── go.mod
  ├── go.sum
  ├── logs
  │   └── zap.log
  └── main.go
  
  日志输出
  {"level":"INFO","ts":"2021-10-21T02:10:09.279+0800","msg":"This is zap-log"}
  
  配置 EventLogger
  上面的例子中,我们配置了 zap 日志,这回我们修改一下 EventLogger。
  1.创建 boot.yaml
  ---
  eventLogger:
    - name: event-log                      # Required
      encoding: json                       # Optional, options: console, json
      outputPaths: ["logs/event.log"]      # Optional
  gf:
    - name: greeter
      port: 8080
      enabled: true
  
  2.创建 main.go
  往 event-log 实例中写入日志。
  package main
  import (
  "context"
  "github.com/rookie-ninja/rk-boot"
  "github.com/rookie-ninja/rk-entry/entry"
  )
  func main() {
  // Create a new boot instance.
  boot := rkboot.NewBoot()
  // Bootstrap
  boot.Bootstrap(context.Background())
  // Write event log
  helper := boot.GetEventLoggerEntry("event-log").GetEventHelper()
  event := helper.Start("demo-event")
  event.AddPair("key", "value")
  helper.Finish(event)
  // Wait for shutdown sig
  boot.WaitForShutdownSig(context.Background())
  }
  
  3.启动 main.go
  $ go run main.go
  
  4.验证
  文件夹结构
  ├── boot.yaml
  ├── go.mod
  ├── go.sum
  ├── logs
  │   └── event.log
  └── main.go
 
  日志内容
  {"endTime": "2022-01-18T22:18:44.926+0800", "startTime": "2022-01-18T22:18:44.926+0800", "elapsedNano": 746, "timezone": "CST", "ids": {"eventId":"2aaea6f5-c7ac-4245-ac50-857726f3ede4"}, "app": {"appName":"rk","appVersion":"","entryName":"","entryType":""}, "env": {"arch":"amd64","az":"*","domain":"*","hostname":"lark.local","localIP":"10.8.0.2","os":"darwin","realm":"*","region":"*"}, "payloads": {}, "error": {}, "counters": {}, "pairs": {"key":"value"}, "timing": {}, "remoteAddr": "localhost", "operation": "demo-event", "eventStatus": "Ended", "resCode": "OK"}
  
  概念
  上面的例子中,我们尝试了 ZapLogger 和 EventLogger。接下来我们看看 rk-boot 是如何实现的,并且怎么使用。
  架构
  ZapLoggerEntry
  ZapLoggerEntry 是 zap 实例的一个封装。
  // ZapLoggerEntry contains bellow fields.
  // 1: EntryName: Name of entry.
  // 2: EntryType: Type of entry which is ZapLoggerEntryType.
  // 3: EntryDescription: Description of ZapLoggerEntry.
  // 4: Logger: zap.Logger which was initialized at the beginning.
  // 5: LoggerConfig: zap.Logger config which was initialized at the beginning which is not accessible after initialization..
  // 6: LumberjackConfig: lumberjack.Logger which was initialized at the beginning.
  type ZapLoggerEntry struct {
  EntryName        string             `yaml:"entryName" json:"entryName"`
  EntryType        string             `yaml:"entryType" json:"entryType"`
  EntryDescription string             `yaml:"entryDescription" json:"entryDescription"`
  Logger           *zap.Logger        `yaml:"-" json:"-"`
  LoggerConfig     *zap.Config        `yaml:"zapConfig" json:"zapConfig"`
  LumberjackConfig *lumberjack.Logger `yaml:"lumberjackConfig" json:"lumberjackConfig"`
  }
 
  如何在 boot.yaml 里配置 ZapLoggerEntry?
  ZapLoggerEntry 完全兼容 zap 和 lumberjack 的 YAML 结构。
  用户可以根据需求,配置多个 ZapLogger 实例,并且通过 name 来访问。
  完整配置:
  ---
  zapLogger:
    - name: zap-logger                      # Required
      description: "Description of entry"   # Optional
      zap:
        level: info                         # Optional, default: info, options: [debug, DEBUG, info, INFO, warn, WARN, dpanic, DPANIC, panic, PANIC, fatal, FATAL]
        development: true                   # Optional, default: true
        disableCaller: false                # Optional, default: false
        disableStacktrace: true             # Optional, default: true
        sampling:                           # Optional, default: empty map
          initial: 0
          thereafter: 0
        encoding: console                   # Optional, default: "console", options: [console, json]
        encoderConfig:
          messageKey: "msg"                 # Optional, default: "msg"
          levelKey: "level"                 # Optional, default: "level"
          timeKey: "ts"                     # Optional, default: "ts"
          nameKey: "logger"                 # Optional, default: "logger"
          callerKey: "caller"               # Optional, default: "caller"
          functionKey: ""                   # Optional, default: ""
          stacktraceKey: "stacktrace"       # Optional, default: "stacktrace"
          lineEnding: "\n"                  # Optional, default: "\n"
          levelEncoder: "capitalColor"      # Optional, default: "capitalColor", options: [capital, capitalColor, color, lowercase]
          timeEncoder: "iso8601"            # Optional, default: "iso8601", options: [rfc3339nano, RFC3339Nano, rfc3339, RFC3339, iso8601, ISO8601, millis, nanos]
          durationEncoder: "string"         # Optional, default: "string", options: [string, nanos, ms]
          callerEncoder: ""                 # Optional, default: ""
          nameEncoder: ""                   # Optional, default: ""
          consoleSeparator: ""              # Optional, default: ""
        outputPaths: [ "stdout" ]           # Optional, default: ["stdout"], stdout would be replaced if specified
        errorOutputPaths: [ "stderr" ]      # Optional, default: ["stderr"], stderr would be replaced if specified
        initialFields:                      # Optional, default: empty map
          key: "value"
      lumberjack:                           # Optional
        filename: "rkapp-event.log"         # Optional, default: It uses <processname>-lumberjack.log in os.TempDir() if empty.
        maxsize: 1024                       # Optional, default: 1024 (MB)
        maxage: 7                           # Optional, default: 7 (days)
        maxbackups: 3                       # Optional, default: 3 (days)
        localtime: true                     # Optional, default: true
        compress: true                      # Optional, default: true
  
  如何在代码里获取 ZapLogger?
  通过 name 来访问。
  boot := rkboot.NewBoot()
  // Access entry
  boot.GetZapLoggerEntry("zap-logger")
  // Access zap logger
  boot.GetZapLoggerEntry("zap-logger").GetLogger()
  // Access zap logger config
  boot.GetZapLoggerEntry("zap-logger").GetLoggerConfig()
  // Access lumberjack config
  boot.GetZapLoggerEntry("zap-logger").GetLumberjackConfig()
  
  EventLoggerEntry
  rk-boot 把每一个 RPC 请求看作一个 Event,并且使用 rk-query 中的 Event 类型来记录日志。
  // EventLoggerEntry contains bellow fields.
  // 1: EntryName: Name of entry.
  // 2: EntryType: Type of entry which is EventLoggerEntryType.
  // 3: EntryDescription: Description of EventLoggerEntry.
  // 4: EventFactory: rkquery.EventFactory was initialized at the beginning.
  // 5: EventHelper: rkquery.EventHelper was initialized at the beginning.
  // 6: LoggerConfig: zap.Config which was initialized at the beginning which is not accessible after initialization.
  // 7: LumberjackConfig: lumberjack.Logger which was initialized at the beginning.
  type EventLoggerEntry struct {
  EntryName        string                `yaml:"entryName" json:"entryName"`
  EntryType        string                `yaml:"entryType" json:"entryType"`
  EntryDescription string                `yaml:"entryDescription" json:"entryDescription"`
  EventFactory     *rkquery.EventFactory `yaml:"-" json:"-"`
  EventHelper      *rkquery.EventHelper  `yaml:"-" json:"-"`
  LoggerConfig     *zap.Config           `yaml:"zapConfig" json:"zapConfig"`
  LumberjackConfig *lumberjack.Logger    `yaml:"lumberjackConfig" json:"lumberjackConfig"`
  }
  
  EventLogger 字段
  我们可以看到 EventLogger 打印出来的日志里,包含字段,介绍一下这些字段。

  例子
  ------------------------------------------------------------------------
  endTime=2021-11-27T02:30:27.670807+08:00
  startTime=2021-11-27T02:30:27.670745+08:00
  elapsedNano=62536
  timezone=CST
  ids={"eventId":"4bd9e16b-2b29-4773-8908-66c860bf6754"}
  app={"appName":"gf-demo","appVersion":"master-f948c90","entryName":"greeter","entryType":"GfEntry"}
  env={"arch":"amd64","az":"*","domain":"*","hostname":"lark.local","localIP":"10.8.0.6","os":"darwin","realm":"*","region":"*"}
  payloads={"apiMethod":"GET","apiPath":"/rk/v1/healthy","apiProtocol":"HTTP/1.1","apiQuery":"","userAgent":"curl/7.64.1"}
  error={}
  counters={}
  pairs={}
  timing={}
  remoteAddr=localhost:61726
  operation=/rk/v1/healthy
  resCode=200
  eventStatus=Ended
  EOE
  
  如何在 boot.yaml 里配置 EventLoggerEntry?
  EventLoggerEntry 将会把 Application 名字注入到 Event 中。启动器会从 go.mod 文件中提取 Application 名字。 如果没有 go.mod 文件,启动器会使用默认的名字。
  用户可以根据需求,配置多个 EventLogger 实例,并且通过 name 来访问。
  完整配置:
  ---
  eventLogger:
    - name: event-logger                 # Required
      description: "This is description" # Optional
      encoding: console                  # Optional, default: console, options: console and json
      outputPaths: ["stdout"]            # Optional
      lumberjack:                        # Optional
        filename: "rkapp-event.log"      # Optional, default: It uses <processname>-lumberjack.log in os.TempDir() if empty.
        maxsize: 1024                    # Optional, default: 1024 (MB)
        maxage: 7                        # Optional, default: 7 (days)
        maxbackups: 3                    # Optional, default: 3 (days)
        localtime: true                  # Optional, default: true
        compress: true                   # Optional, default: true
  
  如何在代码里获取 EventLogger?
  通过 name 来访问。
  boot := rkboot.NewBoot()
  // Access entry
  boot.GetEventLoggerEntry("event-logger")
  // Access event factory
  boot.GetEventLoggerEntry("event-logger").GetEventFactory()
  // Access event helper
  boot.GetEventLoggerEntry("event-logger").GetEventHelper()
  // Access lumberjack config
  boot.GetEventLoggerEntry("event-logger").GetLumberjackConfig()
  
  如何使用 Event?
  Event 是一个 interface,包含了若干方法,请参考:Event
  常用方法:
  boot := rkboot.NewBoot()
  // Get EventHelper to create Event instance
  helper := boot.GetEventLoggerEntry("event-log").GetEventHelper()
  // Start and finish event
  event := helper.Start("demo-event")
  helper.Finish(event)
  // Add K/V
  event.AddPair("key", "value")
  // Start and end timer
  event.StartTimer("my-timer")
  event.EndTimer("my-timer")
  // Set counter
  event.SetCounter("my-counter", 1)

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号