// newLogFileReader creates a new reader to read log files // // It creates a chain of readers which looks as following: // // limit -> (multiline -> timeout) -> strip_newline -> json -> encode -> line -> log_file // // Each reader on the left, contains the reader on the right and calls `Next()` to fetch more data. // At the base of all readers the the log_file reader. That means in the data is flowing in the opposite direction: // // log_file -> line -> encode -> json -> strip_newline -> (timeout -> multiline) -> limit // // log_file implements io.Reader interface and encode reader is an adapter for io.Reader to // reader.Reader also handling file encodings. All other readers implement reader.Reader func (h *Harvester) newLogFileReader() (reader.Reader, error) { var r reader.Reader var err error // TODO: NewLineReader uses additional buffering to deal with encoding and testing // for new lines in input stream. Simple 8-bit based encodings, or plain // don't require 'complicated' logic. h.fileReader, err = NewLogFile(h.file, h.config) if err != nil { return nil, err } r, err = reader.NewEncode(h.fileReader, h.encoding, h.config.BufferSize) if err != nil { return nil, err } if h.config.JSON != nil { r = reader.NewJSON(r, h.config.JSON) } r = reader.NewStripNewline(r) if h.config.Multiline != nil { r, err = reader.NewMultiline(r, "\n", h.config.MaxBytes, h.config.Multiline) if err != nil { return nil, err } } return reader.NewLimit(r, h.config.MaxBytes), nil }
// newLogFileReader creates a new reader to read log files // // It creates a chain of readers which looks as following: // // limit -> (multiline -> timeout) -> strip_newline -> json -> encode -> line -> log_file // // Each reader on the left, contains the reader on the right and calls `Next()` to fetch more data. // At the base of all readers the the log_file reader. That means in the data is flowing in the opposite direction: // // log_file -> line -> encode -> json -> strip_newline -> (timeout -> multiline) -> limit // // log_file implements io.Reader interface and encode reader is an adapter for io.Reader to // reader.Reader also handling file encodings. All other readers implement reader.Reader func (h *Harvester) newLogFileReader() (reader.Reader, error) { var r reader.Reader var err error // TODO: NewLineReader uses additional buffering to deal with encoding and testing // for new lines in input stream. Simple 8-bit based encodings, or plain // don't require 'complicated' logic. h.fileReader, err = NewLogFile(h.file, h.config) if err != nil { return nil, err } // Closes reader after timeout or when done channel is closed go func() { var closeTimeout <-chan time.Time if h.config.CloseTimeout > 0 { closeTimeout = time.After(h.config.CloseTimeout) } select { case <-h.done: case <-closeTimeout: logp.Info("Closing harvester because close_timeout was reached: %s", h.state.Source) } h.fileReader.Close() }() r, err = reader.NewEncode(h.fileReader, h.encoding, h.config.BufferSize) if err != nil { return nil, err } if h.config.JSON != nil { r = reader.NewJSON(r, h.config.JSON) } r = reader.NewStripNewline(r) if h.config.Multiline != nil { r, err = reader.NewMultiline(r, "\n", h.config.MaxBytes, h.config.Multiline) if err != nil { return nil, err } } return reader.NewLimit(r, h.config.MaxBytes), nil }