This repository has been archived by the owner on Feb 8, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 196
/
logs.go
116 lines (103 loc) · 2.68 KB
/
logs.go
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package daemon
import (
"fmt"
"io"
"strconv"
"time"
"github.com/docker/docker/daemon/logger"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/stdcopy"
"github.com/golang/glog"
)
// ContainerLogsConfig holds configs for logging operations. Exists
// for users of the daemon to to pass it a logging configuration.
type ContainerLogsConfig struct {
// if true stream log output
Follow bool
// if true include timestamps for each line of log output
Timestamps bool
// return that many lines of log output from the end
Tail string
// filter logs by returning on those entries after this time
Since time.Time
// whether or not to show stdout and stderr as well as log entries.
UseStdout, UseStderr bool
OutStream io.Writer
Stop <-chan bool
}
func (daemon *Daemon) GetContainerLogs(container string, config *ContainerLogsConfig) (err error) {
var (
tailLines int
)
p, id, ok := daemon.PodList.GetByContainerIdOrName(container)
if !ok {
err = fmt.Errorf("cannot find container %s", container)
glog.Error(err)
return err
}
l := p.ContainerLogger(id)
if l == nil {
err = fmt.Errorf("cannot get logger for container %s", container)
glog.Error(err)
return err
}
logReader, ok := l.(logger.LogReader)
if !ok {
err = fmt.Errorf("container %s: logger not support read", container)
glog.Error(err)
return err
}
follow := config.Follow && p.IsContainerAlive(id)
tailLines, err = strconv.Atoi(config.Tail)
if err != nil {
tailLines = -1
}
readConfig := logger.ReadConfig{
Since: config.Since,
Tail: tailLines,
Follow: follow,
}
logs := logReader.ReadLogs(readConfig)
wf := ioutils.NewWriteFlusher(config.OutStream)
defer wf.Close()
wf.Flush()
var outStream io.Writer = wf
errStream := outStream
if !p.ContainerHasTty(id) {
errStream = stdcopy.NewStdWriter(outStream, stdcopy.Stderr)
outStream = stdcopy.NewStdWriter(outStream, stdcopy.Stdout)
}
for {
select {
case <-config.Stop:
return nil
case e := <-logs.Err:
glog.Errorf("Error streaming logs: %v", e)
return nil
case msg, ok := <-logs.Msg:
if !ok {
glog.V(1).Info("logs: end stream")
logs.Close()
return nil
}
logLine := msg.Line
if config.Timestamps {
logLine = append([]byte(msg.Timestamp.Format(logger.TimeFormat)+" "), logLine...)
}
if msg.Source == "stdout" && config.UseStdout {
glog.V(2).Info("print stdout log: ", logLine)
_, err := outStream.Write(logLine)
if err != nil {
return nil
}
}
if msg.Source == "stderr" && config.UseStderr {
glog.V(2).Info("print stderr log: ", logLine)
_, err := errStream.Write(logLine)
if err != nil {
return nil
}
}
}
}
}