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:
parent
fdad41f5b9
commit
066330fc96
4 changed files with 136 additions and 123 deletions
|
@ -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
133
daemon/logs.go
Normal 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
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue