英文:
How to standardize go-kit/kit/log fields
问题
问题
go-kit/log的日志记录接口非常简单明了:
type Logger interface {
Log(keyvals ...interface{}) error
}
但是人们往往以不同的方式思考,并用不同的名称来称呼相同的事物。
我在代码中看到有人将错误文本字段称为"err",而其他人称为"error"。这使得日志难以搜索。你必须同时搜索"err"和"error"。这也可能发生在"msg"或"message"字段上。
有没有办法标准化这样的命名?
英文:
Problem
go-kit/log Logging interface is straightforward and nice
type Logger interface {
Log(keyvals ...interface{}) error
}
But people tend to think in different ways and name the same things with different names.
I see in a code that one calls a field for error text as "err" and other "error". This makes logs difficult to search for. You have to search for both "err" and "error" in the same time. This also can be the case for "msg" or "message" fields.
Is there any way to standardize such naming?
答案1
得分: 3
我会为你翻译以下内容:
我发现建造者模式更加清晰和可读:
type KVBuilder struct {
KeyVals []interface{}
}
func NewKVBuilder() *KVBuilder {
return &KVBuilder{}
}
func (k *KVBuilder) Err(err error) *KVBuilder {
return k.KV("err", err)
}
func (k *KVBuilder) Msg(msg string) *KVBuilder {
return k.KV("msg", msg)
}
func (k *KVBuilder) KV(kv ...interface{}) *KVBuilder {
k.KeyVals = append(k.KeyVals, kv...)
return k
}
使用它:
var logger Logger
logger.Log(NewKVBuilder().
Err(errors.New("foo")).
Msg("bar").
KV("some", "other").
KeyVals...,
)
如果你给 KVBuilder
添加另一个方法:
func (k *KVBuilder) LogTo(logger Logger) error {
return logger.Log(k.KeyVals...)
}
你也可以这样使用它:
NewKVBuilder().
Err(errors.New("foo")).
Msg("bar").
KV("some", "other").
LogTo(logger)
英文:
I'd find a builder pattern cleaner and more readable:
type KVBuilder struct {
KeyVals []interface{}
}
func NewKVBuilder() *KVBuilder {
return &KVBuilder{}
}
func (k *KVBuilder) Err(err error) *KVBuilder {
return k.KV("err", err)
}
func (k *KVBuilder) Msg(msg string) *KVBuilder {
return k.KV("msg", msg)
}
func (k *KVBuilder) KV(kv ...interface{}) *KVBuilder {
k.KeyVals = append(k.KeyVals, kv...)
return k
}
Using it:
var logger Logger
logger.Log(NewKVBuilder().
Err(errors.New("foo")).
Msg("bar").
KV("some", "other").
KeyVals...,
)
And if you add another method to KVBuilder
:
func (k *KVBuilder) LogTo(logger Logger) error {
return logger.Log(k.KeyVals...)
}
You can also use it like this:
NewKVBuilder().
Err(errors.New("foo")).
Msg("bar").
KV("some", "other").
LogTo(logger)
答案2
得分: 2
我看到解决这个问题的三个选项:
1)团队内部的正式约定和一个代码检查工具(linter)来检查它。
2)使用共享的标记包来声明日志字段名称为常量(例如opentracing-go中的示例扩展包)。团队始终使用Log(ext.Message, "log message text", ext.Error, err)
这样的调用。
3)一种语法糖,它隐藏了字段命名的细节。它可以像这样实现(live example):
// 包 loghelper
func Err(err error) []interface{} {
return []interface{}{"err", err}
}
func Msg(s string) []interface{} {
return []interface{}{"msg", s}
}
func KV(items ...interface{}) []interface{} {
var kv []interface{}
for _, item := range items {
switch v := item.(type) {
default:
kv = append(kv, v)
case []interface{}:
kv = append(kv, v...)
}
}
return kv
}
// 使用示例
// 包 main
import lh "./loghelper"
cid := "42"
logger.Log(lh.KV(
lh.Msg("log message text"),
lh.Err(errors.New("error-test")),
"customer.id", cid
)...)
英文:
I see three options to solve this problem:
- A formal convention within a team and a linter to check it
- A shared tagging package for log field names declared as consts (example ext package in opentracing-go). A team always use it for
Log(ext.Message, "log message text", ext.Error, err)
calls. - A syntactic sugar which hides the field naming inside. It can look like this (live example)
// pakage loghelper
func Err(err error) []interface{} {
return []interface{}{"err", err}
}
func Msg(s string) []interface{} {
return []interface{}{"msg", s}
}
func KV(items ...interface{}) []interface{} {
var kv []interface{}
for _, item := range items {
switch v := item.(type) {
default:
kv = append(kv, v)
case []interface{}:
kv = append(kv, v...)
}
}
return kv
}
// USAGE
// package main
import lh ./loghelper
cid = "42"
logger.Log(lh.KV(
lh.Msg("log message text"),
lh.Err(errors.New("error-test")),
"customer.id", cid
)...)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论