From a031b83a09a8628435317a03f199cdc18b78262f Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Wed, 1 Nov 2017 11:24:59 -0400 Subject: Initial checkin from CRI-O repo Signed-off-by: Matthew Heon --- libkpod/logs.go | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 libkpod/logs.go (limited to 'libkpod/logs.go') diff --git a/libkpod/logs.go b/libkpod/logs.go new file mode 100644 index 000000000..00b0f0167 --- /dev/null +++ b/libkpod/logs.go @@ -0,0 +1,80 @@ +package libkpod + +import ( + "path" + "strings" + "time" + + "github.com/hpcloud/tail" +) + +// LogOptions contains all of the options for displaying logs in kpod +type LogOptions struct { + Details bool + Follow bool + SinceTime time.Time + Tail uint64 +} + +// GetLogs gets each line of a log file and, if it matches the criteria in logOptions, sends it down logChan +func (c *ContainerServer) GetLogs(container string, logChan chan string, opts LogOptions) error { + defer close(logChan) + // Get the full ID of the container + ctr, err := c.LookupContainer(container) + if err != nil { + return err + } + + containerID := ctr.ID() + sandbox := ctr.Sandbox() + if sandbox == "" { + sandbox = containerID + } + // Read the log line by line and pass it into the pipe + logsFile := path.Join(c.config.LogDir, sandbox, containerID+".log") + + seekInfo := &tail.SeekInfo{Offset: 0, Whence: 0} + if opts.Tail > 0 { + // seek to correct position in logs files + seekInfo.Offset = int64(opts.Tail) + seekInfo.Whence = 2 + } + + t, err := tail.TailFile(logsFile, tail.Config{Follow: false, ReOpen: false, Location: seekInfo}) + for line := range t.Lines { + if since, err := logSinceTime(opts.SinceTime, line.Text); err != nil || !since { + continue + } + logMessage := line.Text[secondSpaceIndex(line.Text):] + if opts.Details { + // add additional information to line + } + logChan <- logMessage + } + return err +} + +func logSinceTime(sinceTime time.Time, logStr string) (bool, error) { + timestamp := strings.Split(logStr, " ")[0] + logTime, err := time.Parse("2006-01-02T15:04:05.999999999-07:00", timestamp) + if err != nil { + return false, err + } + return logTime.After(sinceTime) || logTime.Equal(sinceTime), nil +} + +// 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 +} -- cgit v1.2.3-54-g00ecf