func (s *Service) ProcessEntryFields(row map[string]interface{}) { var length C.size_t var cData *C.char for C.sd_journal_restart_data(s.Journal); C.sd_journal_enumerate_data(s.Journal, (*unsafe.Pointer)(unsafe.Pointer(&cData)), &length) > 0; { data := C.GoString(cData) parts := strings.SplitN(data, "=", 2) key := strings.ToLower(parts[0]) value := parts[1] switch key { // don't index bloat case "_cap_effective": case "_cmdline": case "_exe": case "_hostname": case "_systemd_cgroup": case "_systemd_slice": case "_transport": case "syslog_facility": case "syslog_identifier": continue default: row[strings.TrimPrefix(key, "_")] = value } } }
func (s *Service) ProcessEntryFields(row map[string]interface{}) { var length C.size_t var cData *C.char for C.sd_journal_restart_data(s.Journal); C.sd_journal_enumerate_data(s.Journal, (*unsafe.Pointer)(unsafe.Pointer(&cData)), &length) > 0; { data := C.GoString(cData) parts := strings.SplitN(data, "=", 2) key := strings.ToLower(parts[0]) value := parts[1] row[strings.TrimPrefix(key, "_")] = value } }
func (j *Journal) GetDataAll() (JournalEntry, error) { data := make(JournalEntry) var d unsafe.Pointer var l C.size_t var cboot_id C.sd_id128_t var csid = C.CString("123456789012345678901234567890123") defer C.free(unsafe.Pointer(csid)) var crealtime C.uint64_t var cmonotonic C.uint64_t var ccursor *C.char j.mu.Lock() // not in their own fields C.sd_journal_set_data_threshold(j.cjournal, 0) C.sd_journal_get_realtime_usec(j.cjournal, &crealtime) C.sd_journal_get_monotonic_usec(j.cjournal, &cmonotonic, &cboot_id) C.sd_id128_to_string(cboot_id, csid) C.sd_journal_get_cursor(j.cjournal, (**C.char)(&ccursor)) defer C.free(unsafe.Pointer(ccursor)) // reset to start the loop C.sd_journal_restart_data(j.cjournal) j.mu.Unlock() realtime := uint64(crealtime) monotonic := uint64(cmonotonic) cursor := C.GoString(ccursor) bootid := C.GoString(csid) data["__CURSOR"] = cursor data["__REALTIME_TIMESTAMP"] = realtime data["__MONOTONIC_TIMESTAMP"] = monotonic data["__BOOT_ID"] = bootid for { // retrieve new field j.mu.Lock() r := C.sd_journal_enumerate_data(j.cjournal, &d, &l) j.mu.Unlock() if r <= 0 { break } fieldData := C.GoBytes(d, C.int(l)) name, value := splitNameValue(fieldData) addToMap(data, name, value) } // Add catalog data as well if there is a MESSAGE_ID _, ok := data["MESSAGE_ID"] if ok { catalogEntry, err := j.GetCatalog() if err == nil { data["CATALOG_ENTRY"] = catalogEntry } } return data, nil }
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 }