Browse Source

Merge pull request #21309 from nalind/journal-error-reporting

Improve error reporting when following journals
David Calavera 9 years ago
parent
commit
0dac544448
1 changed files with 29 additions and 12 deletions
  1. 29 12
      daemon/logger/journald/read.go

+ 29 - 12
daemon/logger/journald/read.go

@@ -63,11 +63,11 @@ package journald
 //		fds[0].events = POLLHUP;
 //		fds[1].fd = sd_journal_get_fd(j);
 //		if (fds[1].fd < 0) {
-//			return -1;
+//			return fds[1].fd;
 //		}
 //		jevents = sd_journal_get_events(j);
 //		if (jevents < 0) {
-//			return -1;
+//			return jevents;
 //		}
 //		fds[1].events = jevents;
 //		sd_journal_get_timeout(j, &when);
@@ -81,7 +81,7 @@ package journald
 //		i = poll(fds, 2, timeout);
 //		if ((i == -1) && (errno != EINTR)) {
 //			/* An unexpected error. */
-//			return -1;
+//			return (errno != 0) ? -errno : -EINTR;
 //		}
 //		if (fds[0].revents & POLLHUP) {
 //			/* The close notification pipe was closed. */
@@ -101,6 +101,7 @@ import (
 	"time"
 	"unsafe"
 
+	"github.com/Sirupsen/logrus"
 	"github.com/coreos/go-systemd/journal"
 	"github.com/docker/docker/daemon/logger"
 )
@@ -177,9 +178,18 @@ func (s *journald) followJournal(logWatcher *logger.LogWatcher, config logger.Re
 	s.readers.readers[logWatcher] = logWatcher
 	s.readers.mu.Unlock()
 	go func() {
-		// Keep copying journal data out until we're notified to stop.
-		for C.wait_for_data_or_close(j, pfd[0]) == 1 {
+		// Keep copying journal data out until we're notified to stop
+		// or we hit an error.
+		status := C.wait_for_data_or_close(j, pfd[0])
+		for status == 1 {
 			cursor = s.drainJournal(logWatcher, config, j, cursor)
+			status = C.wait_for_data_or_close(j, pfd[0])
+		}
+		if status < 0 {
+			cerrstr := C.strerror(C.int(-status))
+			errstr := C.GoString(cerrstr)
+			fmtstr := "error %q while attempting to follow journal for container %q"
+			logrus.Errorf(fmtstr, errstr, s.vars["CONTAINER_ID_FULL"])
 		}
 		// Clean up.
 		C.close(pfd[0])
@@ -293,14 +303,21 @@ func (s *journald) readLogs(logWatcher *logger.LogWatcher, config logger.ReadCon
 	}
 	cursor = s.drainJournal(logWatcher, config, j, "")
 	if config.Follow {
-		// Create a pipe that we can poll at the same time as the journald descriptor.
-		if C.pipe(&pipes[0]) == C.int(-1) {
-			logWatcher.Err <- fmt.Errorf("error opening journald close notification pipe")
+		// Allocate a descriptor for following the journal, if we'll
+		// need one.  Do it here so that we can report if it fails.
+		if fd := C.sd_journal_get_fd(j); fd < C.int(0) {
+			logWatcher.Err <- fmt.Errorf("error opening journald follow descriptor: %q", C.GoString(C.strerror(-fd)))
 		} else {
-			s.followJournal(logWatcher, config, j, pipes, cursor)
-			// Let followJournal handle freeing the journal context
-			// object and closing the channel.
-			following = true
+			// Create a pipe that we can poll at the same time as
+			// the journald descriptor.
+			if C.pipe(&pipes[0]) == C.int(-1) {
+				logWatcher.Err <- fmt.Errorf("error opening journald close notification pipe")
+			} else {
+				s.followJournal(logWatcher, config, j, pipes, cursor)
+				// Let followJournal handle freeing the journal context
+				// object and closing the channel.
+				following = true
+			}
 		}
 	}
 	return