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 <solomon@docker.com> (github: shykes)
This commit is contained in:
Solomon Hykes 2014-07-31 21:03:21 +00:00 committed by Tibor Vass
parent fdad41f5b9
commit 066330fc96
4 changed files with 136 additions and 123 deletions

View file

@ -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
}

133
daemon/logs.go Normal file
View file

@ -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
}

View file

@ -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)

View file

@ -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,