// GetDockerLogs returns the last 2000 lines of logs from the docker container
968225
func (a *AgentServer) GetDockerLogs(dockerID string, logs *string) error {
	cmd := exec.Command("docker", "logs", "--tail=2000", dockerID)
	output, err := cmd.CombinedOutput()
	if err != nil {
		plog.WithError(err).WithField("dockerid", dockerID).Error("Unable to retrieve logs from docker")
		return err
	}
	*logs = string(output)
	return nil
}
193202
func (c *containerLogManager) cleanupUnusedLogs(logs []string) ([]string, error) {
	inuse, unused := filterUnusedLogs(logs)
	for _, l := range unused {
		if err := os.Remove(l); err != nil {
			return nil, fmt.Errorf("failed to remove unused log %q: %v", l, err)
		}
	}
	return inuse, nil
}
372012
func (api *PublicFilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*types.Log, error) {
	api.filtersMu.Lock()
	f, found := api.filters[id]
	api.filtersMu.Unlock()

	if !found || f.typ != LogsSubscription {
		return nil, fmt.Errorf("filter not found")
	}

	var filter *Filter
	if f.crit.BlockHash != nil {
		// Block filter requested, construct a single-shot filter
		filter = NewBlockFilter(api.backend, *f.crit.BlockHash, f.crit.Addresses, f.crit.Topics)
	} else {
		// Convert the RPC block numbers into internal representations
		begin := rpc.LatestBlockNumber.Int64()
		if f.crit.FromBlock != nil {
			begin = f.crit.FromBlock.Int64()
		}
		end := rpc.LatestBlockNumber.Int64()
		if f.crit.ToBlock != nil {
			end = f.crit.ToBlock.Int64()
		}
		// Construct the range filter
		filter = NewRangeFilter(api.backend, begin, end, f.crit.Addresses, f.crit.Topics)
	}
	// Run the filter and return all the logs
	logs, err := filter.Logs(ctx)
	if err != nil {
		return nil, err
	}
	return returnLogs(logs), nil
}
1303520
func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) {
	// If we're doing singleton block filtering, execute and return
	if f.block != (common.Hash{}) {
		header, err := f.backend.HeaderByHash(ctx, f.block)
		if err != nil {
			return nil, err
		}
		if header == nil {
			return nil, errors.New("unknown block")
		}
		return f.blockLogs(ctx, header)
	}
	// Figure out the limits of the filter range
	header, _ := f.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber)
	if header == nil {
		return nil, nil
	}
	head := header.Number.Uint64()

	if f.begin == -1 {
		f.begin = int64(head)
	}
	end := uint64(f.end)
	if f.end == -1 {
		end = head
	}
	// Gather all indexed logs, and finish with non indexed ones
	var (
		logs []*types.Log
		err  error
	)
	size, sections := f.backend.BloomStatus()
	if indexed := sections * size; indexed > uint64(f.begin) {
		if indexed > end {
			logs, err = f.indexedLogs(ctx, end)
		} else {
			logs, err = f.indexedLogs(ctx, indexed-1)
		}
		if err != nil {
			return logs, err
		}
	}
	rest, err := f.unindexedLogs(ctx, end)
	logs = append(logs, rest...)
	return logs, err
}
1115252
func (a *api) ExportLogs(configParam ExportLogsConfig) (err error) {

	startTime := time.Now().UTC()
	// time.RFC3339 = "2006-01-02T15:04:05Z07:00"
	timeLabel := strings.Replace(startTime.Format(time.RFC3339), ":", "", -1)

	e := validateConfiguration(&configParam, timeLabel)
	if e != nil {
		return e
	}

	var exporter *logExporter
	defer func() {
		if exporter != nil {
			exporter.cleanup()
		}
	}()

	exporter, e = buildExporter(configParam, startTime, timeLabel, a.GetAllServiceDetails, a.GetHostMap)
	if e != nil {
		return e
	}

	numWarnings := 0
	foundIndexedDay := false

	log := log.WithFields(logrus.Fields{
		"tmpdir": exporter.tempdir,
		"from":   exporter.FromDate,
		"to":     exporter.ToDate,
	})
	log.Info("Starting part 1 of 3: Processing Logstash Elastic results")
	foundIndexedDay, numWarnings, e = exporter.retrieveLogs()
	if e != nil {
		return e
	} else if !foundIndexedDay {
		return fmt.Errorf("no logstash indexes exist for the given date range %s - %s", exporter.FromDate, exporter.ToDate)
	}

	log.WithFields(logrus.Fields{
		"numfiles": len(exporter.outputFiles),
	}).Info("Starting part 2 of 3: Sort output files")

	indexData := []string{}
	for i, outputFile := range exporter.outputFiles {
		if e := exporter.organizeAndGroomLogFile(i, numWarnings); e != nil {
			return e
		}
		indexData = append(indexData, exporter.fileIndex.GetFileIndexData(
			i,
			outputFile,
			exporter.getHostName(outputFile.HostID),
			exporter.getServiceName(outputFile.ServiceID)))
	}
	sort.Strings(indexData)

	servicesDesc := make([]string, 0)
	for _, id := range configParam.ServiceIDs {
		servicesDesc = append(servicesDesc, fmt.Sprintf("%s (%s)", exporter.getServiceName(id), id))
	}
	indexData = append([]string{
		"LOG EXPORT SUMMARY",
		fmt.Sprintf("       Export Ran On: %s", exporter.startTime.Format(time.RFC1123)),
		fmt.Sprintf("Available Date Range: %s - %s", exporter.days[len(exporter.days)-1], exporter.days[0]),
		fmt.Sprintf("     Requested Dates: %s - %s", configParam.FromDate, configParam.ToDate),
		fmt.Sprintf("      Exported Dates: %s - %s", exporter.minDateFound, exporter.maxDateFound),
		fmt.Sprintf("          Grouped By: %s", configParam.GroupBy),
		fmt.Sprintf("Requested Service(s): %s", strings.Join(servicesDesc, ", ")),
		fmt.Sprintf("Child Svcs Excluded?: %s", strconv.FormatBool(configParam.ExcludeChildren)),
		fmt.Sprintf("   Requested File(s): %s", strings.Join(configParam.FileNames, ", ")),
		"",
		"INDEX OF LOG FILES",
		exporter.fileIndex.GetIndexHeader()},
		indexData...)
	indexData = append(indexData, "")
	indexFile := filepath.Join(exporter.tempdir, "index.txt")
	e = ioutil.WriteFile(indexFile, []byte(strings.Join(indexData, "\n")), 0644)
	if e != nil {
		return fmt.Errorf("failed writing to %s: %s", indexFile, e)
	}

	log.WithFields(logrus.Fields{
		"outfile": exporter.OutFileName,
	}).Info("Starting part 3 of 3: Generate tar file")
	gz := gzip.NewWriter(exporter.outFile)
	defer gz.Close()
	tarfile := tar.NewWriter(gz)
	defer tarfile.Close()
	if e := volume.ExportDirectory(tarfile, exporter.tempdir, filepath.Base(exporter.tempdir)); e != nil {
		return fmt.Errorf("failed to write tgz %s: %s", exporter.OutFileName, e)
	}

	if numWarnings != 0 {
		log.WithFields(logrus.Fields{
			"warnfile": filepath.Join(filepath.Base(exporter.tempdir), filepath.Base(exporter.parseWarningsFilename)),
		}).Info("Warnings for log parse are included in the tar file")
	}

	return nil
}
1160158
func (b *FastLogStore) GetLog(idx uint64, log *raft.Log) error {
	b.mu.RLock()
	defer b.mu.RUnlock()
	if b.closed {
		return ErrClosed
	}
	vlog := b.lvm[idx]
	if vlog == nil {
		return raft.ErrLogNotFound
	}
	*log = *vlog
	return nil
}
72401
func (ds *dockerService) ReopenContainerLog(_ context.Context, _ *runtimeapi.ReopenContainerLogRequest) (*runtimeapi.ReopenContainerLogResponse, error) {
	return nil, fmt.Errorf("docker does not support reopening container log files")
}
396080
func ReadLogs(ctx context.Context, path, containerID string, opts *LogOptions, runtimeService internalapi.RuntimeService, stdout, stderr io.Writer) error {
	f, err := os.Open(path)
	if err != nil {
		return fmt.Errorf("failed to open log file %q: %v", path, err)
	}
	defer f.Close()

	// Search start point based on tail line.
	start, err := tail.FindTailLineStartIndex(f, opts.tail)
	if err != nil {
		return fmt.Errorf("failed to tail %d lines of log file %q: %v", opts.tail, path, err)
	}
	if _, err := f.Seek(start, io.SeekStart); err != nil {
		return fmt.Errorf("failed to seek %d in log file %q: %v", start, path, err)
	}

	// Start parsing the logs.
	r := bufio.NewReader(f)
	// Do not create watcher here because it is not needed if `Follow` is false.
	var watcher *fsnotify.Watcher
	var parse parseFunc
	var stop bool
	found := true
	writer := newLogWriter(stdout, stderr, opts)
	msg := &logMessage{}
	for {
		if stop {
			klog.V(2).Infof("Finish parsing log file %q", path)
			return nil
		}
		l, err := r.ReadBytes(eol[0])
		if err != nil {
			if err != io.EOF { // This is an real error
				return fmt.Errorf("failed to read log file %q: %v", path, err)
			}
			if opts.follow {
				// The container is not running, we got to the end of the log.
				if !found {
					return nil
				}
				// Reset seek so that if this is an incomplete line,
				// it will be read again.
				if _, err := f.Seek(-int64(len(l)), io.SeekCurrent); err != nil {
					return fmt.Errorf("failed to reset seek in log file %q: %v", path, err)
				}
				if watcher == nil {
					// Initialize the watcher if it has not been initialized yet.
					if watcher, err = fsnotify.NewWatcher(); err != nil {
						return fmt.Errorf("failed to create fsnotify watcher: %v", err)
					}
					defer watcher.Close()
					if err := watcher.Add(f.Name()); err != nil {
						return fmt.Errorf("failed to watch file %q: %v", f.Name(), err)
					}
					// If we just created the watcher, try again to read as we might have missed
					// the event.
					continue
				}
				var recreated bool
				// Wait until the next log change.
				found, recreated, err = waitLogs(ctx, containerID, watcher, runtimeService)
				if err != nil {
					return err
				}
				if recreated {
					newF, err := os.Open(path)
					if err != nil {
						if os.IsNotExist(err) {
							continue
						}
						return fmt.Errorf("failed to open log file %q: %v", path, err)
					}
					f.Close()
					if err := watcher.Remove(f.Name()); err != nil && !os.IsNotExist(err) {
						klog.Errorf("failed to remove file watch %q: %v", f.Name(), err)
					}
					f = newF
					if err := watcher.Add(f.Name()); err != nil {
						return fmt.Errorf("failed to watch file %q: %v", f.Name(), err)
					}
					r = bufio.NewReader(f)
				}
				// If the container exited consume data until the next EOF
				continue
			}
			// Should stop after writing the remaining content.
			stop = true
			if len(l) == 0 {
				continue
			}
			klog.Warningf("Incomplete line in log file %q: %q", path, l)
		}
		if parse == nil {
			// Initialize the log parsing function.
			parse, err = getParseFunc(l)
			if err != nil {
				return fmt.Errorf("failed to get parse function: %v", err)
			}
		}
		// Parse the log line.
		msg.reset()
		if err := parse(l, msg); err != nil {
			klog.Errorf("Failed with err %v when parsing log for log file %q: %q", err, path, l)
			continue
		}
		// Write the log line into the stream.
		if err := writer.write(msg); err != nil {
			if err == errMaximumWrite {
				klog.V(2).Infof("Finish parsing log file %q, hit bytes limit %d(bytes)", path, opts.bytes)
				return nil
			}
			klog.Errorf("Failed with err %v when writing log for log file %q: %+v", err, path, msg)
			return err
		}
	}
}
955969
func (c *ContainerServer) GetLogs(container string, logChan chan string, opts LogOptions) error {
	defer close(logChan)
	// Get the full ID of the container
	ctr, err := c.LookupContainer(container)
	if err != nil {
		return err
	}

	containerID := ctr.ID()
	sandbox := ctr.Sandbox()
	if sandbox == "" {
		sandbox = containerID
	}
	// Read the log line by line and pass it into the pipe
	logsFile := path.Join(c.config.LogDir, sandbox, containerID+".log")

	seekInfo := &tail.SeekInfo{Offset: 0, Whence: 0}
	if opts.Tail > 0 {
		// seek to correct position in logs files
		seekInfo.Offset = int64(opts.Tail)
		seekInfo.Whence = 2
	}

	t, err := tail.TailFile(logsFile, tail.Config{Follow: false, ReOpen: false, Location: seekInfo})
	for line := range t.Lines {
		if since, err := logSinceTime(opts.SinceTime, line.Text); err != nil || !since {
			continue
		}
		logMessage := line.Text[secondSpaceIndex(line.Text):]
		logChan <- logMessage
	}
	return err
}
813489
func getLoggerOpts(module string, level api.Level) *loggerOpts {
	rwmutex.RLock()
	defer rwmutex.RUnlock()
	return &loggerOpts{
		levelEnabled:      moduleLevels.IsEnabledFor(module, level),
		callerInfoEnabled: callerInfos.IsCallerInfoEnabled(module, level),
	}
}
308094
func (b *BoltStore) StoreLogs(logs []*raft.Log) error {
	tx, err := b.conn.Begin(true)
	if err != nil {
		return err
	}
	defer tx.Rollback()

	for _, log := range logs {
		key := uint64ToBytes(log.Index)
		val, err := encodeMsgPack(log)
		if err != nil {
			return err
		}
		bucket := tx.Bucket(dbLogs)
		if err := bucket.Put(key, val.Bytes()); err != nil {
			return err
		}
	}

	return tx.Commit()
}
586926
func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*types.Log, error) {
	var filter *Filter
	if crit.BlockHash != nil {
		// Block filter requested, construct a single-shot filter
		filter = NewBlockFilter(api.backend, *crit.BlockHash, crit.Addresses, crit.Topics)
	} else {
		// Convert the RPC block numbers into internal representations
		begin := rpc.LatestBlockNumber.Int64()
		if crit.FromBlock != nil {
			begin = crit.FromBlock.Int64()
		}
		end := rpc.LatestBlockNumber.Int64()
		if crit.ToBlock != nil {
			end = crit.ToBlock.Int64()
		}
		// Construct the range filter
		filter = NewRangeFilter(api.backend, begin, end, crit.Addresses, crit.Topics)
	}
	// Run the filter and return all the logs
	logs, err := filter.Logs(ctx)
	if err != nil {
		return nil, err
	}
	return returnLogs(logs), err
}
563031
func (as *AnalyticalStorage) FindLogs(ctx context.Context, filter influxdb.LogFilter) ([]*influxdb.Log, int, error) {
	var logs []*influxdb.Log
	if filter.Run != nil {
		run, err := as.FindRunByID(ctx, filter.Task, *filter.Run)
		if err != nil {
			return nil, 0, err
		}
		for i := 0; i < len(run.Log); i++ {
			logs = append(logs, &run.Log[i])
		}
		return logs, len(logs), nil
	}

	// add historical logs to the transactional logs.
	runs, n, err := as.FindRuns(ctx, influxdb.RunFilter{Task: filter.Task})
	if err != nil {
		return nil, 0, err
	}

	for _, run := range runs {
		for i := 0; i < len(run.Log); i++ {
			logs = append(logs, &run.Log[i])
		}
	}

	return logs, n, err
}
1021756
func (c *Cluster) ServiceLogs(ctx context.Context, selector *backend.LogSelector, config *apitypes.ContainerLogsOptions) (<-chan *backend.LogMessage, error) {
	c.mu.RLock()
	defer c.mu.RUnlock()

	state := c.currentNodeState()
	if !state.IsActiveManager() {
		return nil, c.errNoManager(state)
	}

	swarmSelector, err := convertSelector(ctx, state.controlClient, selector)
	if err != nil {
		return nil, errors.Wrap(err, "error making log selector")
	}

	// set the streams we'll use
	stdStreams := []swarmapi.LogStream{}
	if config.ShowStdout {
		stdStreams = append(stdStreams, swarmapi.LogStreamStdout)
	}
	if config.ShowStderr {
		stdStreams = append(stdStreams, swarmapi.LogStreamStderr)
	}

	// Get tail value squared away - the number of previous log lines we look at
	var tail int64
	// in ContainerLogs, if the tail value is ANYTHING non-integer, we just set
	// it to -1 (all). i don't agree with that, but i also think no tail value
	// should be legitimate. if you don't pass tail, we assume you want "all"
	if config.Tail == "all" || config.Tail == "" {
		// tail of 0 means send all logs on the swarmkit side
		tail = 0
	} else {
		t, err := strconv.Atoi(config.Tail)
		if err != nil {
			return nil, errors.New("tail value must be a positive integer or \"all\"")
		}
		if t < 0 {
			return nil, errors.New("negative tail values not supported")
		}
		// we actually use negative tail in swarmkit to represent messages
		// backwards starting from the beginning. also, -1 means no logs. so,
		// basically, for api compat with docker container logs, add one and
		// flip the sign. we error above if you try to negative tail, which
		// isn't supported by docker (and would error deeper in the stack
		// anyway)
		//
		// See the logs protobuf for more information
		tail = int64(-(t + 1))
	}

	// get the since value - the time in the past we're looking at logs starting from
	var sinceProto *gogotypes.Timestamp
	if config.Since != "" {
		s, n, err := timetypes.ParseTimestamps(config.Since, 0)
		if err != nil {
			return nil, errors.Wrap(err, "could not parse since timestamp")
		}
		since := time.Unix(s, n)
		sinceProto, err = gogotypes.TimestampProto(since)
		if err != nil {
			return nil, errors.Wrap(err, "could not parse timestamp to proto")
		}
	}

	stream, err := state.logsClient.SubscribeLogs(ctx, &swarmapi.SubscribeLogsRequest{
		Selector: swarmSelector,
		Options: &swarmapi.LogSubscriptionOptions{
			Follow:  config.Follow,
			Streams: stdStreams,
			Tail:    tail,
			Since:   sinceProto,
		},
	})
	if err != nil {
		return nil, err
	}

	messageChan := make(chan *backend.LogMessage, 1)
	go func() {
		defer close(messageChan)
		for {
			// Check the context before doing anything.
			select {
			case <-ctx.Done():
				return
			default:
			}
			subscribeMsg, err := stream.Recv()
			if err == io.EOF {
				return
			}
			// if we're not io.EOF, push the message in and return
			if err != nil {
				select {
				case <-ctx.Done():
				case messageChan <- &backend.LogMessage{Err: err}:
				}
				return
			}

			for _, msg := range subscribeMsg.Messages {
				// make a new message
				m := new(backend.LogMessage)
				m.Attrs = make([]backend.LogAttr, 0, len(msg.Attrs)+3)
				// add the timestamp, adding the error if it fails
				m.Timestamp, err = gogotypes.TimestampFromProto(msg.Timestamp)
				if err != nil {
					m.Err = err
				}

				nodeKey := contextPrefix + ".node.id"
				serviceKey := contextPrefix + ".service.id"
				taskKey := contextPrefix + ".task.id"

				// copy over all of the details
				for _, d := range msg.Attrs {
					switch d.Key {
					case nodeKey, serviceKey, taskKey:
						// we have the final say over context details (in case there
						// is a conflict (if the user added a detail with a context's
						// key for some reason))
					default:
						m.Attrs = append(m.Attrs, backend.LogAttr{Key: d.Key, Value: d.Value})
					}
				}
				m.Attrs = append(m.Attrs,
					backend.LogAttr{Key: nodeKey, Value: msg.Context.NodeID},
					backend.LogAttr{Key: serviceKey, Value: msg.Context.ServiceID},
					backend.LogAttr{Key: taskKey, Value: msg.Context.TaskID},
				)

				switch msg.Stream {
				case swarmapi.LogStreamStdout:
					m.Source = "stdout"
				case swarmapi.LogStreamStderr:
					m.Source = "stderr"
				}
				m.Line = msg.Data

				// there could be a case where the reader stops accepting
				// messages and the context is canceled. we need to check that
				// here, or otherwise we risk blocking forever on the message
				// send.
				select {
				case <-ctx.Done():
					return
				case messageChan <- m:
				}
			}
		}
	}()
	return messageChan, nil
}
947176
func Logs(dockerID string, args []string) error {
	if _, err := FindContainer(dockerID); err != nil {
		return err
	}

	var command []string = []string{"/usr/bin/docker", "logs"}
	if len(args) > 0 {
		command = append(command, args...)
	}
	command = append(command, dockerID)

	glog.V(1).Infof("exec logs command for container:%v command: %+v\n", dockerID, command)
	return syscall.Exec(command[0], command[0:], os.Environ())
}
409205
func collectLogEntries(store raft.LogStore) (*raft.Log, *raft.Log, error) {
	var latest raft.Log

	lastIndex, err := store.LastIndex()
	if err != nil {
		return nil, nil, errors.Annotate(err, "getting last index")
	}

	if lastIndex == 0 {
		return nil, nil, errors.Errorf("no log entries, expected at least one for configuration")
	}

	err = store.GetLog(lastIndex, &latest)
	if err != nil {
		return nil, nil, errors.Annotate(err, "getting last log entry")
	}

	if latest.Type == raft.LogConfiguration {
		return &latest, &latest, nil
	}

	firstIndex, err := store.FirstIndex()
	if err != nil {
		return nil, nil, errors.Annotate(err, "getting first index`")
	}
	current := lastIndex
	for current > firstIndex {
		current--
		var entry raft.Log
		err := store.GetLog(current, &entry)
		if errors.Cause(err) == raft.ErrLogNotFound {
			continue
		} else if err != nil {
			return nil, nil, errors.Annotatef(err, "getting log index %d", current)
		}
		if entry.Type == raft.LogConfiguration {
			return &latest, &entry, nil
		}
	}

	return nil, nil, errors.Errorf("no configuration entry in log")
}
1008586
func GetLoggerWithFields(ctx context.Context, fields map[interface{}]interface{}, keys ...interface{}) Logger {
	// must convert from interface{} -> interface{} to string -> interface{} for logrus.
	lfields := make(logrus.Fields, len(fields))
	for key, value := range fields {
		lfields[fmt.Sprint(key)] = value
	}

	return getLogrusLogger(ctx, keys...).WithFields(lfields)
}