client: save logs to trace file

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
docker-18.09
Tonis Tiigi 2017-06-18 22:24:41 -07:00
parent 0a7a2c1da3
commit 3d3190573c
5 changed files with 91 additions and 11 deletions

View File

@ -73,6 +73,14 @@ func (c *Client) Solve(ctx context.Context, r io.Reader, statusChan chan *SolveS
Completed: v.Completed,
})
}
for _, v := range resp.Logs {
s.Logs = append(s.Logs, &VertexLog{
Vertex: v.Vertex,
Stream: int(v.Stream),
Data: v.Msg,
Timestamp: v.Timestamp,
})
}
if statusChan != nil {
statusChan <- &s
}

View File

@ -2,8 +2,11 @@ package main
import (
"context"
"encoding/json"
"io/ioutil"
"os"
"github.com/Sirupsen/logrus"
"github.com/tonistiigi/buildkit_poc/client"
"github.com/tonistiigi/buildkit_poc/util/progress/progressui"
"github.com/urfave/cli"
@ -22,7 +25,17 @@ func build(clicontext *cli.Context) error {
return err
}
traceFile, err := ioutil.TempFile("", "buildctl")
if err != nil {
return err
}
defer traceFile.Close()
traceEnc := json.NewEncoder(traceFile)
logrus.Infof("tracing logs to %s", traceFile.Name())
ch := make(chan *client.SolveStatus)
displayCh := make(chan *client.SolveStatus)
eg, ctx := errgroup.WithContext(context.TODO()) // TODO: define appContext
eg.Go(func() error {
@ -30,16 +43,18 @@ func build(clicontext *cli.Context) error {
})
eg.Go(func() error {
return progressui.DisplaySolveStatus(ctx, ch)
// for s := range ch {
// for _, v := range s.Vertexes {
// log.Print(spew.Sdump(v))
// }
// for _, v := range s.Statuses {
// log.Print(spew.Sdump(v))
// }
// }
// return nil
defer close(displayCh)
for s := range ch {
if err := traceEnc.Encode(s); err != nil {
logrus.Error(err)
}
displayCh <- s
}
return nil
})
eg.Go(func() error {
return progressui.DisplaySolveStatus(ctx, displayCh)
})
return eg.Wait()

View File

@ -111,6 +111,14 @@ func (c *Controller) Status(req *controlapi.StatusRequest, stream controlapi.Con
Completed: v.Completed,
})
}
for _, v := range ss.Logs {
sr.Logs = append(sr.Logs, &controlapi.VertexLog{
Vertex: v.Vertex,
Stream: int64(v.Stream),
Msg: v.Data,
Timestamp: v.Timestamp,
})
}
if err := stream.SendMsg(&sr); err != nil {
return err
}

View File

@ -122,6 +122,15 @@ func (j *job) pipe(ctx context.Context, ch chan *client.SolveStatus) error {
Completed: v.Completed,
}
ss.Statuses = append(ss.Statuses, vs)
case client.VertexLog:
vtx, ok := p.Meta("vertex")
if !ok {
logrus.Warnf("progress %s status without vertex info", p.ID)
continue
}
v.Vertex = vtx.(digest.Digest)
v.Timestamp = p.Timestamp
ss.Logs = append(ss.Logs, &v)
}
}
select {

View File

@ -1,6 +1,7 @@
package solver
import (
"io"
"os"
"strings"
"sync"
@ -10,6 +11,7 @@ import (
"github.com/pkg/errors"
"github.com/tonistiigi/buildkit_poc/cache"
"github.com/tonistiigi/buildkit_poc/client"
"github.com/tonistiigi/buildkit_poc/identity"
"github.com/tonistiigi/buildkit_poc/solver/pb"
"github.com/tonistiigi/buildkit_poc/source"
"github.com/tonistiigi/buildkit_poc/util/progress"
@ -211,7 +213,12 @@ func (g *opVertex) runExecOp(ctx context.Context, cm cache.Manager, w worker.Wor
Cwd: op.Exec.Meta.Cwd,
}
if err := w.Exec(ctx, meta, mounts, os.Stderr, os.Stderr); err != nil {
stdout := newStreamWriter(ctx, 1)
defer stdout.Close()
stderr := newStreamWriter(ctx, 2)
defer stderr.Close()
if err := w.Exec(ctx, meta, mounts, stdout, stderr); err != nil {
return errors.Wrapf(err, "worker failed running %v", meta.Args)
}
@ -253,3 +260,36 @@ func (g *opVertex) name() string {
return "unknown"
}
}
func newStreamWriter(ctx context.Context, stream int) io.WriteCloser {
pw, _, _ := progress.FromContext(ctx)
return &streamWriter{
pw: pw,
stream: stream,
}
}
type streamWriter struct {
pw progress.Writer
stream int
}
func (sw *streamWriter) Write(dt []byte) (int, error) {
sw.pw.Write(identity.NewID(), client.VertexLog{
Stream: sw.stream,
Data: append([]byte{}, dt...),
})
// TODO: remove debug
switch sw.stream {
case 1:
return os.Stdout.Write(dt)
case 2:
return os.Stderr.Write(dt)
default:
return 0, errors.Errorf("invalid stream %d", sw.stream)
}
}
func (sw *streamWriter) Close() error {
return sw.pw.Close()
}