code: func NewLogStreamV4EventReader(
  	logDirectory string,
  	logPrefix string,
  	startingLogFileNum uint,
  	isRelayLog bool,
  	logger Logger) EventReader {
  
  	openLogReader := func(
  		dir string,
  		file string,
  		parsers V4EventParserMap) (
  		EventReader,
  		error) {
  
  		filePath := path.Join(dir, file)
  		logFile, err := os.Open(filePath)
  		if err != nil {
  			return nil, err
  		}
  
  		return NewLogFileV4EventReader(logFile, filePath, parsers, logger), nil
  	}
  
  	return NewLogStreamV4EventReaderWithLogFileReaderCreator(
  		logDirectory,
  		logPrefix,
  		startingLogFileNum,
  		isRelayLog,
  		logger,
  		openLogReader)
  }
docs: // This returns an EventReader which read and parses events from a (bin /relay)
  // log stream composed of multiple log files.  If no parser is available for
  // the event, or if an error occurs during parsing, then the reader will
  // return the original event along with the error.  NOTE: this reader will
  // transparently switch log files on rotate events (relay log wrapper events
  // are not returned).  When the reader fails to open a log file, it will return
  // a *FailedToOpenFileError; it is safe to retry reading, assuming the filename
  // is valid.  When the reader encounters an invalid rotate event, it will
  // return both the rotate event and an *InvalidRotationError.