diff --git a/main.go b/main.go index 3c055d6..270513d 100644 --- a/main.go +++ b/main.go @@ -14,6 +14,9 @@ import ( "github.com/docker/docker/api/types/container" "github.com/docker/docker/client" "github.com/docker/docker/pkg/stdcopy" + + "github.com/docker/docker/api/types/events" + "github.com/docker/docker/api/types/filters" ) var containers = make(map[string]int) @@ -26,22 +29,54 @@ type LogType struct { func main() { ctx := context.Background() - pp.Println("Running") + pp.Println("Running1") ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() logschan := make(chan LogType) - listContainersAndLogType(ctx, logschan) + go 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) + slog.Info(i.ContainerName + ": " + i.Log) + } +} + +func eventListen(cli *client.Client, logschan chan<- LogType) { + ctx := context.Background() + + options := events.ListOptions{ + Filters: filters.NewArgs( + filters.Arg("type", "container"), + ), + } + + eventChan, errChan := cli.Events(ctx, options) + + slog.Info("Waiting for events") + for { + select { + case event := <-eventChan: + switch event.Action { + case "create": + fmt.Println("Container created:", event.Actor.Attributes["image"]) + case "start": + fmt.Println("Container started:", event.Actor.Attributes["image"]) + streamContainerLogs(ctx, cli, event.Actor.ID, logschan) + case "die": + fmt.Println("Container stopped:", event.Actor.Attributes["image"]) + case "destroy": + fmt.Println("Container destroyed:", event.Actor.Attributes["image"]) + } + case err := <-errChan: + if err != nil { + fmt.Println("Error listening to Docker events:", err) + return + } + } } } @@ -56,73 +91,90 @@ func listContainersAndLogType(ctx context.Context, logschan chan<- LogType) { log.Fatalf("Error listing containers: %v", err) } + pp.Println(len(containers)) for _, curcont := range containers { go func() { - defer streamContainerLogs(ctx, cli, curcont, logschan) + defer streamContainerLogs(ctx, cli, curcont.ID, logschan) }() } + fmt.Println("Ending") + eventListen(cli, logschan) } -func streamContainerLogs(ctx context.Context, cli *client.Client, curcont container.Summary, logschan chan<- LogType) { - inspect, err := cli.ContainerInspect(ctx, curcont.ID) +func streamContainerLogs(ctx context.Context, cli *client.Client, containerID string, logschan chan<- LogType) { + inspect, err := cli.ContainerInspect(ctx, containerID) if err != nil { - log.Printf("Error inspecting container %s: %v", curcont.ID, err) + log.Printf("Error inspecting container %s: %v", containerID, 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) + slog.Debug("Skipping container as cmd empty", "container-id", containerID, "container-image", inspect.Image) return } - if inspect.Config.Cmd[0] == "/lilog" { - slog.Info("Skipping own container logs") + if inspect.Config.Cmd[0] == "/lilog" || inspect.Config.Cmd[0] == "sh" { + slog.Debug("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{ + if inspect.State.Status != "running" { + slog.Debug("Skipping container which isn't running", "container-id", containerID) + return + } + + fmt.Printf("Container: %s (%-20s) ID: %.12s LogDriver: %s\n", + inspect.Config.Cmd[0], inspect.Image, inspect.ID, logType) + reader, err := cli.ContainerLogs(ctx, containerID, container.LogsOptions{ ShowStdout: true, ShowStderr: true, Follow: true, - Tail: "3", + Tail: "0", }) 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) + if inspect.Config.Tty { + scanner := bufio.NewScanner(reader) for scanner.Scan() { - logschan <- LogType{ - ContainerName: inspect.Name, - Source: "tty", - Log: scanner.Text(), - } + logschan <- LogType{ContainerName: inspect.Name, Source: "tty", Log: scanner.Text()} } - }() + } else { + stdoutPR, stdoutPW := io.Pipe() + stderrPR, stderrPW := io.Pipe() - go func() { - scanner := bufio.NewScanner(stderrPR) - for scanner.Scan() { - logschan <- LogType{ - ContainerName: inspect.Name, - Source: "tty", - Log: scanner.Text(), + 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(), + } } - } - }() + }() - stdcopy.StdCopy(stdoutPW, stderrPW, reader) + go func() { + scanner := bufio.NewScanner(stderrPR) + for scanner.Scan() { + logschan <- LogType{ + ContainerName: inspect.Name, + Source: "tty", + Log: scanner.Text(), + } + } + }() + + _, err := stdcopy.StdCopy(stdoutPW, stderrPW, reader) + if err != nil { + panic(err) + } + } }