summaryrefslogtreecommitdiff
path: root/libkpod/logs.go
blob: 00b0f01674de03552e9bcac5a3e5668b1010d373 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
}