Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cdeb7bbd authored by Colin Cross's avatar Colin Cross
Browse files

Flush verbose log every second

The gzipped verbose log can buffer for an arbitrarily long time,
which could lose logs in case of a crash, and is annoying when
trying to see the ouptut while the build is still running.  Move
the writes to the verbose log to a goroutine that also calls
gzip.Writer.Flush() every second to make sure the file on disk
is as up to date as possible.

Test: manual
Change-Id: Ib66dad85bbf409bc8327fe11fd78667952de9138
parent f6978173
Loading
Loading
Loading
Loading
+47 −9
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import (
	"io/ioutil"
	"os"
	"strings"
	"sync"
	"time"

	"google.golang.org/protobuf/proto"

@@ -31,7 +33,10 @@ import (
)

type verboseLog struct {
	w io.WriteCloser
	w    *gzip.Writer
	lock *sync.Mutex
	data chan []string
	stop chan bool
}

func NewVerboseLog(log logger.Logger, filename string) StatusOutput {
@@ -47,9 +52,42 @@ func NewVerboseLog(log logger.Logger, filename string) StatusOutput {

	w := gzip.NewWriter(f)

	return &verboseLog{
	l := &verboseLog{
		w:    w,
		lock: &sync.Mutex{},
		data: make(chan []string),
		stop: make(chan bool),
	}
	l.startWriter()
	return l
}

func (v *verboseLog) startWriter() {
	go func() {
		tick := time.Tick(time.Second)
		for {
			select {
			case <-v.stop:
				close(v.data)
				v.w.Close()
				return
			case <-tick:
				v.w.Flush()
			case dataList := <-v.data:
				for _, data := range dataList {
					fmt.Fprint(v.w, data)
				}
			}
		}
	}()
}

func (v *verboseLog) stopWriter() {
	v.stop <- true
}

func (v *verboseLog) queueWrite(s ...string) {
	v.data <- s
}

func (v *verboseLog) StartAction(action *Action, counts Counts) {}
@@ -60,27 +98,27 @@ func (v *verboseLog) FinishAction(result ActionResult, counts Counts) {
		cmd = result.Description
	}

	fmt.Fprintf(v.w, "[%d/%d] %s\n", counts.FinishedActions, counts.TotalActions, cmd)
	v.queueWrite(fmt.Sprintf("[%d/%d] ", counts.FinishedActions, counts.TotalActions), cmd, "\n")

	if result.Error != nil {
		fmt.Fprintf(v.w, "FAILED: %s\n", strings.Join(result.Outputs, " "))
		v.queueWrite("FAILED: ", strings.Join(result.Outputs, " "), "\n")
	}

	if result.Output != "" {
		fmt.Fprintln(v.w, result.Output)
		v.queueWrite(result.Output, "\n")
	}
}

func (v *verboseLog) Flush() {
	v.w.Close()
	v.stopWriter()
}

func (v *verboseLog) Message(level MsgLevel, message string) {
	fmt.Fprintf(v.w, "%s%s\n", level.Prefix(), message)
	v.queueWrite(level.Prefix(), message, "\n")
}

func (v *verboseLog) Write(p []byte) (int, error) {
	fmt.Fprint(v.w, string(p))
	v.queueWrite(string(p))
	return len(p), nil
}