summaryrefslogtreecommitdiff
path: root/libpod/container_log.go
diff options
context:
space:
mode:
authorbaude <bbaude@redhat.com>2019-06-25 08:40:19 -0500
committerbaude <bbaude@redhat.com>2019-06-27 07:56:24 -0500
commit8561b996447793999a6465f9b9e3f0f7bbea2c6a (patch)
tree133cf8d959934eac882535e6b572aee5d0acf3c5 /libpod/container_log.go
parent58a1777f518657ff12744bb69ccf2dab3d429625 (diff)
downloadpodman-8561b996447793999a6465f9b9e3f0f7bbea2c6a.tar.gz
podman-8561b996447793999a6465f9b9e3f0f7bbea2c6a.tar.bz2
podman-8561b996447793999a6465f9b9e3f0f7bbea2c6a.zip
libpod removal from main (phase 2)
this is phase 2 for the removal of libpod from main. Signed-off-by: baude <bbaude@redhat.com>
Diffstat (limited to 'libpod/container_log.go')
-rw-r--r--libpod/container_log.go229
1 files changed, 0 insertions, 229 deletions
diff --git a/libpod/container_log.go b/libpod/container_log.go
deleted file mode 100644
index 374e5a1fc..000000000
--- a/libpod/container_log.go
+++ /dev/null
@@ -1,229 +0,0 @@
-package libpod
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "strings"
- "sync"
- "time"
-
- "github.com/hpcloud/tail"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-const (
- // logTimeFormat is the time format used in the log.
- // It is a modified version of RFC3339Nano that guarantees trailing
- // zeroes are not trimmed, taken from
- // https://github.com/golang/go/issues/19635
- logTimeFormat = "2006-01-02T15:04:05.000000000Z07:00"
-
- // partialLogType signifies a log line that exceeded the buffer
- // length and needed to spill into a new line
- partialLogType = "P"
-
- // fullLogType signifies a log line is full
- fullLogType = "F"
-)
-
-// LogOptions is the options you can use for logs
-type LogOptions struct {
- Details bool
- Follow bool
- Since time.Time
- Tail uint64
- Timestamps bool
- Multi bool
- WaitGroup *sync.WaitGroup
-}
-
-// LogLine describes the information for each line of a log
-type LogLine struct {
- Device string
- ParseLogType string
- Time time.Time
- Msg string
- CID string
-}
-
-// Log is a runtime function that can read one or more container logs.
-func (r *Runtime) Log(containers []*Container, options *LogOptions, logChannel chan *LogLine) error {
- for _, ctr := range containers {
- if err := ctr.ReadLog(options, logChannel); err != nil {
- return err
- }
- }
- return nil
-}
-
-// ReadLog reads a containers log based on the input options and returns loglines over a channel
-func (c *Container) ReadLog(options *LogOptions, logChannel chan *LogLine) error {
- // TODO Skip sending logs until journald logs can be read
- // TODO make this not a magic string
- if c.LogDriver() == JournaldLogging {
- return c.readFromJournal(options, logChannel)
- }
- return c.readFromLogFile(options, logChannel)
-}
-
-func (c *Container) readFromLogFile(options *LogOptions, logChannel chan *LogLine) error {
- t, tailLog, err := getLogFile(c.LogPath(), options)
- if err != nil {
- // If the log file does not exist, this is not fatal.
- if os.IsNotExist(errors.Cause(err)) {
- return nil
- }
- return errors.Wrapf(err, "unable to read log file %s for %s ", c.ID(), c.LogPath())
- }
- options.WaitGroup.Add(1)
- if len(tailLog) > 0 {
- for _, nll := range tailLog {
- nll.CID = c.ID()
- if nll.Since(options.Since) {
- logChannel <- nll
- }
- }
- }
-
- go func() {
- var partial string
- for line := range t.Lines {
- nll, err := newLogLine(line.Text)
- if err != nil {
- logrus.Error(err)
- continue
- }
- if nll.Partial() {
- partial = partial + nll.Msg
- continue
- } else if !nll.Partial() && len(partial) > 1 {
- nll.Msg = partial
- partial = ""
- }
- nll.CID = c.ID()
- if nll.Since(options.Since) {
- logChannel <- nll
- }
- }
- options.WaitGroup.Done()
- }()
- return nil
-}
-
-// getLogFile returns an hp tail for a container given options
-func getLogFile(path string, options *LogOptions) (*tail.Tail, []*LogLine, error) {
- var (
- whence int
- err error
- logTail []*LogLine
- )
- // whence 0=origin, 2=end
- if options.Tail > 0 {
- whence = 2
- logTail, err = getTailLog(path, int(options.Tail))
- if err != nil {
- return nil, nil, err
- }
- }
- seek := tail.SeekInfo{
- Offset: 0,
- Whence: whence,
- }
-
- t, err := tail.TailFile(path, tail.Config{MustExist: true, Poll: true, Follow: options.Follow, Location: &seek, Logger: tail.DiscardingLogger})
- return t, logTail, err
-}
-
-func getTailLog(path string, tail int) ([]*LogLine, error) {
- var (
- tailLog []*LogLine
- nlls []*LogLine
- tailCounter int
- partial string
- )
- content, err := ioutil.ReadFile(path)
- if err != nil {
- return nil, err
- }
- splitContent := strings.Split(string(content), "\n")
- // We read the content in reverse and add each nll until we have the same
- // number of F type messages as the desired tail
- for i := len(splitContent) - 1; i >= 0; i-- {
- if len(splitContent[i]) == 0 {
- continue
- }
- nll, err := newLogLine(splitContent[i])
- if err != nil {
- return nil, err
- }
- nlls = append(nlls, nll)
- if !nll.Partial() {
- tailCounter = tailCounter + 1
- }
- if tailCounter == tail {
- break
- }
- }
- // Now we iterate the results and assemble partial messages to become full messages
- for _, nll := range nlls {
- if nll.Partial() {
- partial = partial + nll.Msg
- } else {
- nll.Msg = nll.Msg + partial
- tailLog = append(tailLog, nll)
- partial = ""
- }
- }
- return tailLog, nil
-}
-
-// String converts a logline to a string for output given whether a detail
-// bool is specified.
-func (l *LogLine) String(options *LogOptions) string {
- var out string
- if options.Multi {
- cid := l.CID
- if len(cid) > 12 {
- cid = cid[:12]
- }
- out = fmt.Sprintf("%s ", cid)
- }
- if options.Timestamps {
- out = out + fmt.Sprintf("%s ", l.Time.Format(logTimeFormat))
- }
- return out + l.Msg
-}
-
-// Since returns a bool as to whether a log line occurred after a given time
-func (l *LogLine) Since(since time.Time) bool {
- return l.Time.After(since)
-}
-
-// newLogLine creates a logLine struct from a container log string
-func newLogLine(line string) (*LogLine, error) {
- splitLine := strings.Split(line, " ")
- if len(splitLine) < 4 {
- return nil, errors.Errorf("'%s' is not a valid container log line", line)
- }
- logTime, err := time.Parse(logTimeFormat, splitLine[0])
- if err != nil {
- return nil, errors.Wrapf(err, "unable to convert time %s from container log", splitLine[0])
- }
- l := LogLine{
- Time: logTime,
- Device: splitLine[1],
- ParseLogType: splitLine[2],
- Msg: strings.Join(splitLine[3:], " "),
- }
- return &l, nil
-}
-
-// Partial returns a bool if the log line is a partial log type
-func (l *LogLine) Partial() bool {
- if l.ParseLogType == partialLogType {
- return true
- }
- return false
-}