1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #34888 from jahkeup/sized-logger

logger: copy to log driver's bufsize, fixes #34887
This commit is contained in:
Yong Tang 2017-10-30 12:37:41 -07:00 committed by GitHub
commit dfc2d62632
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 85 additions and 5 deletions

View file

@ -275,6 +275,10 @@ func (l *logStream) Name() string {
return name return name
} }
func (l *logStream) BufSize() int {
return maximumBytesPerEvent
}
// Log submits messages for logging by an instance of the awslogs logging driver // Log submits messages for logging by an instance of the awslogs logging driver
func (l *logStream) Log(msg *logger.Message) error { func (l *logStream) Log(msg *logger.Message) error {
l.lock.RLock() l.lock.RLock()

View file

@ -1052,6 +1052,11 @@ func TestCreateTagSuccess(t *testing.T) {
} }
} }
func TestIsSizedLogger(t *testing.T) {
awslogs := &logStream{}
assert.Implements(t, (*logger.SizedLogger)(nil), awslogs, "awslogs should implement SizedLogger")
}
func BenchmarkUnwrapEvents(b *testing.B) { func BenchmarkUnwrapEvents(b *testing.B) {
events := make([]wrappedEvent, maximumLogEventsPerPut) events := make([]wrappedEvent, maximumLogEventsPerPut)
for i := 0; i < maximumLogEventsPerPut; i++ { for i := 0; i < maximumLogEventsPerPut; i++ {

View file

@ -10,8 +10,13 @@ import (
) )
const ( const (
bufSize = 16 * 1024 // readSize is the maximum bytes read during a single read
// operation.
readSize = 2 * 1024 readSize = 2 * 1024
// defaultBufSize provides a reasonable default for loggers that do
// not have an external limit to impose on log line size.
defaultBufSize = 16 * 1024
) )
// Copier can copy logs from specified sources to Logger and attach Timestamp. // Copier can copy logs from specified sources to Logger and attach Timestamp.
@ -44,7 +49,13 @@ func (c *Copier) Run() {
func (c *Copier) copySrc(name string, src io.Reader) { func (c *Copier) copySrc(name string, src io.Reader) {
defer c.copyJobs.Done() defer c.copyJobs.Done()
bufSize := defaultBufSize
if sizedLogger, ok := c.dst.(SizedLogger); ok {
bufSize = sizedLogger.BufSize()
}
buf := make([]byte, bufSize) buf := make([]byte, bufSize)
n := 0 n := 0
eof := false eof := false

View file

@ -31,6 +31,25 @@ func (l *TestLoggerJSON) Close() error { return nil }
func (l *TestLoggerJSON) Name() string { return "json" } func (l *TestLoggerJSON) Name() string { return "json" }
type TestSizedLoggerJSON struct {
*json.Encoder
mu sync.Mutex
}
func (l *TestSizedLoggerJSON) Log(m *Message) error {
l.mu.Lock()
defer l.mu.Unlock()
return l.Encode(m)
}
func (*TestSizedLoggerJSON) Close() error { return nil }
func (*TestSizedLoggerJSON) Name() string { return "sized-json" }
func (*TestSizedLoggerJSON) BufSize() int {
return 32 * 1024
}
func TestCopier(t *testing.T) { func TestCopier(t *testing.T) {
stdoutLine := "Line that thinks that it is log line from docker stdout" stdoutLine := "Line that thinks that it is log line from docker stdout"
stderrLine := "Line that thinks that it is log line from docker stderr" stderrLine := "Line that thinks that it is log line from docker stderr"
@ -104,10 +123,9 @@ func TestCopier(t *testing.T) {
// TestCopierLongLines tests long lines without line breaks // TestCopierLongLines tests long lines without line breaks
func TestCopierLongLines(t *testing.T) { func TestCopierLongLines(t *testing.T) {
// Long lines (should be split at "bufSize") // Long lines (should be split at "defaultBufSize")
const bufSize = 16 * 1024 stdoutLongLine := strings.Repeat("a", defaultBufSize)
stdoutLongLine := strings.Repeat("a", bufSize) stderrLongLine := strings.Repeat("b", defaultBufSize)
stderrLongLine := strings.Repeat("b", bufSize)
stdoutTrailingLine := "stdout trailing line" stdoutTrailingLine := "stdout trailing line"
stderrTrailingLine := "stderr trailing line" stderrTrailingLine := "stderr trailing line"
@ -205,6 +223,41 @@ func TestCopierSlow(t *testing.T) {
} }
} }
func TestCopierWithSized(t *testing.T) {
var jsonBuf bytes.Buffer
expectedMsgs := 2
sizedLogger := &TestSizedLoggerJSON{Encoder: json.NewEncoder(&jsonBuf)}
logbuf := bytes.NewBufferString(strings.Repeat(".", sizedLogger.BufSize()*expectedMsgs))
c := NewCopier(map[string]io.Reader{"stdout": logbuf}, sizedLogger)
c.Run()
// Wait for Copier to finish writing to the buffered logger.
c.Wait()
c.Close()
recvdMsgs := 0
dec := json.NewDecoder(&jsonBuf)
for {
var msg Message
if err := dec.Decode(&msg); err != nil {
if err == io.EOF {
break
}
t.Fatal(err)
}
if msg.Source != "stdout" {
t.Fatalf("Wrong Source: %q, should be %q", msg.Source, "stdout")
}
if len(msg.Line) != sizedLogger.BufSize() {
t.Fatalf("Line was not of expected max length %d, was %d", sizedLogger.BufSize(), len(msg.Line))
}
recvdMsgs++
}
if recvdMsgs != expectedMsgs {
t.Fatalf("expected to receive %d messages, actually received %d", expectedMsgs, recvdMsgs)
}
}
type BenchmarkLoggerDummy struct { type BenchmarkLoggerDummy struct {
} }

View file

@ -78,6 +78,13 @@ type Logger interface {
Close() error Close() error
} }
// SizedLogger is the interface for logging drivers that can control
// the size of buffer used for their messages.
type SizedLogger interface {
Logger
BufSize() int
}
// ReadConfig is the configuration passed into ReadLogs. // ReadConfig is the configuration passed into ReadLogs.
type ReadConfig struct { type ReadConfig struct {
Since time.Time Since time.Time