From b77d7864faa8089927dcd0452560541c5b5a7646 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Mon, 28 Feb 2022 23:32:36 -0800 Subject: [PATCH] progress: avoid double logs when multiple targets build same step Signed-off-by: Tonis Tiigi --- util/progress/multiwriter.go | 10 ++++----- util/progress/printer.go | 42 ++++++++++++++++++++++++++++++------ util/progress/writer.go | 14 ++++++++++++ 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/util/progress/multiwriter.go b/util/progress/multiwriter.go index 340e5694..86efac32 100644 --- a/util/progress/multiwriter.go +++ b/util/progress/multiwriter.go @@ -8,14 +8,14 @@ import ( func WithPrefix(w Writer, pfx string, force bool) Writer { return &prefixed{ - main: w, - pfx: pfx, - force: force, + Writer: w, + pfx: pfx, + force: force, } } type prefixed struct { - main Writer + Writer pfx string force bool } @@ -26,7 +26,7 @@ func (p *prefixed) Write(v *client.SolveStatus) { v.Name = addPrefix(p.pfx, v.Name) } } - p.main.Write(v) + p.Writer.Write(v) } func addPrefix(pfx, name string) string { diff --git a/util/progress/printer.go b/util/progress/printer.go index 86be5fb6..5abb5145 100644 --- a/util/progress/printer.go +++ b/util/progress/printer.go @@ -5,11 +5,13 @@ import ( "io" "io/ioutil" "os" + "sync" "github.com/containerd/console" "github.com/docker/buildx/util/logutil" "github.com/moby/buildkit/client" "github.com/moby/buildkit/util/progress/progressui" + "github.com/opencontainers/go-digest" "github.com/sirupsen/logrus" ) @@ -21,10 +23,12 @@ const ( ) type Printer struct { - status chan *client.SolveStatus - done <-chan struct{} - err error - warnings []client.VertexWarning + status chan *client.SolveStatus + done <-chan struct{} + err error + warnings []client.VertexWarning + logMu sync.Mutex + logSourceMap map[digest.Digest]interface{} } func (p *Printer) Wait() error { @@ -41,13 +45,39 @@ func (p *Printer) Warnings() []client.VertexWarning { return p.warnings } +func (p *Printer) ValidateLogSource(dgst digest.Digest, v interface{}) bool { + p.logMu.Lock() + defer p.logMu.Unlock() + src, ok := p.logSourceMap[dgst] + if ok { + if src == v { + return true + } + } else { + p.logSourceMap[dgst] = v + return true + } + return false +} + +func (p *Printer) ClearLogSource(v interface{}) { + p.logMu.Lock() + defer p.logMu.Unlock() + for d := range p.logSourceMap { + if p.logSourceMap[d] == v { + delete(p.logSourceMap, d) + } + } +} + func NewPrinter(ctx context.Context, w io.Writer, out console.File, mode string) *Printer { statusCh := make(chan *client.SolveStatus) doneCh := make(chan struct{}) pw := &Printer{ - status: statusCh, - done: doneCh, + status: statusCh, + done: doneCh, + logSourceMap: map[digest.Digest]interface{}{}, } if v := os.Getenv("BUILDKIT_PROGRESS"); v != "" && mode == PrinterModeAuto { diff --git a/util/progress/writer.go b/util/progress/writer.go index 44194b59..e5cc1ca0 100644 --- a/util/progress/writer.go +++ b/util/progress/writer.go @@ -10,6 +10,8 @@ import ( type Writer interface { Write(*client.SolveStatus) + ValidateLogSource(digest.Digest, interface{}) bool + ClearLogSource(interface{}) } func Write(w Writer, name string, f func() error) { @@ -47,8 +49,20 @@ func NewChannel(w Writer) (chan *client.SolveStatus, chan struct{}) { v, ok := <-ch if !ok { close(done) + w.ClearLogSource(done) return } + + if len(v.Logs) > 0 { + logs := make([]*client.VertexLog, 0, len(v.Logs)) + for _, l := range v.Logs { + if w.ValidateLogSource(l.Vertex, done) { + logs = append(logs, l) + } + } + v.Logs = logs + } + w.Write(v) } }()