diff options
author | umohnani8 <umohnani@redhat.com> | 2018-08-30 10:10:05 -0400 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2018-09-05 13:48:20 +0000 |
commit | 7ffb8a79007414e510ac14ac0d682e1bbfe30c7c (patch) | |
tree | 8c031232a361c5d3ed662bc6bc9082f23cb2911a /cmd/podman/logs.go | |
parent | 4ddcbd7941e8cb32cbdcac2f1aa3a939e82be764 (diff) | |
download | podman-7ffb8a79007414e510ac14ac0d682e1bbfe30c7c.tar.gz podman-7ffb8a79007414e510ac14ac0d682e1bbfe30c7c.tar.bz2 podman-7ffb8a79007414e510ac14ac0d682e1bbfe30c7c.zip |
Add CRI logs parsing to podman logs
Podman logs was not parsing CRI logs well, especially
the F and P logs. Now using the same parsing code as
in kube here.
Signed-off-by: umohnani8 <umohnani@redhat.com>
Closes: #1403
Approved by: rhatdan
Diffstat (limited to 'cmd/podman/logs.go')
-rw-r--r-- | cmd/podman/logs.go | 161 |
1 files changed, 8 insertions, 153 deletions
diff --git a/cmd/podman/logs.go b/cmd/podman/logs.go index 555c65fa5..34d062c56 100644 --- a/cmd/podman/logs.go +++ b/cmd/podman/logs.go @@ -1,28 +1,17 @@ package main import ( - "fmt" - "io" "os" - "strings" "time" - "bufio" "github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/libpod" + "github.com/containers/libpod/pkg/logs" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/urfave/cli" ) -type logOptions struct { - details bool - follow bool - sinceTime time.Time - tail uint64 - showTimestamps bool -} - var ( logsFlags = []cli.Flag{ cli.BoolFlag{ @@ -90,12 +79,12 @@ func logsCmd(c *cli.Context) error { sinceTime = since } - opts := logOptions{ - details: c.Bool("details"), - follow: c.Bool("follow"), - sinceTime: sinceTime, - tail: c.Uint64("tail"), - showTimestamps: c.Bool("timestamps"), + opts := &logs.LogOptions{ + Details: c.Bool("details"), + Follow: c.Bool("follow"), + Since: sinceTime, + Tail: c.Uint64("tail"), + Timestamps: c.Bool("timestamps"), } if c.Bool("latest") { @@ -123,141 +112,7 @@ func logsCmd(c *cli.Context) error { return nil } } - - file, err := os.Open(logPath) - if err != nil { - return errors.Wrapf(err, "unable to read container log file") - } - defer file.Close() - reader := bufio.NewReader(file) - if opts.follow { - followLog(reader, opts, ctr) - } else { - dumpLog(reader, opts) - } - return err -} - -func followLog(reader *bufio.Reader, opts logOptions, ctr *libpod.Container) error { - var cacheOutput []string - firstPass := false - if opts.tail > 0 { - firstPass = true - } - // We need to read the entire file in here until we reach EOF - // and then dump it out in the case that the user also wants - // tail output - for { - line, err := reader.ReadString('\n') - if err == io.EOF && opts.follow { - if firstPass { - firstPass = false - cacheLen := int64(len(cacheOutput)) - start := int64(0) - if cacheLen > int64(opts.tail) { - start = cacheLen - int64(opts.tail) - } - for i := start; i < cacheLen; i++ { - printLine(cacheOutput[i], opts) - } - continue - } - time.Sleep(1 * time.Second) - // Check if container is still running or paused - state, err := ctr.State() - if err != nil { - return err - } - if state != libpod.ContainerStateRunning && state != libpod.ContainerStatePaused { - break - } - continue - } - // exits - if err != nil { - break - } - if firstPass { - cacheOutput = append(cacheOutput, line) - continue - } - printLine(line, opts) - } - return nil -} - -func dumpLog(reader *bufio.Reader, opts logOptions) error { - output := readLog(reader, opts) - for _, line := range output { - printLine(line, opts) - } - - return nil -} - -func readLog(reader *bufio.Reader, opts logOptions) []string { - var output []string - for { - line, err := reader.ReadString('\n') - if err != nil { - break - } - output = append(output, line) - } - start := 0 - if opts.tail > 0 { - if len(output) > int(opts.tail) { - start = len(output) - int(opts.tail) - } - } - return output[start:] -} - -func printLine(line string, opts logOptions) { - start := 3 - fields := strings.Fields(line) - if opts.showTimestamps || !isStringTimestamp(fields[0]) { - start = 0 - } - if opts.sinceTime.IsZero() || logSinceTime(opts.sinceTime, fields[0]) { - output := strings.Join(fields[start:], " ") - fmt.Printf("%s\n", output) - } -} - -func isStringTimestamp(t string) bool { - _, err := time.Parse("2006-01-02T15:04:05.999999999-07:00", t) - if err != nil { - return false - } - return true -} - -// returns true if the time stamps of the logs are equal to or after the -// timestamp comparing to -func logSinceTime(sinceTime time.Time, logStr string) bool { - timestamp := strings.Split(logStr, " ")[0] - logTime, err := time.Parse("2006-01-02T15:04:05.999999999-07:00", timestamp) - if err != nil { - return false - } - return logTime.After(sinceTime) || logTime.Equal(sinceTime) -} - -// secondSpaceIndex returns the index of the second space in a string -// In a line of the logs, the first two tokens are a timestamp and stdout/stderr, -// followed by the message itself. This allows us to get the index of the message -// and avoid sending the other information back to the caller of GetLogs() -func secondSpaceIndex(line string) int { - index := strings.Index(line, " ") - if index == -1 { - return 0 - } - index = strings.Index(line[index:], " ") - if index == -1 { - return 0 - } - return index + return logs.ReadLogs(logPath, ctr, opts) } // parseInputTime takes the users input and to determine if it is valid and |