// Copyright (C) The Arvados Authors. All rights reserved. // // SPDX-License-Identifier: AGPL-3.0 package crunchrun import ( "bytes" "strings" ) // logScanner is an io.Writer that calls ReportFunc(pattern) the first // time one of the Patterns appears in the data. Patterns must not // contain newlines. type logScanner struct { Patterns []string ReportFunc func(pattern, text string) reported bool buf bytes.Buffer } func (s *logScanner) Write(p []byte) (int, error) { if s.reported { // We only call reportFunc once. Once we've called it // there's no need to buffer/search subsequent writes. return len(p), nil } split := bytes.LastIndexByte(p, '\n') if split < 0 { return s.buf.Write(p) } s.buf.Write(p[:split+1]) txt := s.buf.String() for _, pattern := range s.Patterns { if found := strings.Index(txt, pattern); found >= 0 { // Report the entire line where the pattern // was found. txt = txt[strings.LastIndexByte(txt[:found], '\n')+1:] if end := strings.IndexByte(txt, '\n'); end >= 0 { txt = txt[:end] } s.ReportFunc(pattern, txt) s.reported = true return len(p), nil } } s.buf.Reset() if split == len(p) { return len(p), nil } n, err := s.buf.Write(p[split+1:]) return n + split + 1, err }