package main import ( "bufio" "context" "fmt" "io" "log" "log/slog" "time" "github.com/k0kubun/pp/v3" "github.com/docker/docker/api/types/container" "github.com/docker/docker/client" "github.com/docker/docker/pkg/stdcopy" ) var containers = make(map[string]int) type LogType struct { Log string Source string ContainerName string } func main() { ctx := context.Background() pp.Println("Running") ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() logschan := make(chan LogType) listContainersAndLogType(ctx, logschan) go func() { time.Sleep(3 * time.Second) slog.Info("Slept") done := ctx.Done() test := <- done pp.Println(test) }() for i := range logschan { pp.Println(i.ContainerName + ": " + i.Log) } } func listContainersAndLogType(ctx context.Context, logschan chan<- LogType) { cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { log.Fatalf("Error creating Docker client: %v", err) } containers, err := cli.ContainerList(ctx, container.ListOptions{All: true}) if err != nil { log.Fatalf("Error listing containers: %v", err) } for _, curcont := range containers { go func() { defer streamContainerLogs(ctx, cli, curcont, logschan) }() } } func streamContainerLogs(ctx context.Context, cli *client.Client, curcont container.Summary, logschan chan<- LogType) { inspect, err := cli.ContainerInspect(ctx, curcont.ID) if err != nil { log.Printf("Error inspecting container %s: %v", curcont.ID, err) return } fmt.Println("Cmd: ", inspect.Config.Cmd) fmt.Println("Entrypoint: ", inspect.Config.Entrypoint) if len(inspect.Config.Cmd) == 0 { slog.Info("Skipping container as cmd empty", "container-id", curcont.ID, "container-image", curcont.Image) return } if inspect.Config.Cmd[0] == "/lilog" { slog.Info("Skipping own container logs") return } logType := inspect.HostConfig.LogConfig.Type fmt.Printf("Container: %-20s ID: %.12s LogDriver: %s\n", curcont.Image, curcont.ID, logType) reader, err := cli.ContainerLogs(ctx, curcont.ID, container.LogsOptions{ ShowStdout: true, ShowStderr: true, Follow: true, Tail: "3", }) if err != nil { panic(err) } defer reader.Close() stdoutPR, stdoutPW := io.Pipe() stderrPR, stderrPW := io.Pipe() defer stdoutPW.Close() defer stderrPW.Close() go func() { scanner := bufio.NewScanner(stdoutPR) for scanner.Scan() { logschan <- LogType{ ContainerName: inspect.Name, Source: "tty", Log: scanner.Text(), } } }() go func() { scanner := bufio.NewScanner(stderrPR) for scanner.Scan() { logschan <- LogType{ ContainerName: inspect.Name, Source: "tty", Log: scanner.Text(), } } }() stdcopy.StdCopy(stdoutPW, stderrPW, reader) }