你可以使用Golang如何获取容器日志?(错误)

huangapple go评论65阅读模式
英文:

How can I get Container Logs using Golang? (Error)

问题

我正在尝试使用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)
	}
}

请帮我看看问题出在哪里。

英文:

I am trying to code a Docker Monitoring software in Golang.

my Code looks as followed:

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)
}

The problem is that the execution of the above code stops on the fmt.Println(buf.ReadFrom(out)) statement. The code used to work, but it suddenly just doesn't anymore. Either it stops without an error, or it returns an empty String.

The client I am trying to collect the logs from is also coded by myself, and it looks like follows:

package main

import (
	"log"
	"time"
)

func main() {
	for i := 0; i > -1; i++ {
		log.Output(1, "Hello World logged!")
		time.Sleep(time.Minute)
	}
}

I already tried debugging and checking Variables, but I just can't get to the source of the Problem.

答案1

得分: 1

我真的不确定,因为我没有任何错误日志来确认我的假设。
但是有可能是这样的,因为ContainerLogs返回一个流(io.ReadCloser),也许流本身还没有关闭?

如果这是一个可能性,你可以先进行一次干运行,通过添加超时并在每个小的时间间隔后记录日志来测试这个理论。

一种可能的方法是

select {
case <-time.After(5 * time.Second):
    fmt.Println("在读取容器日志时超时")
case <-ctx.Done():
    fmt.Println("在读取容器日志时上下文取消")
case b := <-out:
    if b != nil {
        buf.Write(b)
    }
}
英文:

I am really not sure as I don't have any error logs to confirm my hypothesis.
But could it be the case that as the ContainerLogs returns a stream (io.ReadCloser), maybe the stream itself hasn't closed yet?

If this is a possibility, you can either do a dry run first to test out this theory by adding a timeout and logging it after every small duration ?

one possible way to do this is

    select {
case &lt;-time.After(5 * time.Second):
fmt.Println(&quot;Timeout exceeded while reading container logs&quot;)
case &lt;-ctx.Done():
fmt.Println(&quot;Context cancelled while reading container logs&quot;)
case b := &lt;-out:
if b != nil {
buf.Write(b)
}
}

huangapple
  • 本文由 发表于 2023年2月17日 19:15:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/75483578.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定