func (s *journald) drainJournal(logWatcher *logger.LogWatcher, config logger.ReadConfig, j *C.sd_journal, oldCursor string) string { var msg, cursor *C.char var length C.size_t var stamp C.uint64_t var priority C.int // Walk the journal from here forward until we run out of new entries. drain: for { // Try not to send a given entry twice. if oldCursor != "" { ccursor := C.CString(oldCursor) defer C.free(unsafe.Pointer(ccursor)) for C.sd_journal_test_cursor(j, ccursor) > 0 { if C.sd_journal_next(j) <= 0 { break drain } } } // Read and send the logged message, if there is one to read. i := C.get_message(j, &msg, &length) if i != -C.ENOENT && i != -C.EADDRNOTAVAIL { // Read the entry's timestamp. if C.sd_journal_get_realtime_usec(j, &stamp) != 0 { break } // Set up the time and text of the entry. timestamp := time.Unix(int64(stamp)/1000000, (int64(stamp)%1000000)*1000) line := append(C.GoBytes(unsafe.Pointer(msg), C.int(length)), "\n"...) // Recover the stream name by mapping // from the journal priority back to // the stream that we would have // assigned that value. source := "" if C.get_priority(j, &priority) != 0 { source = "" } else if priority == C.int(journal.PriErr) { source = "stderr" } else if priority == C.int(journal.PriInfo) { source = "stdout" } // Send the log message. cid := s.vars["CONTAINER_ID_FULL"] logWatcher.Msg <- &logger.Message{ContainerID: cid, Line: line, Source: source, Timestamp: timestamp} } // If we're at the end of the journal, we're done (for now). if C.sd_journal_next(j) <= 0 { break } } retCursor := "" if C.sd_journal_get_cursor(j, &cursor) == 0 { retCursor = C.GoString(cursor) C.free(unsafe.Pointer(cursor)) } return retCursor }
func (s *journald) drainJournal(logWatcher *logger.LogWatcher, config logger.ReadConfig, j *C.sd_journal, oldCursor string) string { var msg, data, cursor *C.char var length C.size_t var stamp C.uint64_t var priority C.int // Walk the journal from here forward until we run out of new entries. drain: for { // Try not to send a given entry twice. if oldCursor != "" { ccursor := C.CString(oldCursor) defer C.free(unsafe.Pointer(ccursor)) for C.sd_journal_test_cursor(j, ccursor) > 0 { if C.sd_journal_next(j) <= 0 { break drain } } } // Read and send the logged message, if there is one to read. i := C.get_message(j, &msg, &length) if i != -C.ENOENT && i != -C.EADDRNOTAVAIL { // Read the entry's timestamp. if C.sd_journal_get_realtime_usec(j, &stamp) != 0 { break } // Set up the time and text of the entry. timestamp := time.Unix(int64(stamp)/1000000, (int64(stamp)%1000000)*1000) line := append(C.GoBytes(unsafe.Pointer(msg), C.int(length)), "\n"...) // Recover the stream name by mapping // from the journal priority back to // the stream that we would have // assigned that value. source := "" if C.get_priority(j, &priority) != 0 { source = "" } else if priority == C.int(journal.PriErr) { source = "stderr" } else if priority == C.int(journal.PriInfo) { source = "stdout" } // Retrieve the values of any variables we're adding to the journal. attrs := make(map[string]string) C.sd_journal_restart_data(j) for C.get_attribute_field(j, &data, &length) > C.int(0) { kv := strings.SplitN(C.GoStringN(data, C.int(length)), "=", 2) attrs[kv[0]] = kv[1] } if len(attrs) == 0 { attrs = nil } // Send the log message. logWatcher.Msg <- &logger.Message{ Line: line, Source: source, Timestamp: timestamp.In(time.UTC), Attrs: attrs, } } // If we're at the end of the journal, we're done (for now). if C.sd_journal_next(j) <= 0 { break } } retCursor := "" if C.sd_journal_get_cursor(j, &cursor) == 0 { retCursor = C.GoString(cursor) C.free(unsafe.Pointer(cursor)) } return retCursor }