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  }