github.com/jaylevin/jenkins-library@v1.230.4/pkg/log/writer.go (about)

     1  package log
     2  
     3  import (
     4  	"bytes"
     5  	"strings"
     6  	"sync"
     7  )
     8  
     9  type logTarget interface {
    10  	Info(args ...interface{})
    11  	Warn(args ...interface{})
    12  	Error(args ...interface{})
    13  }
    14  
    15  // logrusWriter can be used as the destination for a tool's std output and forwards
    16  // chunks between linebreaks to the logrus framework. This works around a problem
    17  // with using Entry().Writer() directly, since that doesn't support chunks
    18  // larger than 64K without linebreaks.
    19  // Implementation copied from https://github.com/sirupsen/logrus/issues/564
    20  type logrusWriter struct {
    21  	logger logTarget
    22  	buffer bytes.Buffer
    23  	mutex  sync.Mutex
    24  }
    25  
    26  func (w *logrusWriter) Write(buffer []byte) (int, error) {
    27  	w.mutex.Lock()
    28  	defer w.mutex.Unlock()
    29  
    30  	origLen := len(buffer)
    31  	for {
    32  		if len(buffer) == 0 {
    33  			return origLen, nil
    34  		}
    35  		linebreakIndex := bytes.IndexByte(buffer, '\n')
    36  		if linebreakIndex < 0 {
    37  			w.buffer.Write(buffer)
    38  			return origLen, nil
    39  		}
    40  
    41  		w.buffer.Write(buffer[:linebreakIndex])
    42  		w.alwaysFlush()
    43  		buffer = buffer[linebreakIndex+1:]
    44  	}
    45  }
    46  
    47  func (w *logrusWriter) alwaysFlush() {
    48  	message := w.buffer.String()
    49  	w.buffer.Reset()
    50  	// Align level with underlying tool (like maven or npm)
    51  	// This is to avoid confusion when maven or npm print errors or warnings which piper would print as "info"
    52  	if strings.Contains(message, "ERROR") || strings.Contains(message, "ERR!") {
    53  		w.logger.Error(message)
    54  	} else if strings.Contains(message, "WARN") {
    55  		w.logger.Warn(message)
    56  	} else {
    57  		w.logger.Info(message)
    58  	}
    59  }
    60  
    61  func (w *logrusWriter) Flush() {
    62  	w.mutex.Lock()
    63  	defer w.mutex.Unlock()
    64  
    65  	if w.buffer.Len() != 0 {
    66  		w.alwaysFlush()
    67  	}
    68  }