From 066330fc9687edd3f8a5066fd4201ea14af15f93 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Thu, 31 Jul 2014 21:03:21 +0000 Subject: [PATCH] Move "logs" to daemon/logs.go This is part of an effort to break apart the deprecated server/ package Docker-DCO-1.1-Signed-off-by: Solomon Hykes (github: shykes) --- daemon/daemon.go | 3 + daemon/logs.go | 133 ++++++++++++++++++++++++++++++++++++++++++++ server/container.go | 122 ---------------------------------------- server/init.go | 1 - 4 files changed, 136 insertions(+), 123 deletions(-) create mode 100644 daemon/logs.go diff --git a/daemon/daemon.go b/daemon/daemon.go index 27c380b1d3..333a6f870e 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -144,6 +144,9 @@ func (daemon *Daemon) Install(eng *engine.Engine) error { if err := eng.Register("commit", daemon.ContainerCommit); err != nil { return err } + if err := eng.Register("logs", daemon.ContainerLogs); err != nil { + return err + } return nil } diff --git a/daemon/logs.go b/daemon/logs.go new file mode 100644 index 0000000000..edfffac4ff --- /dev/null +++ b/daemon/logs.go @@ -0,0 +1,133 @@ +package daemon + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "os" + "strconv" + "time" + + "github.com/docker/docker/pkg/tailfile" + + "github.com/docker/docker/engine" + "github.com/docker/docker/utils" +) + +func (daemon *Daemon) ContainerLogs(job *engine.Job) engine.Status { + if len(job.Args) != 1 { + return job.Errorf("Usage: %s CONTAINER\n", job.Name) + } + + var ( + name = job.Args[0] + stdout = job.GetenvBool("stdout") + stderr = job.GetenvBool("stderr") + tail = job.Getenv("tail") + follow = job.GetenvBool("follow") + times = job.GetenvBool("timestamps") + lines = -1 + format string + ) + if !(stdout || stderr) { + return job.Errorf("You must choose at least one stream") + } + if times { + format = time.RFC3339Nano + } + if tail == "" { + tail = "all" + } + container := daemon.Get(name) + if container == nil { + return job.Errorf("No such container: %s", name) + } + cLog, err := container.ReadLog("json") + if err != nil && os.IsNotExist(err) { + // Legacy logs + utils.Debugf("Old logs format") + if stdout { + cLog, err := container.ReadLog("stdout") + if err != nil { + utils.Errorf("Error reading logs (stdout): %s", err) + } else if _, err := io.Copy(job.Stdout, cLog); err != nil { + utils.Errorf("Error streaming logs (stdout): %s", err) + } + } + if stderr { + cLog, err := container.ReadLog("stderr") + if err != nil { + utils.Errorf("Error reading logs (stderr): %s", err) + } else if _, err := io.Copy(job.Stderr, cLog); err != nil { + utils.Errorf("Error streaming logs (stderr): %s", err) + } + } + } else if err != nil { + utils.Errorf("Error reading logs (json): %s", err) + } else { + if tail != "all" { + var err error + lines, err = strconv.Atoi(tail) + if err != nil { + utils.Errorf("Failed to parse tail %s, error: %v, show all logs", err) + lines = -1 + } + } + if lines != 0 { + if lines > 0 { + f := cLog.(*os.File) + ls, err := tailfile.TailFile(f, lines) + if err != nil { + return job.Error(err) + } + tmp := bytes.NewBuffer([]byte{}) + for _, l := range ls { + fmt.Fprintf(tmp, "%s\n", l) + } + cLog = tmp + } + dec := json.NewDecoder(cLog) + for { + l := &utils.JSONLog{} + + if err := dec.Decode(l); err == io.EOF { + break + } else if err != nil { + utils.Errorf("Error streaming logs: %s", err) + break + } + logLine := l.Log + if times { + logLine = fmt.Sprintf("%s %s", l.Created.Format(format), logLine) + } + if l.Stream == "stdout" && stdout { + fmt.Fprintf(job.Stdout, "%s", logLine) + } + if l.Stream == "stderr" && stderr { + fmt.Fprintf(job.Stderr, "%s", logLine) + } + } + } + } + if follow { + errors := make(chan error, 2) + if stdout { + stdoutPipe := container.StdoutLogPipe() + go func() { + errors <- utils.WriteLog(stdoutPipe, job.Stdout, format) + }() + } + if stderr { + stderrPipe := container.StderrLogPipe() + go func() { + errors <- utils.WriteLog(stderrPipe, job.Stderr, format) + }() + } + err := <-errors + if err != nil { + utils.Errorf("%s", err) + } + } + return engine.StatusOK +} diff --git a/server/container.go b/server/container.go index 6ac46ba3b6..c711b7cbea 100644 --- a/server/container.go +++ b/server/container.go @@ -5,8 +5,6 @@ package server import ( - "bytes" - "encoding/json" "errors" "fmt" "io" @@ -17,13 +15,10 @@ import ( "path/filepath" "strconv" "strings" - "time" "github.com/docker/docker/daemon" "github.com/docker/docker/engine" "github.com/docker/docker/pkg/graphdb" - "github.com/docker/docker/pkg/tailfile" - "github.com/docker/docker/utils" ) func (srv *Server) ContainerTop(job *engine.Job) engine.Status { @@ -353,123 +348,6 @@ func (srv *Server) ContainerDestroy(job *engine.Job) engine.Status { return engine.StatusOK } -func (srv *Server) ContainerLogs(job *engine.Job) engine.Status { - if len(job.Args) != 1 { - return job.Errorf("Usage: %s CONTAINER\n", job.Name) - } - - var ( - name = job.Args[0] - stdout = job.GetenvBool("stdout") - stderr = job.GetenvBool("stderr") - tail = job.Getenv("tail") - follow = job.GetenvBool("follow") - times = job.GetenvBool("timestamps") - lines = -1 - format string - ) - if !(stdout || stderr) { - return job.Errorf("You must choose at least one stream") - } - if times { - format = time.RFC3339Nano - } - if tail == "" { - tail = "all" - } - container := srv.daemon.Get(name) - if container == nil { - return job.Errorf("No such container: %s", name) - } - cLog, err := container.ReadLog("json") - if err != nil && os.IsNotExist(err) { - // Legacy logs - utils.Debugf("Old logs format") - if stdout { - cLog, err := container.ReadLog("stdout") - if err != nil { - utils.Errorf("Error reading logs (stdout): %s", err) - } else if _, err := io.Copy(job.Stdout, cLog); err != nil { - utils.Errorf("Error streaming logs (stdout): %s", err) - } - } - if stderr { - cLog, err := container.ReadLog("stderr") - if err != nil { - utils.Errorf("Error reading logs (stderr): %s", err) - } else if _, err := io.Copy(job.Stderr, cLog); err != nil { - utils.Errorf("Error streaming logs (stderr): %s", err) - } - } - } else if err != nil { - utils.Errorf("Error reading logs (json): %s", err) - } else { - if tail != "all" { - var err error - lines, err = strconv.Atoi(tail) - if err != nil { - utils.Errorf("Failed to parse tail %s, error: %v, show all logs", err) - lines = -1 - } - } - if lines != 0 { - if lines > 0 { - f := cLog.(*os.File) - ls, err := tailfile.TailFile(f, lines) - if err != nil { - return job.Error(err) - } - tmp := bytes.NewBuffer([]byte{}) - for _, l := range ls { - fmt.Fprintf(tmp, "%s\n", l) - } - cLog = tmp - } - dec := json.NewDecoder(cLog) - for { - l := &utils.JSONLog{} - - if err := dec.Decode(l); err == io.EOF { - break - } else if err != nil { - utils.Errorf("Error streaming logs: %s", err) - break - } - logLine := l.Log - if times { - logLine = fmt.Sprintf("%s %s", l.Created.Format(format), logLine) - } - if l.Stream == "stdout" && stdout { - fmt.Fprintf(job.Stdout, "%s", logLine) - } - if l.Stream == "stderr" && stderr { - fmt.Fprintf(job.Stderr, "%s", logLine) - } - } - } - } - if follow { - errors := make(chan error, 2) - if stdout { - stdoutPipe := container.StdoutLogPipe() - go func() { - errors <- utils.WriteLog(stdoutPipe, job.Stdout, format) - }() - } - if stderr { - stderrPipe := container.StderrLogPipe() - go func() { - errors <- utils.WriteLog(stderrPipe, job.Stderr, format) - }() - } - err := <-errors - if err != nil { - utils.Errorf("%s", err) - } - } - return engine.StatusOK -} - func (srv *Server) ContainerCopy(job *engine.Job) engine.Status { if len(job.Args) != 2 { return job.Errorf("Usage: %s CONTAINER RESOURCE\n", job.Name) diff --git a/server/init.go b/server/init.go index 74cd923612..87be38a572 100644 --- a/server/init.go +++ b/server/init.go @@ -95,7 +95,6 @@ func InitServer(job *engine.Job) engine.Status { "viz": srv.ImagesViz, "container_copy": srv.ContainerCopy, "log": srv.Log, - "logs": srv.ContainerLogs, "changes": srv.ContainerChanges, "top": srv.ContainerTop, "load": srv.ImageLoad,