github.com/mheon/docker@v0.11.2-0.20150922122814-44f47903a831/daemon/logs.go (about) 1 package daemon 2 3 import ( 4 "fmt" 5 "io" 6 "strconv" 7 "time" 8 9 "github.com/Sirupsen/logrus" 10 "github.com/docker/docker/daemon/logger" 11 "github.com/docker/docker/pkg/stdcopy" 12 ) 13 14 // ContainerLogsConfig holds configs for logging operations. Exists 15 // for users of the daemon to to pass it a logging configuration. 16 type ContainerLogsConfig struct { 17 // if true stream log output 18 Follow bool 19 // if true include timestamps for each line of log output 20 Timestamps bool 21 // return that many lines of log output from the end 22 Tail string 23 // filter logs by returning on those entries after this time 24 Since time.Time 25 // whether or not to show stdout and stderr as well as log entries. 26 UseStdout, UseStderr bool 27 OutStream io.Writer 28 Stop <-chan bool 29 } 30 31 // ContainerLogs hooks up a container's stdout and stderr streams 32 // configured with the given struct. 33 func (daemon *Daemon) ContainerLogs(container *Container, config *ContainerLogsConfig) error { 34 if !(config.UseStdout || config.UseStderr) { 35 return fmt.Errorf("You must choose at least one stream") 36 } 37 38 outStream := config.OutStream 39 errStream := outStream 40 if !container.Config.Tty { 41 errStream = stdcopy.NewStdWriter(outStream, stdcopy.Stderr) 42 outStream = stdcopy.NewStdWriter(outStream, stdcopy.Stdout) 43 } 44 config.OutStream = outStream 45 46 cLog, err := container.getLogger() 47 if err != nil { 48 return err 49 } 50 logReader, ok := cLog.(logger.LogReader) 51 if !ok { 52 return logger.ErrReadLogsNotSupported 53 } 54 55 follow := config.Follow && container.IsRunning() 56 tailLines, err := strconv.Atoi(config.Tail) 57 if err != nil { 58 tailLines = -1 59 } 60 61 logrus.Debug("logs: begin stream") 62 readConfig := logger.ReadConfig{ 63 Since: config.Since, 64 Tail: tailLines, 65 Follow: follow, 66 } 67 logs := logReader.ReadLogs(readConfig) 68 69 for { 70 select { 71 case err := <-logs.Err: 72 logrus.Errorf("Error streaming logs: %v", err) 73 return nil 74 case <-config.Stop: 75 logs.Close() 76 return nil 77 case msg, ok := <-logs.Msg: 78 if !ok { 79 logrus.Debugf("logs: end stream") 80 return nil 81 } 82 logLine := msg.Line 83 if config.Timestamps { 84 logLine = append([]byte(msg.Timestamp.Format(logger.TimeFormat)+" "), logLine...) 85 } 86 if msg.Source == "stdout" && config.UseStdout { 87 outStream.Write(logLine) 88 } 89 if msg.Source == "stderr" && config.UseStderr { 90 errStream.Write(logLine) 91 } 92 } 93 } 94 }