src/client/pps.go
func (c APIClient) GetLogs(
	pipelineName string,
	jobID string,
	data []string,
	datumID string,
	master bool,
	follow bool,
	tail int64,
) *LogsIter {
	request := pps.GetLogsRequest{
		Master: master,
		Follow: follow,
		Tail:   tail,
	}
	resp := &LogsIter{}
	if pipelineName != "" {
		request.Pipeline = NewPipeline(pipelineName)
	}
	if jobID != "" {
		request.Job = NewJob(jobID)
	}
	request.DataFilters = data
	if datumID != "" {
		request.Datum = &pps.Datum{
			Job: NewJob(jobID),
			ID:  datumID,
		}
	}
	resp.logsClient, resp.err = c.PpsAPIClient.GetLogs(c.Ctx(), &request)
	resp.err = grpcutil.ScrubGRPC(resp.err)
	return resp
}
func (c APIClient) GetLogs(
	pipelineName string,
	jobID string,
	data []string,
	datumID string,
	master bool,
	follow bool,
	tail int64,
) *LogsIter {
	request := pps.GetLogsRequest{
		Master: master,
		Follow: follow,
		Tail:   tail,
	}
	resp := &LogsIter{}
	if pipelineName != "" {
		request.Pipeline = NewPipeline(pipelineName)
	}
	if jobID != "" {
		request.Job = NewJob(jobID)
	}
	request.DataFilters = data
	if datumID != "" {
		request.Datum = &pps.Datum{
			Job: NewJob(jobID),
			ID:  datumID,
		}
	}
	resp.logsClient, resp.err = c.PpsAPIClient.GetLogs(c.Ctx(), &request)
	resp.err = grpcutil.ScrubGRPC(resp.err)
	return resp
}
// GetLogs gets logs from a job (logs includes stdout and stderr). 'pipelineName',
// 'jobID', 'data', and 'datumID', are all filters. To forego any filter,
// simply pass an empty value, though one of 'pipelineName' and 'jobID'
// must be set. Responses are written to 'messages'