所以我使用了结构化日志库(logrus),并且我有一个core
包用作其他包的基础,我们可以调用此包me/core
,然后单独的包,如me/foo-service
,me/bar-service
等使用此核心库的常见依赖/实用程序,如设置,配置加载,我也想用它来标准化的事情,如日志记录,所以我希望me/core
能够为其他软件包配置日志记录,使用Logrus可以执行
import(
log "github.com/Sirupsen/logrus"
)
[...]
log.SetLevel(log.DebugLevel)
log.SetFormatter(&log.TextFormatter{FullTimestamp:true})
然后做;
log.Debug("Moo")
log.WithFields(log.Fields{"structured":"data"}).Debug("I have structure data")
获得类似
的输出> DEBU[2016-04-12T22:11:38+01:00] Moo
> DEBU[2016-04-12T22:11:38+01:00] I have structure data structured=data
所以我想在我的me/foo-service
包中配置类似
import(
"me/core/logging"
)
func main(){
logging.Setup()
}
只是出于各种原因我遇到了问题。主要问题似乎是me/core
和me/foo-service
都有logrus
库的托管版本,那些log.Set*
命令会修改变量logrus.std
记录器拥有标准的全局记录器,但这是两个包的单独实例,因为me/core/vendor/.../logrus/std
和me/foo-service/vendor/.../logrus/std
是不同的对象。
我尝试的第一件事是在me/core/logging
中创建一个我可以在父级中使用的变量,所以类似
package logging
import(
log "github.com/Sirupsen/logrus"
)
var Log *log.Logger
func Setup(verbose bool){
Log = log.New()
if verbose{
Log.Level = log.DebugLevel
} else {
Log.Level = log.InfoLevel
}
Log.Formatter = &log.TextFormatter{FullTimestamp:true}
Log.Debug("Logging verbosely")
}
这适用于像这样的简单案例
package main
import(
"me/core/logging"
)
func main() {
logging.Setup(parsedOptions.Verbose)
logging.Log.Debug("Moo")
}
但是,尝试使用结构化数据Fields
会导致问题,我无法使用本地出售的logrus
字段,例如
logging.Log.WithFields(log.Fields{"data":"hi"}).Debug("test")
我得到了
cannot use "me/foo-service/vendor/github.com/Sirupsen/logrus".Fields literal (type "me/foo-service/vendor/github.com/Sirupsen/logrus".Fields) as type "me/core/vendor/github.com/Sirupsen/logrus".Fields in argument to logging.Log.WithFields
尝试使用
之类的内容镜像me/core/logging
中的字段
type Fields log.Fields
没有工作以太,因为它仍然是一个不同的类型
cannot use logging.Fields literal (type logging.Fields) as type "me/core/vendor/github.com/Sirupsen/logrus".Fields in argument to logging.Log.WithFields
我也无法考虑将本地log.std
从me/foo-service
传递到me/core
的任何方式,因为它的销售包装也是另一种类型
我目前的工作涉及创建每个方法的镜像,所以在me/core/logging
我有一个像
package logging
import(
log "github.com/Sirupsen/logrus"
)
var Log *log.Logger
type Fields map[string]interface{}
func Setup(verbose bool){
Log = log.New()
if verbose{
Log.Level = log.DebugLevel
} else {
Log.Level = log.InfoLevel
}
Log.Formatter = &log.TextFormatter{FullTimestamp:true}
Log.Debug("Logging verbosely")
}
func Debug(msg interface{}){
Log.Debug(msg)
}
func WithFields(fields Fields) *log.Entry{
lf := log.Fields{}
for k,v := range fields{
lf[k] = v
}
return Log.WithFields(lf)
}
但这会涉及为每个方法创建一个镜像,这似乎效率很低。
因此,我想了解如何me/core/vendor/.../logrus/std
可以me/foo-service
使用,或者如果我以完全错误的方式考虑这个问题,我可以采取更好的方法它
答案 0 :(得分:1)
您只能镜像WithFields
,因为其他人接受内置类型。此外,由于logging.Fields
和logrus.Fields
属于同一类型,因此您可以更简单地执行
func WithFields(f Fields) log.*Entry {
return Log.WithFields(log.Fields(f))
}
然后在您的服务中,您可以致电
logging.Log.Debug("message")
logging.WithFields(logging.Fields{"k":"v"}).Debug("message")