正确处理Golang中的全局日志记录

Car*_*son 106 logging go

Go中的应用程序日志记录模式是什么?如果我有5个goroutines我需要登录,我应该......

  • 创建一个log.Logger并传递它?
  • 传递指向那个log.Logger
  • 每个goroutine或函数应该创建一个记录器吗?
  • 我应该将记录器创建为全局变量吗?

tux*_*21b 52

  • 创建一个log.Logger并传递它?

这是可能的.甲log.Logger可以同时从多个够程中使用.

  • 传递指向该log.Logger的指针?

log.New返回一个*Logger通常表示你应该将对象作为指针传递的指示.将其作为值传递将创建结构的副本(即Logger的副本),然后多个goroutine可能同时写入同一个io.Writer.这可能是一个严重的问题,取决于作者的实施.

  • 每个goroutine或函数应该创建一个记录器吗?

我不会为每个函数或goroutine创建一个单独的记录器.Goroutines(和函数)用于非常轻量级的任务,不能证明维护单独的记录器是合理的.为项目的每个更大的组件创建一个记录器可能是个好主意.例如,如果您的项目使用SMTP服务发送邮件,则为邮件服务创建单独的记录器听起来是个好主意,以便您可以单独过滤和关闭输出.

  • 我应该将记录器创建为全局变量吗?

这取决于你的包裹.在上一个邮件服务示例中,为每个服务实例配置一个记录器可能是个好主意,这样用户可以在使用gmail邮件服务时记录失败,而不是使用本地MTA时发生的故障(例如sendmail) ).


zzz*_*zzz 33

对于简单的情况,日志包中定义了一个全局记录器log.Logger.可以通过配置此全局记录器log.SetFlags.

后来一个可以叫日志包等顶级功能log.Printflog.Fatalf,其中使用全局实例.


Isr*_*rba 14

这是一个简单的记录器

package customlogger

import (
    "log"
    "os"
    "sync"
)

type logger struct {
    filename string
    *log.Logger
}

var logger *logger
var once sync.Once

// start loggeando
func GetInstance() *logger {
    once.Do(func() {
        logger = createLogger("mylogger.log")
    })
    return logger
}

func createLogger(fname string) *logger {
    file, _ := os.OpenFile(fname, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)

    return &logger{
        filename: fname,
        Logger:   log.New(file, "My app Name ", log.Lshortfile),
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以这样使用它

package main

import (
    "customlogger"
    "fmt"
    "net/http"
)

func main() {
    logger := customlogger.GetInstance()
    logger.Println("Starting")

    http.HandleFunc("/", sroot)
    http.ListenAndServe(":8080", nil)
}

func sroot(w http.ResponseWriter, r *http.Request) {
    logger := customlogger.GetInstance()

    fmt.Fprintf(w, "welcome")
    logger.Println("Starting")
}
Run Code Online (Sandbox Code Playgroud)


Omo*_*tis 9

我知道这个问题有点陈旧,但是,如果像我一样,你的项目是由多个较小的文件组成的,我会投票给你的第四个选项 - 我已经创建了一个logger.go包主体的一部分.此go文件创建记录器,将其分配给文件,并将其提供给main的其余部分.注意我还没有想出一个优雅的方法来关闭errorlog ...

package main

import (
    "fmt"
    "log"
    "os"
)

var errorlog *os.File
var logger *log.Logger

func init() {
    errorlog, err := os.OpenFile(logfile,  os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    if err != nil {
        fmt.Printf("error opening file: %v", err)
        os.Exit(1)
    }

    logger = log.New(errorlog, "applog: ", log.Lshortfile|log.LstdFlags)
}
Run Code Online (Sandbox Code Playgroud)

  • 为了优雅的结束,您可以在执行结束时"推迟errorlog.Close()",或者使用Go的信号包https://golang.org/pkg/os/signal/更好地确保其关闭的设置信号处理程序 (7认同)