Go中的应用程序日志记录模式是什么?如果我有5个goroutines,我需要登录,我应该......
log.Logger
并传递它?log.Logger
?答案 0 :(得分:44)
- 创建一个log.Logger并传递它?
这是可能的。可以从多个goroutine中同时使用log.Logger。
- 传递指向该log.Logger的指针?
log.New返回*Logger
,这通常表示您应该将对象作为指针传递。将其作为值传递将创建结构的副本(即Logger的副本),然后多个goroutine可以同时写入同一io.Writer。这可能是一个严重的问题,取决于作者的实施。
- 每个goroutine或函数都应该创建一个记录器吗?
我不会为每个函数或goroutine创建一个单独的记录器。 Goroutines(和函数)用于非常轻量级的任务,不能证明维护单独的记录器是合理的。为项目的每个更大的组件创建一个记录器可能是个好主意。例如,如果您的项目使用SMTP服务发送邮件,那么为邮件服务创建单独的记录器听起来是个好主意,这样您就可以单独过滤和关闭输出。
- 我应该将记录器创建为全局变量吗?
这取决于你的包裹。在上一个邮件服务示例中,为每个服务实例配置一个记录器可能是个好主意,这样用户可以在使用gmail邮件服务时记录失败,而不是使用本地MTA时发生的故障(例如sendmail) )。
答案 1 :(得分:32)
对于简单的情况,日志包中定义了一个全局记录器log.Logger
。可以通过log.SetFlags
配置此全局记录器。
之后可以调用日志包的顶级函数,如log.Printf
和log.Fatalf
,它们使用该全局实例。
答案 2 :(得分:8)
我知道这个问题有点旧,但是,如果像我一样,你的项目是由多个较小的文件组成的,我投票给你的第四个选项 - 我创建了一个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)
}
答案 3 :(得分:5)
这是一个简单的记录器
ARGV
你可以这样使用它
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),
}
}
答案 4 :(得分:3)
这是一个较旧的问题,但我想建议使用http://github.com/romana/rlog(我们开发的)。它通过环境变量配置,在导入rlog时创建并初始化logger对象。因此,无需绕过记录器。
rlog有很多功能:
它非常小,没有外部依赖,除了标准的Golang库,并且正在积极开发。回购中提供了示例。
答案 5 :(得分:2)
我发现默认日志包(https://golang.org/pkg/log/)有些限制。例如,不支持信息与调试日志 经过一番探讨后,决定使用https://github.com/golang/glog。这似乎是https://github.com/google/glog的一个端口,并且在日志记录方面提供了相当大的灵活性。例如,在本地运行应用程序时,您可能需要DEBUG级别日志,但可能只想在生产中的INFO / ERROR级别运行。完整功能/指南的列表是https://google-glog.googlecode.com/svn/trunk/doc/glog.html(它用于c ++模块,但大部分转换为golang端口)
答案 6 :(得分:0)
您可以考虑的日志记录模块之一是klog。它支持“ V”记录,从而可以灵活地记录特定级别的
klog是glog的分支,并克服了以下缺点
示例实施
package main
import (
"flag"
"k8s.io/klog"
)
type myError struct {
str string
}
func (e myError) Error() string {
return e.str
}
func main() {
klog.InitFlags(nil)
flag.Set("v", "1")
flag.Parse()
klog.Info("hello", "val1", 1, "val2", map[string]int{"k": 1})
klog.V(3).Info("nice to meet you")
klog.Error(nil, "uh oh", "trouble", true, "reasons", []float64{0.1, 0.11, 3.14})
klog.Error(myError{"an error occurred"}, "goodbye", "code", -1)
klog.Flush()
}