libpod/Container.readFromJournal(): don't skip the first entry

When reading log entries from the journal, don't skip past the first
matching entry after we've positioned the cursor at it.

Make the first blank-line entry that we logged so that the container
would always have at least one log entry for us to find (until it gets
vacuumed out, at least) a fake history entry, so that `logs` doesn't
pass it on for display.

CI already has tests that exercise journal-based logging, so
[NO TESTS NEEDED]

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
This commit is contained in:
Nalin Dahyabhai
2021-08-18 12:13:03 -04:00
parent 6b06e9b77c
commit 1411fa5f23

View File

@ -38,6 +38,8 @@ func (c *Container) initializeJournal(ctx context.Context) error {
m["SYSLOG_IDENTIFIER"] = "podman" m["SYSLOG_IDENTIFIER"] = "podman"
m["PODMAN_ID"] = c.ID() m["PODMAN_ID"] = c.ID()
m["CONTAINER_ID_FULL"] = c.ID() m["CONTAINER_ID_FULL"] = c.ID()
history := events.History
m["PODMAN_EVENT"] = history.String()
return journal.Send("", journal.PriInfo, m) return journal.Send("", journal.PriInfo, m)
} }
@ -89,10 +91,10 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption
var cursorError error var cursorError error
for i := 1; i <= 3; i++ { for i := 1; i <= 3; i++ {
cursor, cursorError = journal.GetCursor() cursor, cursorError = journal.GetCursor()
if err != nil { if cursorError != nil {
time.Sleep(time.Duration(i*100) * time.Millisecond)
continue continue
} }
time.Sleep(time.Duration(i*100) * time.Millisecond)
break break
} }
if cursorError != nil { if cursorError != nil {
@ -116,6 +118,7 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption
tailQueue := []*logs.LogLine{} // needed for options.Tail tailQueue := []*logs.LogLine{} // needed for options.Tail
doTail := options.Tail > 0 doTail := options.Tail > 0
lastReadCursor := ""
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():
@ -125,18 +128,25 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption
// Fallthrough // Fallthrough
} }
if lastReadCursor != "" {
// Advance to next entry if we read this one.
if _, err := journal.Next(); err != nil { if _, err := journal.Next(); err != nil {
logrus.Errorf("Failed to move journal cursor to next entry: %v", err) logrus.Errorf("Failed to move journal cursor to next entry: %v", err)
return return
} }
latestCursor, err := journal.GetCursor() }
// Fetch the location of this entry, presumably either
// the one that follows the last one we read, or that
// same last one, if there is no next entry (yet).
cursor, err = journal.GetCursor()
if err != nil { if err != nil {
logrus.Errorf("Failed to get journal cursor: %v", err) logrus.Errorf("Failed to get journal cursor: %v", err)
return return
} }
// Hit the end of the journal. // Hit the end of the journal (so far?).
if cursor == latestCursor { if cursor == lastReadCursor {
if doTail { if doTail {
// Flush *once* we hit the end of the journal. // Flush *once* we hit the end of the journal.
startIndex := int64(len(tailQueue)-1) - options.Tail startIndex := int64(len(tailQueue)-1) - options.Tail
@ -157,8 +167,9 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption
journal.Wait(sdjournal.IndefiniteWait) journal.Wait(sdjournal.IndefiniteWait)
continue continue
} }
cursor = latestCursor lastReadCursor = cursor
// Read the journal entry.
entry, err := journal.GetEntry() entry, err := journal.GetEntry()
if err != nil { if err != nil {
logrus.Errorf("Failed to get journal entry: %v", err) logrus.Errorf("Failed to get journal entry: %v", err)