Skip to content

Instantly share code, notes, and snippets.

@portante
Last active March 23, 2021 13:30
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save portante/ff7fb429c6f973aab377f7bb77b0ffdb to your computer and use it in GitHub Desktop.
Save portante/ff7fb429c6f973aab377f7bb77b0ffdb to your computer and use it in GitHub Desktop.
Simple C program to demonstrate how to properly "tail" journald, what journalctl -f does, while detecting journal file rotation to avoid keeping deleted files open (basically call sd_journal_get_fd() immediately after sd_journal_open()).
// cc -g2 example_journal_reader.c -lsystemd
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <sys/poll.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <systemd/sd-journal.h>
int main(int argc, char *argv[]) {
uint64_t prev_timestamp = 0;
int r;
sd_journal *j;
r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
if (r < 0) {
fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
return 1;
}
// Prime the journal internals to ensure sd_journal_wait() actually waits.
// NOTE: calling sd_journal_get_fd() here "primes the pump" for the
// sd_journal_wait() to work properly in the face of journal file rotation.
r = sd_journal_get_fd(j);
if (r < 0) {
fprintf(stderr, "Failed to prime journal fd state: %s\n", strerror(-r));
return 1;
}
// This program only emits new records from the time it opens the journal.
r = sd_journal_seek_tail(j);
if (r < 0) {
fprintf(stderr, "Failed to seek to tail of journal: %s\n", strerror(-r));
return 1;
}
// For some reason, fetching previous then next avoids getting an initial
// huge chunk of records. If one calls sd_journal_seek_tail() and then
// calls sd_journal_next() we receive the huge chunk.
r = sd_journal_previous(j);
if (r < 0) {
fprintf(stderr, "Failed to get previous journal entry: %s\n", strerror(-r));
return 1;
}
r = sd_journal_next(j);
while (r >= 0) {
if (r == 0) {
// We wait in a loop to catch spurious NOPs
do {
jr = sd_journal_wait(j, (uint64_t)-1);
if (jr < 0) {
fprintf(stderr, "Failed to wait for journal changes: %s\n", strerror(-jr));
return 1;
}
} while (jr == SD_JOURNAL_NOP);
r = sd_journal_next(j);
continue;
}
const char *d;
size_t l;
r = sd_journal_get_data(j, "MESSAGE", (const void **)&d, &l);
if (r < 0) {
fprintf(stderr, "Failed to read message field: %s\n", strerror(-r));
return 1;
}
struct timeval tv;
uint64_t curr_timestamp;
r = sd_journal_get_realtime_usec(j, &curr_timestamp);
if (r < 0) {
fprintf(stderr, "Failed to read timestamp: %s\n", strerror(-r));
return 1;
}
else {
if (prev_timestamp > curr_timestamp) {
fprintf(stderr, "Timestamp went backwards: %llu %llu\n", prev_timestamp, curr_timestamp);
return 1;
}
else if (prev_timestamp < curr_timestamp) {
prev_timestamp = curr_timestamp;
}
tv.tv_sec = curr_timestamp / 1000000;
tv.tv_usec = curr_timestamp % 1000000;
}
time_t nowtime;
struct tm *nowtm;
char tmbuf[64];
nowtime = tv.tv_sec;
nowtm = localtime(&nowtime);
strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S", nowtm);
printf("%s.%06ld %.*s\n", tmbuf, tv.tv_usec, (int) l, d);
fflush(stdout);
r = sd_journal_next(j);
}
// We only ever exit the above loop due to a failure calling
// sd_journal_next().
if (r < 0) {
fprintf(stderr, "Failed to get next journal entry: %s\n", strerror(-r));
return 1;
}
// Be kind ... close the journal via the API.
sd_journal_close(j);
return 0;
}
#!/usr/bin/env python
import random
import string
import logging
import logging.handlers
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
handler = logging.handlers.SysLogHandler(address = '/dev/log')
formatter = logging.Formatter('%(module)s.%(funcName)s: %(message)s')
handler.setFormatter(formatter)
log.addHandler(handler)
def load(size, chars=string.ascii_uppercase + string.digits):
seq = 0
while True:
msg = ''.join(random.choice(chars) for x in range(size))
log.info("%20d %s" % (seq, msg))
seq += 1
def hello():
log.debug('this is debug')
log.critical('this is critical')
if __name__ == '__main__':
#hello()
load(1024)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment