日志组件是GoFrame框架核心的组件之一,支持非常方便的配置管理能力。

配置文件(推荐)

日志的配置使用的是框架统一的配置组件,支持多种文件格式,也支持配置中心、接口化扩展等特性,更多细节请参考章节:配置管理

日志组件支持配置文件,当使用g.Log(单例名称)获取Logger单例对象时,将会自动通过默认的配置管理对象获取对应的Logger配置。默认情况下会读取logger.单例名称配置项,当该配置项不存在时,将会读取默认的logger配置项。配置项请参考配置对象结构定义:https://pkg.go.dev/github.com/gogf/gf/v2/os/glog#Config

完整配置文件配置项及说明如下,其中配置项名称不区分大小写:

logger:
  path:                  "/var/log/"           # 日志文件路径。默认为空,表示关闭,仅输出到终端
  file:                  "{Y-m-d}.log"         # 日志文件格式。默认为"{Y-m-d}.log"
  prefix:                ""                    # 日志内容输出前缀。默认为空
  level:                 "all"                 # 日志输出级别
  timeFormat:            "2006-01-02T15:04:05" # 自定义日志输出的时间格式,使用Golang标准的时间格式配置
  ctxKeys:               []                    # 自定义Context上下文变量名称,自动打印Context的变量到日志中。默认为空
  header:                true                  # 是否打印日志的头信息。默认true
  stdout:                true                  # 日志是否同时输出到终端。默认true
  rotateSize:            0                     # 按照日志文件大小对文件进行滚动切分。默认为0,表示关闭滚动切分特性
  rotateExpire:          0                     # 按照日志文件时间间隔对文件滚动切分。默认为0,表示关闭滚动切分特性
  rotateBackupLimit:     0                     # 按照切分的文件数量清理切分文件,当滚动切分特性开启时有效。默认为0,表示不备份,切分则删除
  rotateBackupExpire:    0                     # 按照切分的文件有效期清理切分文件,当滚动切分特性开启时有效。默认为0,表示不备份,切分则删除
  rotateBackupCompress:  0                     # 滚动切分文件的压缩比(0-9)。默认为0,表示不压缩
  rotateCheckInterval:   "1h"                  # 滚动切分的时间检测间隔,一般不需要设置。默认为1小时
  stdoutColorDisabled:   false                 # 关闭终端的颜色打印。默认开启
  writerColorEnable:     false                 # 日志文件是否带上颜色。默认false,表示不带颜色

其中,level配置项使用字符串配置,按照日志级别支持以下配置:DEBU < INFO < NOTI < WARN < ERRO < CRIT,也支持ALL, DEV, PROD常见部署模式配置名称。level配置项字符串不区分大小写。关于日志级别的详细介绍请查看 日志组件-日志级别 章节。

示例1,默认配置项

logger:
  path:    "/var/log"
  level:   "all"
  stdout:  false

随后可以使用g.Log()获取默认的单例对象时自动获取并设置该配置。

示例2,多个配置项

多个Logger的配置示例:

logger:
  path:    "/var/log"
  level:   "all"
  stdout:  false
  logger1:
    path:    "/var/log/logger1"
    level:   "dev"
    stdout:  false
  logger2:
    path:    "/var/log/logger2"
    level:   "prod"
    stdout:  true

我们可以通过单例对象名称获取对应配置的Logger单例对象:

// 对应 logger.logger1 配置项
l1 := g.Log("logger1")
// 对应 logger.logger2 配置项
l2 := g.Log("logger2")
// 对应默认配置项 logger
l3 := g.Log("none")
// 对应默认配置项 logger
l4 := g.Log()

配置方法(高级)

配置方法用于模块化使用glog时由开发者自己进行配置管理。

方法列表:

简要说明:

  1. 可以通过SetConfigSetConfigWithMap来设置。
  2. 也可以使用Logger对象的Set*方法进行特定配置的设置。
  3. 主要注意的是,配置项在Logger对象执行日志输出之前设置,避免并发安全问题。

