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

store both logs in a same file, as JSON

This commit is contained in:
Victor Vieux 2013-07-15 16:17:58 +00:00
parent 5756ba9bc4
commit 599f85d4e4
4 changed files with 40 additions and 44 deletions

View file

@ -59,7 +59,6 @@ func assertPipe(input, output string, r io.Reader, w io.Writer, count int) error
return nil return nil
} }
// TestRunHostname checks that 'docker run -h' correctly sets a custom hostname // TestRunHostname checks that 'docker run -h' correctly sets a custom hostname
func TestRunHostname(t *testing.T) { func TestRunHostname(t *testing.T) {
stdout, stdoutPipe := io.Pipe() stdout, stdoutPipe := io.Pipe()
@ -91,7 +90,6 @@ func TestRunHostname(t *testing.T) {
} }
// TestAttachStdin checks attaching to stdin without stdout and stderr. // TestAttachStdin checks attaching to stdin without stdout and stderr.
// 'docker run -i -a stdin' should sends the client's stdin to the command, // 'docker run -i -a stdin' should sends the client's stdin to the command,
// then detach from it and print the container id. // then detach from it and print the container id.
@ -144,15 +142,17 @@ func TestRunAttachStdin(t *testing.T) {
}) })
// Check logs // Check logs
if cmdLogs, err := container.ReadLog("stdout"); err != nil { if cmdLogs, err := container.ReadLog("json"); err != nil {
t.Fatal(err) t.Fatal(err)
} else { } else {
if output, err := ioutil.ReadAll(cmdLogs); err != nil { if output, err := ioutil.ReadAll(cmdLogs); err != nil {
t.Fatal(err) t.Fatal(err)
} else { } else {
expectedLog := "hello\nhi there\n" expectedLogs := []string{"{\"log\":\"hello\\n\",\"stream\":\"stdout\"", "{\"log\":\"hi there\\n\",\"stream\":\"stdout\""}
if string(output) != expectedLog { for _, expectedLog := range expectedLogs {
t.Fatalf("Unexpected logs: should be '%s', not '%s'\n", expectedLog, output) if !strings.Contains(string(output), expectedLog) {
t.Fatalf("Unexpected logs: should contains '%s', it is not '%s'\n", expectedLog, output)
}
} }
} }
} }

View file

