php小编西瓜为你带来关于如何使用Golang获取容器日志的实用指南。在容器化应用开发中,日志是非常重要的,它可以帮助我们快速定位和解决问题。本文将介绍如何使用Golang编写代码,通过Docker API获取容器的日志信息,并对常见错误进行处理。无论你是新手还是有经验的开发者,本文都将为你提供有用的技巧和示例代码,帮助你更好地利用Golang获取容器日志。让我们一起开始吧!
问题内容
我正在尝试用 golang 编写 docker 监控软件。
我的代码如下所示:
package main
import (
"bytes"
"context"
"fmt"
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
)
func main() {
ctx := context.background()
cli, err := client.newclientwithopts(client.fromenv)
if err != nil {
panic(err)
}
containers, err := cli.containerlist(ctx, types.containerlistoptions{})
if err != nil {
panic(err)
}
for _, container := range containers {
out, err := cli.containerlogs(ctx, container.id, types.containerlogsoptions{
showstderr: true,
showstdout: true,
timestamps: false,
follow: true,
tail: "40"})
if err != nil {
panic(err)
}
fmt.println("the "" + container.image + "" container, with the id "" + container.id + "" logged: ")
fmt.println()
buf := new(bytes.buffer)
fmt.println(buf.readfrom(out))
fmt.println(buf.string())
}
time.sleep(time.second * 3)
}
问题是上述代码的执行在 fmt.println(buf.readfrom(out))
语句处停止。该代码曾经可以工作,但突然就不再工作了。它要么停止而没有错误,要么返回一个空字符串。
我尝试收集日志的客户端也是我自己编写的,如下所示:
package main
import (
"log"
"time"
)
func main() {
for i := 0; i > -1; i++ {
log.Output(1, "Hello World logged!")
time.Sleep(time.Minute)
}
}
我已经尝试过调试和检查变量,但我就是无法找到问题的根源。
解决方法
我真的不确定,因为我没有任何错误日志来证实我的假设。 但是,当 containerlogs 返回一个流(io.readcloser)时,是否可能该流本身还没有关闭?
如果有可能,您可以先进行一次试运行,通过添加超时并在每个小持续时间后记录它来测试这个理论?
一种可能的方法是
select {
case <-time.After(5 * time.Second):
fmt.Println("Timeout exceeded while reading container logs")
case <-ctx.Done():
fmt.Println("Context cancelled while reading container logs")
case b := <-out:
if b != nil {
buf.Write(b)
}
}