mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
4be98a38e7
When the multireader hits EOF, we will always get EOF from it, so we cannot store the multrireader fro later error handling, only for the decoder. Thanks @tobiasstadler for pointing this error out. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
154 lines
3.6 KiB
Go
154 lines
3.6 KiB
Go
package jsonfilelog // import "github.com/docker/docker/daemon/logger/jsonfilelog"
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"io"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/docker/docker/daemon/logger"
|
|
"gotest.tools/v3/assert"
|
|
"gotest.tools/v3/fs"
|
|
)
|
|
|
|
func BenchmarkJSONFileLoggerReadLogs(b *testing.B) {
|
|
tmp := fs.NewDir(b, "bench-jsonfilelog")
|
|
defer tmp.Remove()
|
|
|
|
jsonlogger, err := New(logger.Info{
|
|
ContainerID: "a7317399f3f857173c6179d44823594f8294678dea9999662e5c625b5a1c7657",
|
|
LogPath: tmp.Join("container.log"),
|
|
Config: map[string]string{
|
|
"labels": "first,second",
|
|
},
|
|
ContainerLabels: map[string]string{
|
|
"first": "label_value",
|
|
"second": "label_foo",
|
|
},
|
|
})
|
|
assert.NilError(b, err)
|
|
defer jsonlogger.Close()
|
|
|
|
msg := &logger.Message{
|
|
Line: []byte("Line that thinks that it is log line from docker\n"),
|
|
Source: "stderr",
|
|
Timestamp: time.Now().UTC(),
|
|
}
|
|
|
|
buf := bytes.NewBuffer(nil)
|
|
assert.NilError(b, marshalMessage(msg, nil, buf))
|
|
b.SetBytes(int64(buf.Len()))
|
|
|
|
b.ResetTimer()
|
|
|
|
chError := make(chan error, b.N+1)
|
|
go func() {
|
|
for i := 0; i < b.N; i++ {
|
|
chError <- jsonlogger.Log(msg)
|
|
}
|
|
chError <- jsonlogger.Close()
|
|
}()
|
|
|
|
lw := jsonlogger.(*JSONFileLogger).ReadLogs(logger.ReadConfig{Follow: true})
|
|
for {
|
|
select {
|
|
case <-lw.Msg:
|
|
case <-lw.WatchProducerGone():
|
|
return
|
|
case err := <-chError:
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEncodeDecode(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m1 := &logger.Message{Line: []byte("hello 1"), Timestamp: time.Now(), Source: "stdout"}
|
|
m2 := &logger.Message{Line: []byte("hello 2"), Timestamp: time.Now(), Source: "stdout"}
|
|
m3 := &logger.Message{Line: []byte("hello 3"), Timestamp: time.Now(), Source: "stdout"}
|
|
|
|
buf := bytes.NewBuffer(nil)
|
|
assert.Assert(t, marshalMessage(m1, nil, buf))
|
|
assert.Assert(t, marshalMessage(m2, nil, buf))
|
|
assert.Assert(t, marshalMessage(m3, nil, buf))
|
|
|
|
dec := decodeFunc(buf)
|
|
defer dec.Close()
|
|
|
|
msg, err := dec.Decode()
|
|
assert.NilError(t, err)
|
|
assert.Assert(t, string(msg.Line) == "hello 1\n", string(msg.Line))
|
|
|
|
msg, err = dec.Decode()
|
|
assert.NilError(t, err)
|
|
assert.Assert(t, string(msg.Line) == "hello 2\n")
|
|
|
|
msg, err = dec.Decode()
|
|
assert.NilError(t, err)
|
|
assert.Assert(t, string(msg.Line) == "hello 3\n")
|
|
|
|
_, err = dec.Decode()
|
|
assert.Assert(t, err == io.EOF)
|
|
}
|
|
|
|
func TestUnexpectedEOF(t *testing.T) {
|
|
buf := bytes.NewBuffer(nil)
|
|
msg1 := &logger.Message{Timestamp: time.Now(), Line: []byte("hello1")}
|
|
msg2 := &logger.Message{Timestamp: time.Now(), Line: []byte("hello2")}
|
|
|
|
err := marshalMessage(msg1, json.RawMessage{}, buf)
|
|
assert.NilError(t, err)
|
|
err = marshalMessage(msg2, json.RawMessage{}, buf)
|
|
assert.NilError(t, err)
|
|
|
|
r := &readerWithErr{
|
|
err: io.EOF,
|
|
after: buf.Len() / 4,
|
|
r: buf,
|
|
}
|
|
dec := &decoder{rdr: r, maxRetry: 1}
|
|
|
|
_, err = dec.Decode()
|
|
assert.Error(t, err, io.ErrUnexpectedEOF.Error())
|
|
// again just to check
|
|
_, err = dec.Decode()
|
|
assert.Error(t, err, io.ErrUnexpectedEOF.Error())
|
|
|
|
// reset the error
|
|
// from here all reads should succeed until we get EOF on the underlying reader
|
|
r.err = nil
|
|
|
|
msg, err := dec.Decode()
|
|
assert.NilError(t, err)
|
|
assert.Equal(t, string(msg1.Line)+"\n", string(msg.Line))
|
|
|
|
msg, err = dec.Decode()
|
|
assert.NilError(t, err)
|
|
assert.Equal(t, string(msg2.Line)+"\n", string(msg.Line))
|
|
|
|
_, err = dec.Decode()
|
|
assert.Error(t, err, io.EOF.Error())
|
|
}
|
|
|
|
type readerWithErr struct {
|
|
err error
|
|
after int
|
|
r io.Reader
|
|
read int
|
|
}
|
|
|
|
func (r *readerWithErr) Read(p []byte) (int, error) {
|
|
if r.err != nil && r.read > r.after {
|
|
return 0, r.err
|
|
}
|
|
|
|
n, err := r.r.Read(p[:1])
|
|
if n > 0 {
|
|
r.read += n
|
|
}
|
|
return n, err
|
|
}
|