diff options
author | baude <bbaude@redhat.com> | 2019-06-25 08:40:19 -0500 |
---|---|---|
committer | baude <bbaude@redhat.com> | 2019-06-27 07:56:24 -0500 |
commit | 8561b996447793999a6465f9b9e3f0f7bbea2c6a (patch) | |
tree | 133cf8d959934eac882535e6b572aee5d0acf3c5 /libpod/container_log.go | |
parent | 58a1777f518657ff12744bb69ccf2dab3d429625 (diff) | |
download | podman-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.go | 229 |
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 -} |