github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/build/progress_writer.go (about) 1 package build 2 3 import ( 4 "context" 5 "io" 6 "time" 7 8 "github.com/docker/go-units" 9 10 "github.com/tilt-dev/tilt/pkg/logger" 11 ) 12 13 // A little utility class that tracks how many bytes we've written, 14 // to the Docker context. 15 type ProgressWriter struct { 16 ctx context.Context 17 delegate io.Writer 18 createTime time.Time 19 byteCount int 20 lastPrintTime time.Time 21 lastPrintByteCount int 22 } 23 24 func NewProgressWriter(ctx context.Context, w io.Writer) *ProgressWriter { 25 return &ProgressWriter{ 26 ctx: ctx, 27 delegate: w, 28 createTime: time.Now(), 29 } 30 } 31 32 func (w *ProgressWriter) Write(b []byte) (int, error) { 33 // The io.Writer API can handle partial writes, 34 // so write first, then print the results of the Write. 35 n, err := w.delegate.Write(b) 36 37 w.byteCount += n 38 39 hasBeenPrinted := !w.lastPrintTime.IsZero() 40 shouldPrint := !hasBeenPrinted || 41 time.Since(w.lastPrintTime) > 2*time.Second || 42 w.byteCount > 2*w.lastPrintByteCount 43 if shouldPrint { 44 w.info(logger.Fields{}) 45 w.lastPrintTime = time.Now() 46 w.lastPrintByteCount = w.byteCount 47 } 48 49 return n, err 50 } 51 52 func (w *ProgressWriter) Init() { 53 w.info(logger.Fields{}) 54 } 55 56 func (w *ProgressWriter) Close() { 57 fields := logger.Fields{ 58 logger.FieldNameProgressMustPrint: "1", 59 } 60 w.info(fields) 61 } 62 63 func (w *ProgressWriter) info(fields logger.Fields) { 64 fields[logger.FieldNameProgressID] = "tilt-context-upload" 65 logger.Get(w.ctx).WithFields(fields). 66 Infof("Sending Docker build context: %s (%s)", 67 units.HumanSize(float64(w.byteCount)), 68 time.Since(w.createTime).Truncate(time.Millisecond)) 69 }