diff options
Diffstat (limited to 'libpod/container_log_linux.go')
| -rw-r--r-- | libpod/container_log_linux.go | 80 | 
1 files changed, 73 insertions, 7 deletions
| diff --git a/libpod/container_log_linux.go b/libpod/container_log_linux.go index d895171cf..5792633b0 100644 --- a/libpod/container_log_linux.go +++ b/libpod/container_log_linux.go @@ -8,11 +8,12 @@ import (  	"fmt"  	"io"  	"math" -	"strings"  	"time" -	"github.com/containers/podman/v2/libpod/logs" +	"github.com/containers/podman/v3/libpod/define" +	"github.com/containers/podman/v3/libpod/logs"  	journal "github.com/coreos/go-systemd/v22/sdjournal" +	"github.com/hpcloud/tail/watch"  	"github.com/pkg/errors"  	"github.com/sirupsen/logrus"  ) @@ -34,10 +35,16 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption  	var config journal.JournalReaderConfig  	if options.Tail < 0 {  		config.NumFromTail = 0 +	} else if options.Tail == 0 { +		config.NumFromTail = math.MaxUint64  	} else {  		config.NumFromTail = uint64(options.Tail)  	} -	config.Formatter = journalFormatter +	if options.Multi { +		config.Formatter = journalFormatterWithID +	} else { +		config.Formatter = journalFormatter +	}  	defaultTime := time.Time{}  	if options.Since != defaultTime {  		// coreos/go-systemd/sdjournal doesn't correctly handle requests for data in the future @@ -45,7 +52,7 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption  		if time.Now().Before(options.Since) {  			return nil  		} -		config.Since = time.Since(options.Since) +		config.Since = -time.Since(options.Since)  	}  	config.Matches = append(config.Matches, journal.Match{  		Field: "CONTAINER_ID_FULL", @@ -63,8 +70,12 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption  	if options.Tail == math.MaxInt64 {  		r.Rewind()  	} +	state, err := c.State() +	if err != nil { +		return err +	} -	if options.Follow { +	if options.Follow && state == define.ContainerStateRunning {  		go func() {  			done := make(chan bool)  			until := make(chan time.Time) @@ -76,6 +87,21 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption  					// nothing to do anymore  				}  			}() +			go func() { +				for { +					state, err := c.State() +					if err != nil { +						until <- time.Time{} +						logrus.Error(err) +						break +					} +					time.Sleep(watch.POLL_DURATION) +					if state != define.ContainerStateRunning && state != define.ContainerStatePaused { +						until <- time.Time{} +						break +					} +				} +			}()  			follower := FollowBuffer{logChannel}  			err := r.Follow(until, follower)  			if err != nil { @@ -114,7 +140,44 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption  	return nil  } +func journalFormatterWithID(entry *journal.JournalEntry) (string, error) { +	output, err := formatterPrefix(entry) +	if err != nil { +		return "", err +	} + +	id, ok := entry.Fields["CONTAINER_ID_FULL"] +	if !ok { +		return "", fmt.Errorf("no CONTAINER_ID_FULL field present in journal entry") +	} +	if len(id) > 12 { +		id = id[:12] +	} +	output += fmt.Sprintf("%s ", id) +	// Append message +	msg, err := formatterMessage(entry) +	if err != nil { +		return "", err +	} +	output += msg +	return output, nil +} +  func journalFormatter(entry *journal.JournalEntry) (string, error) { +	output, err := formatterPrefix(entry) +	if err != nil { +		return "", err +	} +	// Append message +	msg, err := formatterMessage(entry) +	if err != nil { +		return "", err +	} +	output += msg +	return output, nil +} + +func formatterPrefix(entry *journal.JournalEntry) (string, error) {  	usec := entry.RealtimeTimestamp  	tsString := time.Unix(0, int64(usec)*int64(time.Microsecond)).Format(logs.LogTimeFormat)  	output := fmt.Sprintf("%s ", tsString) @@ -137,13 +200,16 @@ func journalFormatter(entry *journal.JournalEntry) (string, error) {  		output += fmt.Sprintf("%s ", logs.FullLogType)  	} +	return output, nil +} + +func formatterMessage(entry *journal.JournalEntry) (string, error) {  	// Finally, append the message  	msg, ok := entry.Fields["MESSAGE"]  	if !ok {  		return "", fmt.Errorf("no MESSAGE field present in journal entry")  	} -	output += strings.TrimSpace(msg) -	return output, nil +	return msg, nil  }  type FollowBuffer struct { | 
