github.com/tilt-dev/tilt@v0.36.0/pkg/model/logstore/logline.go (about)

     1  package logstore
     2  
     3  import (
     4  	"strings"
     5  	"time"
     6  
     7  	"github.com/tilt-dev/tilt/pkg/logger"
     8  	"github.com/tilt-dev/tilt/pkg/model"
     9  )
    10  
    11  type LogLine struct {
    12  	Text         string
    13  	SpanID       SpanID
    14  	ProgressID   string
    15  	Level        logger.Level
    16  	BuildEvent   string
    17  	ManifestName model.ManifestName
    18  
    19  	// Most progress lines are optional. For example, if a bunch
    20  	// of little upload updates come in, it's ok to skip some.
    21  	//
    22  	// ProgressMustPrint indicates that this line must appear in the
    23  	// output - e.g., a line that communicates that the upload finished.
    24  	ProgressMustPrint bool
    25  
    26  	Time time.Time
    27  }
    28  
    29  type logLineBuilder struct {
    30  	span        *Span
    31  	segments    []LogSegment
    32  	isFirstLine bool
    33  
    34  	needsTrailingNewline bool
    35  }
    36  
    37  func newLogLineBuilder(span *Span, segment LogSegment, isFirstLine bool) *logLineBuilder {
    38  	return &logLineBuilder{
    39  		span:        span,
    40  		segments:    []LogSegment{segment},
    41  		isFirstLine: isFirstLine,
    42  	}
    43  }
    44  
    45  func (b *logLineBuilder) addSegment(segment LogSegment) {
    46  	b.segments = append(b.segments, segment)
    47  }
    48  
    49  func (b *logLineBuilder) lastSegment() LogSegment {
    50  	return b.segments[len(b.segments)-1]
    51  }
    52  
    53  func (b *logLineBuilder) isComplete() bool {
    54  	return b.lastSegment().IsComplete()
    55  }
    56  
    57  func (b *logLineBuilder) build(options logOptions) []LogLine {
    58  	result := []LogLine{}
    59  
    60  	segment := b.segments[0]
    61  	buildEvent := segment.Fields[logger.FieldNameBuildEvent]
    62  	if buildEvent == "init" {
    63  		result = append(result, b.buildSpaceLine(options))
    64  	}
    65  
    66  	result = append(result, b.buildMainLine(options))
    67  	return result
    68  }
    69  
    70  func (b *logLineBuilder) buildSpaceLine(options logOptions) LogLine {
    71  	sb := strings.Builder{}
    72  	span := b.span
    73  	segment := b.segments[0]
    74  	spanID := segment.SpanID
    75  	time := segment.Time
    76  	if options.showManifestPrefix && span.ManifestName != "" {
    77  		shouldSkip := options.skipFirstLineManifestPrefix && b.isFirstLine
    78  		if !shouldSkip {
    79  			sb.WriteString(SourcePrefix(span.ManifestName))
    80  		}
    81  	}
    82  	sb.WriteString("\n")
    83  
    84  	return LogLine{
    85  		Text:         sb.String(),
    86  		SpanID:       spanID,
    87  		Level:        segment.Level,
    88  		BuildEvent:   segment.Fields[logger.FieldNameBuildEvent],
    89  		ManifestName: span.ManifestName,
    90  		Time:         time,
    91  	}
    92  }
    93  
    94  func (b *logLineBuilder) buildMainLine(options logOptions) LogLine {
    95  	segment := b.segments[0]
    96  	span := b.span
    97  	spanID := segment.SpanID
    98  	time := segment.Time
    99  	progressID := segment.Fields[logger.FieldNameProgressID]
   100  	progressMustPrint := segment.Fields[logger.FieldNameProgressMustPrint] == "1"
   101  
   102  	sb := strings.Builder{}
   103  	if options.showManifestPrefix && span.ManifestName != "" {
   104  		shouldSkip := options.skipFirstLineManifestPrefix && b.isFirstLine
   105  		if !shouldSkip {
   106  			sb.WriteString(SourcePrefix(span.ManifestName))
   107  		}
   108  	}
   109  
   110  	if segment.Anchor {
   111  		// TODO(nick): Add Terminal colors when supported.
   112  		if segment.Level == logger.WarnLvl {
   113  			sb.WriteString("WARNING: ")
   114  		} else if segment.Level == logger.ErrorLvl {
   115  			sb.WriteString("ERROR: ")
   116  		}
   117  	}
   118  
   119  	for _, segment := range b.segments {
   120  		sb.Write(segment.Text)
   121  	}
   122  
   123  	if !b.isComplete() && b.needsTrailingNewline {
   124  		sb.WriteString("\n")
   125  	}
   126  
   127  	return LogLine{
   128  		Text:              sb.String(),
   129  		SpanID:            spanID,
   130  		Level:             segment.Level,
   131  		BuildEvent:        segment.Fields[logger.FieldNameBuildEvent],
   132  		ManifestName:      span.ManifestName,
   133  		ProgressID:        progressID,
   134  		ProgressMustPrint: progressMustPrint,
   135  		Time:              time,
   136  	}
   137  }