code: func (l *FileLog) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) ([]EventFields, error) {
  	l.Debugf("SearchEvents(%v, %v, query=%v, limit=%v)", fromUTC, toUTC, query, limit)
  	if limit <= 0 {
  		limit = defaults.EventsIterationLimit
  	}
  	if limit > defaults.EventsMaxIterationLimit {
  		return nil, trace.BadParameter("limit %v exceeds max iteration limit %v", limit, defaults.MaxIterationLimit)
  	}
  	// how many days of logs to search?
  	days := int(toUTC.Sub(fromUTC).Hours() / 24)
  	if days < 0 {
  		return nil, trace.BadParameter("invalid days")
  	}
  	queryVals, err := url.ParseQuery(query)
  	if err != nil {
  		return nil, trace.BadParameter("invalid query")
  	}
  	filtered, err := l.matchingFiles(fromUTC, toUTC)
  	if err != nil {
  		return nil, trace.Wrap(err)
  	}
  	var total int
  	// search within each file:
  	events := make([]EventFields, 0)
  	for i := range filtered {
  		found, err := l.findInFile(filtered[i].path, queryVals, &total, limit)
  		if err != nil {
  			return nil, trace.Wrap(err)
  		}
  		events = append(events, found...)
  		if limit > 0 && total >= limit {
  			break
  		}
  	}
  	// sort all accepted files by timestamp or by event index
  	// in case if events are associated with the same session, to make
  	// sure that events are not displayed out of order in case of multiple
  	// auth servers.
  	sort.Sort(ByTimeAndIndex(events))
  	return events, nil
  }
docs: // SearchEvents finds events. Results show up sorted by date (newest first),
  // limit is used when set to value > 0