@ -640,21 +640,13 @@ func (container *Container) Start(hostConfig *HostConfig) error {
container.cmd = exec.Command("lxc-start", params...) container.cmd = exec.Command("lxc-start", params...)
// Setup logging of stdout and stderr to disk // Setup logging of stdout and stderr to disk
/*
if err := container.runtime.LogToDisk(container.stdout, container.logPath("stdout"), ""); err != nil {
return err
}
if err := container.runtime.LogToDisk(container.stderr, container.logPath("stderr"), ""); err != nil {
return err
}
*/
if err := container.runtime.LogToDisk(container.stdout, container.logPath("json"), "stdout"); err != nil { if err := container.runtime.LogToDisk(container.stdout, container.logPath("json"), "stdout"); err != nil {
return err return err
} }
if err := container.runtime.LogToDisk(container.stderr, container.logPath("json"), "stderr"); err != nil { if err := container.runtime.LogToDisk(container.stderr, container.logPath("json"), "stderr"); err != nil {
return err return err
} }
var err error var err error
if container.Config.Tty { if container.Config.Tty {
err = container.startPty() err = container.startPty()

View file

@ -2,6 +2,7 @@ package docker
import ( import (
"bufio" "bufio"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/dotcloud/docker/auth" "github.com/dotcloud/docker/auth"
@ -1042,20 +1043,21 @@ func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, std
} }
//logs //logs
if logs { if logs {
if stdout { cLog, err := container.ReadLog("json")
cLog, err := container.ReadLog("stdout") if err != nil {
if err != nil { utils.Debugf("Error reading logs (json): %s", err)
utils.Debugf("Error reading logs (stdout): %s", err)
} else if _, err := io.Copy(out, cLog); err != nil {
utils.Debugf("Error streaming logs (stdout): %s", err)
}
} }
if stderr { dec := json.NewDecoder(cLog)
cLog, err := container.ReadLog("stderr") for {
if err != nil { var l utils.JSONLog
utils.Debugf("Error reading logs (stderr): %s", err) if err := dec.Decode(&l); err == io.EOF {
} else if _, err := io.Copy(out, cLog); err != nil { break
utils.Debugf("Error streaming logs (stderr): %s", err) } else if err != nil {
utils.Debugf("Error streaming logs: %s", err)
break
}
if (l.Stream == "stdout" && stdout) || (l.Stream == "stderr" && stderr) {
fmt.Fprintf(out, "%s", l.Log)
} }
} }
} }

View file

@ -247,47 +247,49 @@ func (r *bufReader) Close() error {
type WriteBroadcaster struct { type WriteBroadcaster struct {
sync.Mutex sync.Mutex
writers map[StreamWriter][]byte buf *bytes.Buffer
writers map[StreamWriter]bool
} }
type StreamWriter struct { type StreamWriter struct {
wc io.WriteCloser wc io.WriteCloser
stream string stream string
} }
func (w *WriteBroadcaster) AddWriter(writer io.WriteCloser, stream string) { func (w *WriteBroadcaster) AddWriter(writer io.WriteCloser, stream string) {
w.Lock() w.Lock()
sw := StreamWriter{wc: writer, stream: stream} sw := StreamWriter{wc: writer, stream: stream}
w.writers[sw] = []byte{} w.writers[sw] = true
w.Unlock() w.Unlock()
} }
type JSONLog struct { type JSONLog struct {
Log string `json:"log,omitempty"` Log string `json:"log,omitempty"`
Stream string `json:"stream,omitempty"` Stream string `json:"stream,omitempty"`
Created time.Time `json:"time"` Created time.Time `json:"time"`
} }
func (w *WriteBroadcaster) Write(p []byte) (n int, err error) { func (w *WriteBroadcaster) Write(p []byte) (n int, err error) {
w.Lock() w.Lock()
defer w.Unlock() defer w.Unlock()
w.buf.Write(p)
for sw := range w.writers { for sw := range w.writers {
lp := p lp := p
if sw.stream != "" { if sw.stream != "" {
w.writers[sw] = append(w.writers[sw], p...) lp = nil
s := string(p) for {
if s[len(s)-1] == '\n' { line, err := w.buf.ReadString('\n')
/* lp, err = json.Marshal(&JSONLog{Log: s, Stream: sw.stream, Created: time.Now()}) if err != nil {
w.buf.Write([]byte(line))
break
}
b, err := json.Marshal(&JSONLog{Log: line, Stream: sw.stream, Created: time.Now()})
if err != nil { if err != nil {
// On error, evict the writer // On error, evict the writer
delete(w.writers, sw) delete(w.writers, sw)
continue continue
} }
*/ lp = append(lp, b...)
lp = []byte("[" + time.Now().String() + "] [" + sw.stream + "] " + s)
w.writers[sw] = []byte{}
} else {
continue
} }
} }
if n, err := sw.wc.Write(lp); err != nil || n != len(lp) { if n, err := sw.wc.Write(lp); err != nil || n != len(lp) {
@ -304,12 +306,12 @@ func (w *WriteBroadcaster) CloseWriters() error {
for sw := range w.writers { for sw := range w.writers {
sw.wc.Close() sw.wc.Close()
} }
w.writers = make(map[StreamWriter][]byte) w.writers = make(map[StreamWriter]bool)
return nil return nil
} }
func NewWriteBroadcaster() *WriteBroadcaster { func NewWriteBroadcaster() *WriteBroadcaster {
return &WriteBroadcaster{writers: make(map[StreamWriter][]byte)} return &WriteBroadcaster{writers: make(map[StreamWriter]bool), buf: bytes.NewBuffer(nil)}
} }
func GetTotalUsedFds() int { func GetTotalUsedFds() int {