terraform使用的hashicorp/go-hclog
Hashicorp製OSS中最著名的记录器是hashicorp/logutils,然而,在阅读Terraform代码时,我注意到其内部实际上使用了hashicorp/go-hclog。这两者都是符合Go语言标准日志库的记录器,不过我很好奇为什么要更改记录器,所以进行了一些调查。
hashicop/logutils -> 哈希卡普/日志工具
logutils是一个非常简单的日志记录器。它具有与Go语言标准库的log相同的接口,并通过在日志消息中嵌入日志级别来实现日志级别的过滤。由于具有与标准log相同的接口,它不需要像Debug方法或Info方法一样存在,而是通过在传递给Print方法的消息前面嵌入像[DEBUG]或[INFO]这样的字符串来实现日志级别。这一点相当令人惊讶。
func main() {
filter := &logutils.LevelFilter{
Levels: []logutils.LogLevel{"DEBUG", "WARN", "ERROR"},
MinLevel: logutils.LogLevel("WARN"),
Writer: os.Stderr,
}
log.SetOutput(filter)
log.Print("[DEBUG] Debugging") // this will not print
log.Print("[WARN] Warning") // this will
}
顺便说一下,由于主体代码不到100行,所以可以很轻松地确认实施情况。
哈希科技/go-hclog
尽管hclog也是一个简单的记录器,但相比logutils实现了更多的功能。
与logutils类似,通过将级别标识字符串嵌入到传递给Print方法的消息的开头,可以实现级别记录,并提供了专用的Info方法作为选项。
除此之外,hclog还提供了结构化记录、键值数据记录等一般记录所需的功能。
func main() {
appLogger := hclog.New(&hclog.LoggerOptions{
Name: "my-app",
Level: hclog.LevelFromString("INFO"),
})
appLogger.Debug("this message will not print")
appLogger.Info("this message will print")
appLogger.Info("message with key-value", "key", 42)
}
// $ go run main.go
// 2023-02-26T22:19:29.622+0900 [INFO] my-app: this message will print
// 2023-02-26T22:19:29.622+0900 [INFO] my-app: message with key-value: key=42
顺便提一下,在terraform中,我们没有使用Info方法或其他日志级别方法的功能,而是像logutils一样使用log.Printf(“[INFO] …”)的格式进行记录日志。
参考:terraform-plugin-log(tflog)
尽管我们在terraform的实现中没有使用,但是terraform为插件提供了一个名为terraform-plugin-log (tflog)的日志记录器。
tflog是hclog的一个封装,它能够继承terraform主体的设置,无需在每个插件中进行hclog的日志输出配置。
大概是因为为了实现tflog,terraform可能决定将logutils转换为hclog,并且认为需要在terraform本身和插件之间有更统一的机制。在terraform插件的日志记录中,可以区分terraform本体和插件输出的日志级别,也可以单独修改特定插件的日志级别。例如,terraform可以以info级别输出,terraform-provider-aws可以以debug级别输出,其他插件则不输出日志,这样的实现是可能的。
要在terraform本体中实现此功能过滤似乎会非常麻烦,因此推测它们使用了hclog以及tflog作为其包装的工具来提供此功能。