code: func startFetch(c context.Context, request *http.Request, pathStr string) (data logData, err error) {
  	if data.options, err = resolveOptions(request, pathStr); err != nil {
  		err = errors.Annotate(err, "resolving options").Tag(grpcutil.InvalidArgumentTag).Err()
  		return
  	}
  	// Pull out project/path for convenience.
  	project, path := data.options.project, data.options.path
  	logging.Fields{
  		"project": project,
  		"path":    path,
  		"format":  data.options.format,
  	}.Debugf(c, "parsed options")
  
  	// Enter project namespace.  This is effectively the ACL check.
  	// If successful, the context will be modified to enter the project datastore namespace.
  	if err = coordinator.WithProjectNamespace(&c, project, coordinator.NamespaceAccessREAD); err != nil {
  		return
  	}
  
  	// Enumerate all of the streams we will be fetching from.
  	// If the input path is a fully qualified path, this will return exactly 1 stream.
  	streams, err := resolveStreams(c, data.options)
  	if err != nil {
  		return
  	}
  
  	params, err := initParams(c, streams, project)
  	if err != nil {
  		return
  	}
  
  	// Create a channel to transfer log data.  This channel will be closed by
  	// fetch() to signal that all logs have been returned (or an error was encountered).
  	ch := make(chan logResp, maxBuffer)
  	// Start fetching!!!
  	go fetch(c, ch, params)
  	data.ch = ch
  	data.logStreams = streams
  	return
  }
docs: // startFetch sets up the backend storage instance (Either BigTable or Google Storage)
  // and then jump starts the goroutine to fetch logs from the backend storage.
  // It returns a logData struct containing:
  // * A channel where logs entries are sent back.
  // * Log Stream metadata and state.