summaryrefslogtreecommitdiff
path: root/cmd/podman/logs.go
diff options
context:
space:
mode:
authorumohnani8 <umohnani@redhat.com>2018-08-30 10:10:05 -0400
committerAtomic Bot <atomic-devel@projectatomic.io>2018-09-05 13:48:20 +0000
commit7ffb8a79007414e510ac14ac0d682e1bbfe30c7c (patch)
tree8c031232a361c5d3ed662bc6bc9082f23cb2911a /cmd/podman/logs.go
parent4ddcbd7941e8cb32cbdcac2f1aa3a939e82be764 (diff)
downloadpodman-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.go161
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