in backend/analyzer/LiveUpdate.go [34:80]
func (a *Analyzer) addWatcher(logFile string, entityIndex int) {
for _, watcher := range a.fileWatchers {
if watcher.Filename == logFile {
return
}
}
t, err := tail.TailFile(logFile, tail.Config{
Follow: true,
Poll: true,
Location: &tail.SeekInfo{Offset: 0, Whence: io.SeekEnd}, // <- line changed
})
if err != nil {
log.Println(err)
}
a.fileWatchers = append(a.fileWatchers, t)
log.Printf("Enabled File watcher for: %v", logFile)
previousLogEntry := ""
// t.Lines channel sends new lines of a file to "for" loop.
// Inside the loop, lines are being checked by ConvertStringToLogs function.
// If a line could be converted to log entry (ConvertStringToLogs return nil error), it is being remembered as previousLogEntry.
// If [the next line is also a log entry], previousLogEntry is being appended to the logs entry list. If next line is the last line of file, it also is being appended to the logs entry list.
// If [the next line is not a log entry], it is being appended to the previous log line (as it is part of the same log entry).
for line := range t.Lines {
f, _ := os.Open(t.Filename)
seek, _ := f.Seek(0, 2)
lineIsLast := line.SeekInfo.Offset == seek
if _, err := a.DynamicEntities[entityIndex].ConvertStringToLogs(line.Text); err == nil {
if len(previousLogEntry) != 0 {
a.attachToLogsStruct(previousLogEntry, entityIndex, t.Filename)
}
if lineIsLast {
a.attachToLogsStruct(line.Text, entityIndex, t.Filename)
previousLogEntry = ""
} else {
previousLogEntry = line.Text
}
} else {
previousLogEntry = previousLogEntry + "\n" + line.Text
if lineIsLast {
a.attachToLogsStruct(previousLogEntry, entityIndex, t.Filename)
previousLogEntry = ""
}
}
}
}