github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/engine/log_event_writer.go (about)

     1  package engine
     2  
     3  import (
     4  	"io"
     5  	"strings"
     6  	"unicode/utf8"
     7  
     8  	"code.cloudfoundry.org/clock"
     9  	"github.com/pf-qiu/concourse/v6/atc/db"
    10  	"github.com/pf-qiu/concourse/v6/atc/event"
    11  	"github.com/pf-qiu/concourse/v6/atc/exec"
    12  )
    13  
    14  func newDBEventWriter(build db.Build, origin event.Origin, clock clock.Clock) io.WriteCloser {
    15  	return &dbEventWriter{
    16  		build:  build,
    17  		origin: origin,
    18  		clock:  clock,
    19  	}
    20  }
    21  
    22  type dbEventWriter struct {
    23  	build    db.Build
    24  	origin   event.Origin
    25  	clock    clock.Clock
    26  	dangling []byte
    27  }
    28  
    29  func (writer *dbEventWriter) Write(data []byte) (int, error) {
    30  	text := writer.writeDangling(data)
    31  	if text == nil {
    32  		return len(data), nil
    33  	}
    34  
    35  	err := writer.saveLog(string(text))
    36  	if err != nil {
    37  		return 0, err
    38  	}
    39  
    40  	return len(data), nil
    41  }
    42  
    43  func (writer *dbEventWriter) writeDangling(data []byte) []byte {
    44  	text := append(writer.dangling, data...)
    45  
    46  	checkEncoding, _ := utf8.DecodeLastRune(text)
    47  	if checkEncoding == utf8.RuneError {
    48  		writer.dangling = text
    49  		return nil
    50  	}
    51  
    52  	writer.dangling = nil
    53  	return text
    54  }
    55  
    56  func (writer *dbEventWriter) saveLog(text string) error {
    57  	return writer.build.SaveEvent(event.Log{
    58  		Time:    writer.clock.Now().Unix(),
    59  		Payload: text,
    60  		Origin:  writer.origin,
    61  	})
    62  }
    63  
    64  func (writer *dbEventWriter) Close() error {
    65  	return nil
    66  }
    67  
    68  func newDBEventWriterWithSecretRedaction(build db.Build, origin event.Origin, clock clock.Clock, filter exec.BuildOutputFilter) io.Writer {
    69  	return &dbEventWriterWithSecretRedaction{
    70  		dbEventWriter: dbEventWriter{
    71  			build:  build,
    72  			origin: origin,
    73  			clock:  clock,
    74  		},
    75  		filter: filter,
    76  	}
    77  }
    78  
    79  type dbEventWriterWithSecretRedaction struct {
    80  	dbEventWriter
    81  	filter exec.BuildOutputFilter
    82  }
    83  
    84  func (writer *dbEventWriterWithSecretRedaction) Write(data []byte) (int, error) {
    85  	var text []byte
    86  
    87  	if data != nil {
    88  		text = writer.writeDangling(data)
    89  		if text == nil {
    90  			return len(data), nil
    91  		}
    92  	} else {
    93  		if writer.dangling == nil || len(writer.dangling) == 0 {
    94  			return 0, nil
    95  		}
    96  		text = writer.dangling
    97  	}
    98  
    99  	payload := string(text)
   100  	if data != nil {
   101  		idx := strings.LastIndex(payload, "\n")
   102  		if idx >= 0 && idx < len(payload) {
   103  			// Cache content after the last new-line, and proceed contents
   104  			// before the last new-line.
   105  			writer.dangling = ([]byte)(payload[idx+1:])
   106  			payload = payload[:idx+1]
   107  		} else {
   108  			// No new-line found, then cache the log.
   109  			writer.dangling = text
   110  			return len(data), nil
   111  		}
   112  	}
   113  
   114  	payload = writer.filter(payload)
   115  	err := writer.saveLog(payload)
   116  	if err != nil {
   117  		return 0, err
   118  	}
   119  
   120  	return len(data), nil
   121  }
   122  
   123  func (writer *dbEventWriterWithSecretRedaction) Close() error {
   124  	writer.Write(nil)
   125  	return nil
   126  }