Introduction
零位记录字段
我在我的Golang项目中用了github.com/rs/zerolog
.
我知道我可以使用如下代码将字段添加到输出中:
package main
import (
"os"
"github.com/rs/zerolog"
)
func main() {
logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
logger.Int("myIntField", 42)
logger.Info("a regular log output") // this log entry will also contain the integer field `myIntField`
}
但我想要的是,在第logger.Info("a regular log output")
行的运行时,可以计算出字段myIntField
的值.
设置
我有一个带有GO- routine 的生产者/消费者设置(例如,参见https://goplay.tools/snippet/hkoMAwqKcwj),我有两个整数,它们自动倒计时仍在运行的消费者和生产者GO- routine 的数量.在拆卸消费者和生产者之后,我希望在运行时显示这些数字.
以下是使用LOG而不是ZERLOG时的代码:
package main
import (
"fmt"
"log"
"os"
"sync"
"sync/atomic"
)
func main() {
numProducers := int32(3)
numConsumers := int32(3)
producersRunning := numProducers
consumersRunning := numConsumers
var wg sync.WaitGroup
l := log.New(os.Stderr, "", 0)
// producers
for i := int32(0); i < numProducers; i++ {
idx := i
wg.Add(1)
go (func() {
// producer tear down
defer func() {
atomic.AddInt32(&producersRunning, -1)
l.Printf("producer-%3d . producersRunning: %3d\n", idx, producersRunning)
wg.Done()
}()
// this is where the actual producer works is happening
})()
}
// consumers
for i := int32(0); i < numConsumers; i++ {
idx := i
wg.Add(1)
go (func() {
// consumer tear down
defer func() {
atomic.AddInt32(&consumersRunning, -1)
l.Printf("consumer-%3d . consumersRunning: %3d\n", idx, consumersRunning)
wg.Done()
}()
// this is where the actual consumer works is happening
})()
}
fmt.Println("waiting")
wg.Wait()
}
它输出的内容如下所示:
waiting
producer- 1 . producersRunning: 2
producer- 0 . producersRunning: 1
consumer- 1 . consumersRunning: 2
producer- 2 . producersRunning: 0
consumer- 2 . consumersRunning: 1
consumer- 0 . consumersRunning: 0
消费者/生产者的记录器
使用ZERLOG,您可以创建记录器并将其传递给每个Go-routle:
logger := zerolog.New(os.Stderr)
go myConsumer(logger.With().Str("is", "consumer").Logger())
go myProducer(logger.With().Str("is", "producer").Logger())
然后,只需查看每个日志(log)行中的is
字段,就可以很容易地在日志(log)中找出消息是来自消费者还是生产者.
但是,如果我希望始终在每个日志(log)行中打印当前活动的消费者/生产者的数量,该怎么办?您可能会忍不住想做这样的事情:
go myConsumer(logger.With().Str("is", "consumer").Int("consumersRunning", consumersRunning).Logger())
go myProducer(logger.With().Str("is", "producer").Int("producersRunning", producersRunning).Logger())
但当然,这只会在创建Go程序时打印consumersRunning
和producersRunning
的瞬时值.相反,我希望日志(log)输出反映日志(log)输出时的值.
摘要
我希望我的问题是清楚的.我不确定它是否违背了零度的概念,但像这样的函数
func (e *Event) DeferredInt(key string, i func()int) *Event
如果它存在的话,可能会奏效.
有没有其他方法可以达到同样的效果?
潜在的解决方法
我的意思是,一种方法是将logger
变量替换为如下所示的函数调用:
logFunc := func() zerolog.Logger {
return logger.With().Int("runningConcumers", runningConsumers).Logger()
}
然后可以用logFunc().Msg("hello")
创建一个日志(log)条目.这推迟了runningConsumers
的计算,但也 for each 日志(log)条目创建了一个记录器,这感觉有点过头了.
到目前为止,我希望我没有把你搞糊涂.