1
0
Эх сурвалжийг харах

join log stream before we split by line

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 4 жил өмнө
parent
commit
9097d71009

+ 24 - 14
local/compose/logs.go

@@ -88,15 +88,17 @@ func (s *composeService) Logs(ctx context.Context, projectName string, consumer
 }
 
 type splitBuffer struct {
+	buffer    bytes.Buffer
 	name      string
+	service   string
 	container string
 	consumer  compose.ContainerEventListener
-	service   string
 }
 
 // getWriter creates a io.Writer that will actually split by line and format by LogConsumer
 func getWriter(name, service, container string, events compose.ContainerEventListener) io.Writer {
-	return splitBuffer{
+	return &splitBuffer{
+		buffer:    bytes.Buffer{},
 		name:      name,
 		service:   service,
 		container: container,
@@ -104,18 +106,26 @@ func getWriter(name, service, container string, events compose.ContainerEventLis
 	}
 }
 
-func (s splitBuffer) Write(b []byte) (n int, err error) {
-	split := bytes.Split(b, []byte{'\n'})
-	for _, line := range split {
-		if len(line) != 0 {
-			s.consumer(compose.ContainerEvent{
-				Type:    compose.ContainerEventLog,
-				Name:    s.name,
-				Service: s.service,
-				Source:  s.container,
-				Line:    string(line),
-			})
+// Write implements io.Writer. joins all input, splits on the separator and yields each chunk
+func (s *splitBuffer) Write(b []byte) (int, error) {
+	n, err := s.buffer.Write(b)
+	if err != nil {
+		return n, err
+	}
+	for {
+		b = s.buffer.Bytes()
+		index := bytes.Index(b, []byte{'\n'})
+		if index < 0 {
+			break
 		}
+		line := s.buffer.Next(index + 1)
+		s.consumer(compose.ContainerEvent{
+			Type:    compose.ContainerEventLog,
+			Name:    s.name,
+			Service: s.service,
+			Source:  s.container,
+			Line:    string(line[:len(line)-1]),
+		})
 	}
-	return len(b), nil
+	return n, nil
 }

+ 41 - 0
local/compose/logs_test.go

@@ -0,0 +1,41 @@
+/*
+   Copyright 2020 Docker Compose CLI authors
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package compose
+
+import (
+	"testing"
+
+	"gotest.tools/v3/assert"
+
+	"github.com/docker/compose-cli/api/compose"
+)
+
+func TestSplitWriter(t *testing.T) {
+	var lines []string
+	w := getWriter("service", "container", func(event compose.ContainerEvent) {
+		lines = append(lines, event.Line)
+	})
+	w.Write([]byte("h"))        //nolint: errcheck
+	w.Write([]byte("e"))        //nolint: errcheck
+	w.Write([]byte("l"))        //nolint: errcheck
+	w.Write([]byte("l"))        //nolint: errcheck
+	w.Write([]byte("o"))        //nolint: errcheck
+	w.Write([]byte("\n"))       //nolint: errcheck
+	w.Write([]byte("world!\n")) //nolint: errcheck
+	assert.DeepEqual(t, lines, []string{"hello", "world!"})
+
+}