|
@@ -20,14 +20,16 @@ type Copier struct {
|
|
|
srcs map[string]io.Reader
|
|
|
dst Logger
|
|
|
copyJobs sync.WaitGroup
|
|
|
+ closed chan struct{}
|
|
|
}
|
|
|
|
|
|
// NewCopier creates a new Copier
|
|
|
func NewCopier(cid string, srcs map[string]io.Reader, dst Logger) *Copier {
|
|
|
return &Copier{
|
|
|
- cid: cid,
|
|
|
- srcs: srcs,
|
|
|
- dst: dst,
|
|
|
+ cid: cid,
|
|
|
+ srcs: srcs,
|
|
|
+ dst: dst,
|
|
|
+ closed: make(chan struct{}),
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -44,24 +46,28 @@ func (c *Copier) copySrc(name string, src io.Reader) {
|
|
|
reader := bufio.NewReader(src)
|
|
|
|
|
|
for {
|
|
|
- line, err := reader.ReadBytes('\n')
|
|
|
- line = bytes.TrimSuffix(line, []byte{'\n'})
|
|
|
+ select {
|
|
|
+ case <-c.closed:
|
|
|
+ return
|
|
|
+ default:
|
|
|
+ line, err := reader.ReadBytes('\n')
|
|
|
+ line = bytes.TrimSuffix(line, []byte{'\n'})
|
|
|
|
|
|
- // ReadBytes can return full or partial output even when it failed.
|
|
|
- // e.g. it can return a full entry and EOF.
|
|
|
- if err == nil || len(line) > 0 {
|
|
|
- if logErr := c.dst.Log(&Message{ContainerID: c.cid, Line: line, Source: name, Timestamp: time.Now().UTC()}); logErr != nil {
|
|
|
- logrus.Errorf("Failed to log msg %q for logger %s: %s", line, c.dst.Name(), logErr)
|
|
|
+ // ReadBytes can return full or partial output even when it failed.
|
|
|
+ // e.g. it can return a full entry and EOF.
|
|
|
+ if err == nil || len(line) > 0 {
|
|
|
+ if logErr := c.dst.Log(&Message{ContainerID: c.cid, Line: line, Source: name, Timestamp: time.Now().UTC()}); logErr != nil {
|
|
|
+ logrus.Errorf("Failed to log msg %q for logger %s: %s", line, c.dst.Name(), logErr)
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- if err != nil {
|
|
|
- if err != io.EOF {
|
|
|
- logrus.Errorf("Error scanning log stream: %s", err)
|
|
|
+ if err != nil {
|
|
|
+ if err != io.EOF {
|
|
|
+ logrus.Errorf("Error scanning log stream: %s", err)
|
|
|
+ }
|
|
|
+ return
|
|
|
}
|
|
|
- return
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -69,3 +75,12 @@ func (c *Copier) copySrc(name string, src io.Reader) {
|
|
|
func (c *Copier) Wait() {
|
|
|
c.copyJobs.Wait()
|
|
|
}
|
|
|
+
|
|
|
+// Close closes the copier
|
|
|
+func (c *Copier) Close() {
|
|
|
+ select {
|
|
|
+ case <-c.closed:
|
|
|
+ default:
|
|
|
+ close(c.closed)
|
|
|
+ }
|
|
|
+}
|