我正在尝试确定默认/ sdk记录器日志。PrintYYY()函数是否在某个时间点,退出,紧急情况等时被刷新。我不确定是否需要找到一种刷新方法记录器连接到的编写器,尤其是在使用SetOutput(...)设置输出编写器时。当然,writer接口没有flush()方法,因此不确定是否可以完成此操作。
Go sdk记录器如何以及何时刷新?
答案 0 :(得分:1)
log
程序包不负责刷新基础的io.Writer
。 log
程序包可能会执行类型声明,以查看当前的io.Writer
是否具有Flush()
方法,如果可以,则进行调用,但不能保证如果多个“ io.Writer
”被“链接”,则数据最终将被刷新到最底层。
在我看来,log
软件包没有刷新的主要原因是 performance 。我们使用缓冲的写入器,因此不必每次写入单个字节(或字节片)时都到达底层,但是我们可以缓存最近写入的数据,并在达到特定大小(或特定大小)时进行缓存时间),我们可以立即高效地编写“批处理”。
如果log
软件包将在每个日志语句后刷新,则将使缓冲的IO失效。对于小型应用程序来说,这可能无关紧要,但是,如果您的网络服务器流量很高,则在每个日志语句(每个请求处理中可能有很多日志语句)之后发出刷新操作会严重影响性能。
然后是的,如果应用程序终止,则会出现问题,最后的日志语句可能无法进入基础层。正确的解决方案是执行正常关机:实施信号处理,并在您的应用即将终止时,正确刷新并关闭您使用的记录器的基础io.Writer
。有关详细信息,请参见:
Is it possible to capture a Ctrl+C signal and run a cleanup function, in a "defer" fashion?
Is there something like finally() in Go just opposite to what init()?
Are deferred functions called when SIGINT is received in Go?
如果(仅出于简化目的)您仍然需要一个在每个日志语句后刷新的记录器,则可以轻松实现。这是因为log.Logger
类型可确保通过单个io.Writer
调用将每条日志消息传递到目标Writer.Write()
:
每个日志记录操作都会调用Writer的Write方法。一个Logger可以同时从多个goroutines中使用。它保证序列化对Writer的访问。
因此,基本上,您所需要做的就是创建一个“包装器” io.Writer
,其“ Write()
”方法在将“ Write()
”调用“转发”给其底层编写器之后进行刷新。
它是这样的:
type myWriter struct {
io.Writer
}
func (m *myWriter) Write(p []byte) (n int, err error) {
n, err = m.Writer.Write(p)
if flusher, ok := m.Writer.(interface{ Flush() }); ok {
flusher.Flush()
} else if syncer := m.Writer.(interface{ Sync() error }); ok {
// Preserve original error
if err2 := syncer.Sync(); err2 != nil && err == nil {
err = err2
}
}
return
}
此实现会同时检查Flush()
方法和os.File
的Sync()
方法,并调用它们是否“存在”。
这是可以使用的方式,以便日志记录语句始终刷新:
f, err := os.Create("log.txt")
if err != nil {
panic(err)
}
defer f.Close()
log.SetOutput(&myWriter{Writer: f})
log.Println("hi")
查看相关问题:
Go: Create io.Writer inteface for logging to mongodb database
答案 1 :(得分:0)
记录器不应该知道如何刷新数据。您必须刷新在记录器创建时指定的输出记录器(如果具有此功能)。
中的示例package main
import (
"bufio"
"flag"
"log"
"os"
"strings"
)
func main() {
var flush bool
flag.BoolVar(&flush, "flush", false, "if set, will flush the buffered io before exiting")
flag.Parse()
br := bufio.NewWriter(os.Stdout)
logger := log.New(br, "", log.Ldate)
logger.Printf("%s\n", strings.Repeat("This is a test\n", 5))
if flush {
br.Flush()
}
logger.Fatalf("exiting now!")
}
您可以阅读与您的问题on github相关的整个讨论
或者,您可以查看具有flush
的第三方记录器。检出具有方法logger.Sync()