Esempio n. 1
0
// GetRealtimeUsec gets the realtime (wallclock) timestamp of the current
// journal entry.
func (j *Journal) GetRealtimeUsec() (uint64, error) {
	var usec C.uint64_t

	sd_journal_get_realtime_usec, err := j.getFunction("sd_journal_get_realtime_usec")
	if err != nil {
		return 0, err
	}

	j.mu.Lock()
	r := C.my_sd_journal_get_realtime_usec(sd_journal_get_realtime_usec, j.cjournal, &usec)
	j.mu.Unlock()

	if r < 0 {
		return 0, fmt.Errorf("error getting timestamp for entry: %d", syscall.Errno(-r))
	}

	return uint64(usec), nil
}
Esempio n. 2
0
// GetEntry returns a full representation of a journal entry with
// all key-value pairs of data as well as address fields (cursor, realtime
// timestamp and monotonic timestamp)
func (j *Journal) GetEntry() (*JournalEntry, error) {
	sd_journal_get_realtime_usec, err := getFunction("sd_journal_get_realtime_usec")
	if err != nil {
		return nil, err
	}

	sd_journal_get_monotonic_usec, err := getFunction("sd_journal_get_monotonic_usec")
	if err != nil {
		return nil, err
	}

	sd_journal_get_cursor, err := getFunction("sd_journal_get_cursor")
	if err != nil {
		return nil, err
	}

	sd_journal_restart_data, err := getFunction("sd_journal_restart_data")
	if err != nil {
		return nil, err
	}

	sd_journal_enumerate_data, err := getFunction("sd_journal_enumerate_data")
	if err != nil {
		return nil, err
	}

	j.mu.Lock()
	defer j.mu.Unlock()

	var r C.int
	entry := &JournalEntry{Fields: make(map[string]string)}

	var realtimeUsec C.uint64_t
	r = C.my_sd_journal_get_realtime_usec(sd_journal_get_realtime_usec, j.cjournal, &realtimeUsec)
	if r < 0 {
		return nil, fmt.Errorf("failed to get realtime timestamp: %d", syscall.Errno(-r))
	}

	entry.RealtimeTimestamp = uint64(realtimeUsec)

	var monotonicUsec C.uint64_t
	var boot_id C.sd_id128_t

	r = C.my_sd_journal_get_monotonic_usec(sd_journal_get_monotonic_usec, j.cjournal, &monotonicUsec, &boot_id)
	if r < 0 {
		return nil, fmt.Errorf("failed to get monotonic timestamp: %d", syscall.Errno(-r))
	}

	entry.MonotonicTimestamp = uint64(monotonicUsec)

	var c *C.char
	// since the pointer is mutated by sd_journal_get_cursor, need to wait
	// until after the call to free the memory
	r = C.my_sd_journal_get_cursor(sd_journal_get_cursor, j.cjournal, &c)
	defer C.free(unsafe.Pointer(c))
	if r < 0 {
		return nil, fmt.Errorf("failed to get cursor: %d", syscall.Errno(-r))
	}

	entry.Cursor = C.GoString(c)

	// Implements the JOURNAL_FOREACH_DATA_RETVAL macro from journal-internal.h
	var d unsafe.Pointer
	var l C.size_t
	C.my_sd_journal_restart_data(sd_journal_restart_data, j.cjournal)
	for {
		r = C.my_sd_journal_enumerate_data(sd_journal_enumerate_data, j.cjournal, &d, &l)
		if r == 0 {
			break
		}

		if r < 0 {
			return nil, fmt.Errorf("failed to read message field: %d", syscall.Errno(-r))
		}

		msg := C.GoStringN((*C.char)(d), C.int(l))
		kv := strings.SplitN(msg, "=", 2)
		if len(kv) < 2 {
			return nil, fmt.Errorf("failed to parse field")
		}

		entry.Fields[kv[0]] = kv[1]
	}

	return entry, nil
}