我们可以使用SetConfigWithMap方法通过Key-Value键值对来设置/修改Logger的特定配置,其余的配置使用默认配置即可。其中Key的名称即是Config这个struct中的属性名称,并且不区分大小写,单词间也支持使用-/_/空格符号连接,具体可参考 类型转换-Struct转换 章节的转换规则。

简单示例:

logger := glog.New()
logger.SetConfigWithMap(g.Map{
    "path":     "/var/log",
    "level":    "all",
    "stdout":   false,
    "StStatus": 0,
})
logger.Print("test")

其中StStatus表示是否开启堆栈打印,设置为0表示关闭。键名也可以使用stStatus, st-status, st_status, St Status,其他配置属性以此类推。

注意事项

常见问题:如日志组件的配置为何没有对HTTP ServerGRPC ServerORM组件打印的日志生效。

GoFrame框架采用了模块化设计,日志组件是框架独立的组件,本章节介绍的配置均只对独立使用日志组件的方式生效,例如使用g.Log()或者glog.New()方法创建的日志组件。其他组件的日志配置有专门的配置项,或者日志对象设置方法来实现日志的配置,请具体查看对应的组件文档和API




Content Menu

  • No labels

12 Comments

  1. 请问现在能支持输出格式的控制吗,例如把ctxKeys的输出放到日志行的末尾?

  2. 海亮 郭强 日志配置项stdout=false不生效,且server启动的信息没有写入日志文件,以下是我的配置文件:

    # HTTP Server.
    [server]
    	address        = "0.0.0.0:8199"
    	serverAgent    = "My GoFrame HTTP Server"
        openapiPath    = "/api.json"
        swaggerPath    = "/redoc" # /swagger使用本地静态文件实现,所以此处不能设置路径为/swagger
        lang           = "zh-CN"  # 与i18n文件名对应,zh-CN、en目前只支持这2个
        serverRoot     = "/resource/public"  # 开启静态文件目录,支持swaggerUI
    
    # Logger configurations.
    [logger]
        path   = "log/"
        level  = "all"
        rotateExpire = "1d"  # 一天一个回滚
        rotateBackupLimit =  1   # 保留1个日志文件
        writerColorEnable = true  # 日志文件带有颜色
        RotateBackupCompress =  9  # 日志文件压缩级别,0-9,9最高
        stdout = false
        Flags = 44 #日期 时:分:秒:毫秒 文件:行号
    
    [token]
        timeout = 600000  # 单位:毫秒
        cacheMode = 1  # 使用的缓存模式,1为内存模式,2为redis模式,默认为1
    
    # Redis数据库配置
    [redis.default]
        address = "192.168.212.117:6379"
        db      = 0
        pass    = "7a38d7c46ca4798c7767"
    
    # Database configurations.
    [database]
        link  = "mysql:root:mysql@tcp(192.168.212.117:3306)/mygf"
        debug = true
    
    # GF-CLI工具配置
    [gfcli]
        # 自定义DAO生成配置(默认是读取database配置)
        [[gfcli.gen.dao]]
            link   = "mysql:root:mysql@tcp(192.168.212.117:3306)/mygf"
            descriptionTag =   true
            noModelComment =   true
            removePrefix =     "gf_"
        [gfcli.build]
            name=      "my-goframe"
            path=      "./bin"
            arch=      "amd64"
            system=    "windows,linux"
            mod=       "none"
            cgo=       0
            pack=      "manifest/config,resource/i18n"
            version=   ""
            output=    ""
            extra=     ""
      1. 配置文件中的日志组件配置需要使用g.Log()单例对象时才会自动读取并初始化配置,使用glog包方法打印日志时不会自动读取配置文件,两者区别请参考:日志组件
      2. 如果想要配置Server中的Logger,请参考:服务配置-配置文件模板
      1. 郭强 我自己的代码中使用的g.Log()单例对象操作的,并且这些log也按照我的期望实现了,但是有很多的gf系统日志,却没有按照我上一个提问贴出来的配置实现,比如以下的:

        2022-05-07 11:35:20.949 [DEBU] SetServerRoot path: /root/go-workspace/MyGoFrame/myapp/resource/public
        2022-05-07 11:35:20.958 [INFO] swagger ui is serving at address: http://0.0.0.0:8199/redoc/
        2022-05-07 11:35:20.958 [INFO] openapi specification is serving at address: http://0.0.0.0:8199/api.json
        2022-05-07 11:35:20.959 [INFO] pid[22663]: http server started listening on [0.0.0.0:8199]
        
            ADDRESS    | METHOD |      ROUTE       |                             HANDLER                             |            MIDDLEWARE             
        ---------------|--------|------------------|-----------------------------------------------------------------|-----------------------------------
          0.0.0.0:8199 | ALL    | /*               | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE                 
        ---------------|--------|------------------|-----------------------------------------------------------------|-----------------------------------
        ...省略...

        我期望:日志全部写入文件,标准输出不再有任何输出,但是目前实验了各种姿势,都没有实现。

        以下是我最终的版本,但是依然输出了server启动等的信息,其他的信息已经如愿只写入文件,不输出到标准输出。

        # HTTP Server.
        [server]
        	address        = "0.0.0.0:8199"
        	serverAgent    = "My GoFrame HTTP Server"
            openapiPath    = "/api.json"
            swaggerPath    = "/redoc" # /swagger使用本地静态文件实现,所以此处不能设置路径为/swagger
            lang           = "zh-CN"  # 与i18n文件名对应,zh-CN、en目前只支持这2个
            serverRoot     = "/resource/public"  # 开启静态文件目录,支持swaggerUI
        
            logPath             = "/var/log/my-goframe/"
            accessLogEnabled    = true
            accessLogPattern    = "{Y-m-d}.log"
            errorLogPattern     = "error-{Y-m-d}.log"
            logStdout           = false  # 禁用标准输出,只输出到文件
        
        [logger]
            path   = "/var/log/my-goframe/"
            file   = "{Y-m-d}.log"
            level  = "all"
            rotateExpire = "1d"  # 一天一个回滚
            rotateBackupLimit =  7   # 保留7个日志文件
            writerColorEnable = true  # 日志文件带有颜色
            RotateBackupCompress =  9  # 日志文件压缩级别,0-9,9最高
            stdout = false  # 禁用标准输出,只输出到文件
            Flags = 44 #日期 时:分:秒:毫秒 文件:行号
        
        [token]
            timeout = 600000  # 单位:毫秒,10分钟
            cacheMode = 1  # 使用的缓存模式,1为内存模式,2为redis模式,默认为1
        
        # Redis数据库配置
        [redis.default]
            address = "192.168.212.117:6379"
            db      = 0
            pass    = "7a38d7c46ca4798c7767"
        
        # Database configurations.
        [database]
            [database.logger]
                path =    "/var/log/my-goframe/"
                level =   "all"
                stdout =  false
            [database.default]
                link  = "mysql:root:mysql@tcp(192.168.212.117:3306)/mygf"
                debug = true
        
        # GF-CLI工具配置
        [gfcli]
            # 自定义DAO生成配置(默认是读取database配置)
            [[gfcli.gen.dao]]
                link   = "mysql:root:mysql@tcp(192.168.212.117:3306)/mygf"
                descriptionTag =   true
                noModelComment =   true
                removePrefix =     "gf_"
            [gfcli.build]
                name=      "my-goframe"
                path=      "./bin"
                arch=      "amd64"
                system=    "windows,linux"
                mod=       "none"
                cgo=       0
                pack=      "manifest/config,resource/i18n"
                version=   ""
                output=    ""
                extra=     ""
        1. log在3个地方配置:server、logger、database;感觉很重复
        2. 即使把三个地方的Stdout都禁止,依然在标准输出有输出
        1. 有的组件是直接调用glog的包方法来实现的日志打印,这块是不受业务层配置控制的,但是可以按照以下两种方式修改默认逻辑:

          1. 通过glog.DefaultLogger获取包方法默认的Logger对象,然后设置其配置,则所有组件使用glog包方法打印都会受控制。
          2. 通过v2.1以上版本(目前可以尝试master分支)的glog.SetDefaultHandler设置全局的自定义处理方法来实现自定义日志打印。
          1. 赞,搞定了。我的最终配置文件如下:

            [server]
            	address        = "0.0.0.0:8199"
            	serverAgent    = "My GoFrame HTTP Server"
                openapiPath    = "/api.json"
                swaggerPath    = "/redoc" # /swagger使用本地静态文件实现,所以此处不能设置路径为/swagger
                lang           = "zh-CN"  # 与i18n文件名对应,zh-CN、en目前只支持这2个
                serverRoot     = "/resource/public"  # 开启静态文件目录,支持swaggerUI
            
                errorLogPattern     = "error-{Y-m-d}.log"
            
            [logger]
                path   = "log/"
                file   = "{Y-m-d}.log"
                level  = "all"
                rotateExpire = "1d"  # 一天一个回滚
                rotateBackupLimit =  7   # 保留7个日志文件
                writerColorEnable = true  # 日志文件带有颜色
                RotateBackupCompress =  9  # 日志文件压缩级别,0-9,9最高
                stdout = false  # 禁用标准输出,只输出到文件
                Flags = 44 #日期 时:分:秒:毫秒 文件:行号
            
            [database]
                [database.default]
                    link  = "mysql:root:mysql@tcp(192.168.212.117:3306)/mygf"
                    debug = true

            在cmd.go文件中,设置DefaultHandler

            var (
            	Main = gcmd.Command{
            		Name:  "main",
            		Usage: "main",
            		Brief: "start MyGoFrame server",
            		Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
            			SetDefaultHandler() // 替代默认的log
            
            			s := g.Server()
                        ... 省略...
                    },
            	}
            )
            
            // 替代默认的日志handler,禁止控制台输出,全部输出到文件
            func SetDefaultHandler() {
            	glog.SetDefaultHandler(func(ctx context.Context, in *glog.HandlerInput) {
            		m := map[string]interface{}{
            			"stdout": false,
            			"path":   g.Config().MustGet(ctx, "logger.path", "log/").String(), // 此处必须重新设置,才可以实现db的log写入文件
            		}
            		in.Logger.SetConfigWithMap(m)
            		in.Next(ctx)
            	})
            }
  3. wyy

    glog支持获取配置文件的logger么

    1. wyy

      通过glog.SetDefaultLogger(g.Log())可以实现配置同步,但是测试发现,只能模块内生效

  4. 最新版2.7.1,提了个issue 3620

    rotateExpire 这个配置的时间判断取的是日志文件的修改时间,而不是创建时间,这导致持续有日志写入的日志文件根本不会被切分。

    当然获取文件创建时间的逻辑稍微有点点麻烦:

    finfo, _ := os.Stat("/tmp/access.log")
    g.Dump(gtime.NewFromTime(time.Unix(finfo.Sys().(*syscall.Stat_t).Birthtimespec.Unix())))



  5. 保存文件可以根据日志类型保存不同文件吗

    服务输出正常日志比较多、要找waring和err不太好找

    现在要创建多个logger保存不同的文件,只是为了保存不同的日志类型,有点麻烦

    1. 你可以试试用logger的多个配置项,每个配置项定义不同的路径

      // 对应 logger.logger1 配置项
      l1 := g.Log("logger1")
      // 对应 logger.logger2 配置项
      l2 := g.Log("logger2")
      

      参考多个配置项的内容. 

      日志很多,替换很麻烦的话, 也可以定义个方法, 比容 errorLog("This is a error log") , errorLog 内容还是 g.Log("logger1").Error(ctx, "this is a error log"). 

    2. g.Log().Cat("waring").Info()
      g.Log().Cat("err").Info()