kubernetes/vendor/github.com/opencontainers/runc/libcontainer/logs/logs.go

package logs

import (
	"bufio"
	"encoding/json"
	"io"

	"github.com/sirupsen/logrus"
)

func ForwardLogs(logPipe io.ReadCloser) chan error {
	done := make(chan error, 1)
	s := bufio.NewScanner(logPipe)

	logger := logrus.StandardLogger()
	if logger.ReportCaller {
		// Need a copy of the standard logger, but with ReportCaller
		// turned off, as the logs are merely forwarded and their
		// true source is not this file/line/function.
		logNoCaller := *logrus.StandardLogger()
		logNoCaller.ReportCaller = false
		logger = &logNoCaller
	}

	go func() {
		for s.Scan() {
			processEntry(s.Bytes(), logger)
		}
		if err := logPipe.Close(); err != nil {
			logrus.Errorf("error closing log source: %v", err)
		}
		// The only error we want to return is when reading from
		// logPipe has failed.
		done <- s.Err()
		close(done)
	}()

	return done
}

func processEntry(text []byte, logger *logrus.Logger) {
	if len(text) == 0 {
		return
	}

	var jl struct {
		Level logrus.Level `json:"level"`
		Msg   string       `json:"msg"`
	}
	if err := json.Unmarshal(text, &jl); err != nil {
		logrus.Errorf("failed to decode %q to json: %v", text, err)
		return
	}

	logger.Log(jl.Level, jl.Msg)
}