示例#1
0
static int journal_get_cursor (lua_State *L) {
	sd_journal *j = check_journal(L, 1);
	char *cursor;
	int err = sd_journal_get_cursor(j, &cursor);
	if (err != 0) return handle_error(L, -err);
	lua_pushstring(L, cursor);
	free(cursor);
	return 1;
}
示例#2
0
static void verify_contents(sd_journal *j, unsigned skip) {
        unsigned i;

        assert(j);

        i = 0;
        SD_JOURNAL_FOREACH(j) {
                const void *d;
                char *k, *c;
                size_t l;
                unsigned u;

                assert_se(sd_journal_get_cursor(j, &k) >= 0);
                printf("cursor: %s\n", k);
                free(k);

                assert_se(sd_journal_get_data(j, "MAGIC", &d, &l) >= 0);
                printf("\t%.*s\n", (int) l, (const char*) d);

                assert_se(sd_journal_get_data(j, "NUMBER", &d, &l) >= 0);
                assert_se(k = strndup(d, l));
                printf("\t%s\n", k);

                if (skip > 0) {
                        assert_se(safe_atou(k + 7, &u) >= 0);
                        assert_se(i == u);
                        i += skip;
                }

                free(k);

                assert_se(sd_journal_get_cursor(j, &c) >= 0);
                assert_se(sd_journal_test_cursor(j, c) > 0);
                free(c);
        }

        if (skip > 0)
                assert_se(i == N_ENTRIES);
}
示例#3
0
int main(int argc, char *argv[]) {
        JournalFile *one, *two, *three;
        char t[] = "/tmp/journal-stream-XXXXXX";
        unsigned i;
        _cleanup_journal_close_ sd_journal *j = NULL;
        char *z;
        const void *data;
        size_t l;

        log_set_max_level(LOG_DEBUG);

        assert_se(mkdtemp(t));
        assert_se(chdir(t) >= 0);

        assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0666, true, NULL, NULL, NULL, &one) == 0);
        assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0666, true, NULL, NULL, NULL, &two) == 0);
        assert_se(journal_file_open("three.journal", O_RDWR|O_CREAT, 0666, true, NULL, NULL, NULL, &three) == 0);

        for (i = 0; i < N_ENTRIES; i++) {
                char *p, *q;
                dual_timestamp ts;
                struct iovec iovec[2];

                dual_timestamp_get(&ts);

                assert_se(asprintf(&p, "NUMBER=%u", i) >= 0);
                iovec[0].iov_base = p;
                iovec[0].iov_len = strlen(p);

                assert_se(asprintf(&q, "MAGIC=%s", i % 5 == 0 ? "quux" : "waldo") >= 0);

                iovec[1].iov_base = q;
                iovec[1].iov_len = strlen(q);

                if (i % 10 == 0)
                        assert_se(journal_file_append_entry(three, &ts, iovec, 2, NULL, NULL, NULL) == 0);
                else {
                        if (i % 3 == 0)
                                assert_se(journal_file_append_entry(two, &ts, iovec, 2, NULL, NULL, NULL) == 0);

                        assert_se(journal_file_append_entry(one, &ts, iovec, 2, NULL, NULL, NULL) == 0);
                }

                free(p);
                free(q);
        }

        journal_file_close(one);
        journal_file_close(two);
        journal_file_close(three);

        assert_se(sd_journal_open_directory(&j, t, 0) >= 0);

        assert_se(sd_journal_add_match(j, "MAGIC=quux", 0) >= 0);
        SD_JOURNAL_FOREACH_BACKWARDS(j) {
                _cleanup_free_ char *c = NULL;

                assert_se(sd_journal_get_data(j, "NUMBER", &data, &l) >= 0);
                printf("\t%.*s\n", (int) l, (const char*) data);

                assert_se(sd_journal_get_cursor(j, &c) >= 0);
                assert_se(sd_journal_test_cursor(j, c) > 0);
        }

        SD_JOURNAL_FOREACH(j) {
                _cleanup_free_ char *c = NULL;

                assert_se(sd_journal_get_data(j, "NUMBER", &data, &l) >= 0);
                printf("\t%.*s\n", (int) l, (const char*) data);

                assert_se(sd_journal_get_cursor(j, &c) >= 0);
                assert_se(sd_journal_test_cursor(j, c) > 0);
        }

        sd_journal_flush_matches(j);

        verify_contents(j, 1);

        printf("NEXT TEST\n");
        assert_se(sd_journal_add_match(j, "MAGIC=quux", 0) >= 0);

        assert_se(z = journal_make_match_string(j));
        printf("resulting match expression is: %s\n", z);
        free(z);

        verify_contents(j, 5);

        printf("NEXT TEST\n");
        sd_journal_flush_matches(j);
        assert_se(sd_journal_add_match(j, "MAGIC=waldo", 0) >= 0);
        assert_se(sd_journal_add_match(j, "NUMBER=10", 0) >= 0);
        assert_se(sd_journal_add_match(j, "NUMBER=11", 0) >= 0);
        assert_se(sd_journal_add_match(j, "NUMBER=12", 0) >= 0);

        assert_se(z = journal_make_match_string(j));
        printf("resulting match expression is: %s\n", z);
        free(z);

        verify_contents(j, 0);

        assert_se(sd_journal_query_unique(j, "NUMBER") >= 0);
        SD_JOURNAL_FOREACH_UNIQUE(j, data, l)
                printf("%.*s\n", (int) l, (const char*) data);

        assert_se(rm_rf_dangerous(t, false, true, false) >= 0);

        return 0;
}
char *get_entry_string(){
    const void *data;
    json_t *message = json_object();
    size_t length;

    // journal meta information, prefixed by '__'
    char *cursor;
    uint64_t realtime_usec;
    uint64_t monotonic_usec;
    sd_id128_t boot_id;

    /* mapping from systemd- to GELF- field names */
    const char *fn_sd_host="_HOSTNAME", *fn_gelf_host="host";
    const char *fn_sd_msg="MESSAGE",    *fn_gelf_msg="short_message";
    const char /**fn_sd_time="__REALTIME_TIMESTAMP",*/ *fn_gelf_time="timestamp";
    const char *fn_sd_prio="PRIORITY",  *fn_gelf_prio="level";

    int rc = 0;

    //add version field necessary for GELF
    json_object_set_new(message, "version", json_string("1.1"));

    /* get data necessary for GELF*/

    rc = sd_journal_get_data(j, fn_sd_host, &data, &length);
    if (!rc){
        char *v = get_value(data, length);
	    assert(v);
        json_object_set_new(message, fn_gelf_host, json_string(v));
        free(v);
    }
    else{
        json_object_set_new(message, fn_gelf_host, json_string("not_available"));
    }
    rc = sd_journal_get_data(j, fn_sd_msg, &data, &length);
    if (!rc){
        char *v = get_value(data, length);
        assert(v);
        json_object_set_new(message, fn_gelf_msg, json_string(v));
        free(v);
    }
    else{
        json_object_set_new(message, fn_gelf_msg, json_string("not_available"));
    }
    rc = sd_journal_get_data(j, fn_sd_prio, &data, &length);
    if (!rc){
        char *v = get_value(data, length);
        assert(v);
        int prio = strtol(v, NULL, 10);
        if (prio<0) prio = 0;
        if (prio>7) prio = 7;
        //TODO: log meldung absetzen
        json_object_set_new(message, fn_gelf_prio, json_integer(prio));
        free(v);
    }
    else{
        json_object_set_new(message, fn_gelf_prio, json_string("not_available"));
    }

    // get systemd journal meta fields cursor, realtime- and monotonic timestamp
    // __REALTIME_TIMESTAMP corresponds to  GELF necessary timestamp
    const char *meta_prefixes[] = {"___CURSOR", fn_gelf_time , "___MONOTONIC_TIMESTAMP" };
    sd_journal_get_cursor( j, &cursor );    // needs to be free'd afterwards
    json_object_set_new(message, meta_prefixes[0], json_string(cursor));
    free(cursor);

    sd_journal_get_realtime_usec( j, &realtime_usec );
    json_object_set_new(message, meta_prefixes[1], json_integer(realtime_usec));

    sd_journal_get_monotonic_usec( j, &monotonic_usec, &boot_id);
    json_object_set_new(message, meta_prefixes[2], json_integer(monotonic_usec));

    /* get all remaining fields */
    // (PRIORITY, _HOSTNAME, and MESSAGE are read again)

    // format of prefixes: additional '_' for additional fields in GELF
    // format of retrieved arguments: data="FIELD_NAME=field_value" length=
    SD_JOURNAL_FOREACH_DATA(j, data, length){
        char *v = get_value(data, length);
        assert(v);
        char *k = get_key(data);
        assert(k);
        json_object_set_new(message, k, json_string(v));
        free(v);
        free(k);
    }
示例#5
0
/**
 * Write up to size bytes to buf. Return negative on error, and number of
 * bytes written otherwise. The last case is a kind of an error too.
 */
static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
    int r;
    size_t pos = 0;

    assert(size <= SSIZE_MAX);

    while (true) {

        switch(u->entry_state) {
        case ENTRY_CURSOR: {
            free(u->current_cursor);
            u->current_cursor = NULL;

            r = sd_journal_get_cursor(u->journal, &u->current_cursor);
            if (r < 0)
                return log_error_errno(r, "Failed to get cursor: %m");

            r = snprintf(buf + pos, size - pos,
                         "__CURSOR=%s\n", u->current_cursor);
            if (pos + r > size)
                /* not enough space */
                return pos;

            u->entry_state ++;

            if (pos + r == size) {
                /* exactly one character short, but we don't need it */
                buf[size - 1] = '\n';
                return size;
            }

            pos += r;
            }       /* fall through */

        case ENTRY_REALTIME: {
            usec_t realtime;

            r = sd_journal_get_realtime_usec(u->journal, &realtime);
            if (r < 0)
                return log_error_errno(r, "Failed to get realtime timestamp: %m");

            r = snprintf(buf + pos, size - pos,
                         "__REALTIME_TIMESTAMP="USEC_FMT"\n", realtime);
            if (r + pos > size)
                /* not enough space */
                return pos;

            u->entry_state ++;

            if (r + pos == size) {
                /* exactly one character short, but we don't need it */
                buf[size - 1] = '\n';
                return size;
            }

            pos += r;
            }       /* fall through */

        case ENTRY_MONOTONIC: {
            usec_t monotonic;
            sd_id128_t boot_id;

            r = sd_journal_get_monotonic_usec(u->journal, &monotonic, &boot_id);
            if (r < 0)
                return log_error_errno(r, "Failed to get monotonic timestamp: %m");

            r = snprintf(buf + pos, size - pos,
                         "__MONOTONIC_TIMESTAMP="USEC_FMT"\n", monotonic);
            if (r + pos > size)
                /* not enough space */
                return pos;

            u->entry_state ++;

            if (r + pos == size) {
                /* exactly one character short, but we don't need it */
                buf[size - 1] = '\n';
                return size;
            }

            pos += r;
            }       /* fall through */

        case ENTRY_BOOT_ID: {
            sd_id128_t boot_id;
            char sid[33];

            r = sd_journal_get_monotonic_usec(u->journal, NULL, &boot_id);
            if (r < 0)
                return log_error_errno(r, "Failed to get monotonic timestamp: %m");

            r = snprintf(buf + pos, size - pos,
                         "_BOOT_ID=%s\n", sd_id128_to_string(boot_id, sid));
            if (r + pos > size)
                /* not enough space */
                return pos;

            u->entry_state ++;

            if (r + pos == size) {
                /* exactly one character short, but we don't need it */
                buf[size - 1] = '\n';
                return size;
            }

            pos += r;
            }       /* fall through */

        case ENTRY_NEW_FIELD: {
            u->field_pos = 0;

            r = sd_journal_enumerate_data(u->journal,
                                          &u->field_data,
                                          &u->field_length);
            if (r < 0)
                return log_error_errno(r, "Failed to move to next field in entry: %m");
            else if (r == 0) {
                u->entry_state = ENTRY_OUTRO;
                continue;
            }

            if (!utf8_is_printable_newline(u->field_data,
                                           u->field_length, false)) {
                u->entry_state = ENTRY_BINARY_FIELD_START;
                continue;
            }

            u->entry_state ++;
            }       /* fall through */

        case ENTRY_TEXT_FIELD:
        case ENTRY_BINARY_FIELD: {
            bool done;
            size_t tocopy;

            done = size - pos > u->field_length - u->field_pos;
            if (done)
                tocopy = u->field_length - u->field_pos;
            else
                tocopy = size - pos;

            memcpy(buf + pos,
                   (char*) u->field_data + u->field_pos,
                   tocopy);

            if (done) {
                buf[pos + tocopy] = '\n';
                pos += tocopy + 1;
                u->entry_state = ENTRY_NEW_FIELD;
                continue;
            } else {
                u->field_pos += tocopy;
                return size;
            }
        }

        case ENTRY_BINARY_FIELD_START: {
            const char *c;
            size_t len;

            c = memchr(u->field_data, '=', u->field_length);
            if (!c || c == u->field_data) {
                log_error("Invalid field.");
                return -EINVAL;
            }

            len = c - (const char*)u->field_data;

            /* need space for label + '\n' */
            if (size - pos < len + 1)
                return pos;

            memcpy(buf + pos, u->field_data, len);
            buf[pos + len] = '\n';
            pos += len + 1;

            u->field_pos = len + 1;
            u->entry_state ++;
            }       /* fall through */

        case ENTRY_BINARY_FIELD_SIZE: {
            uint64_t le64;

            /* need space for uint64_t */
            if (size - pos < 8)
                return pos;

            le64 = htole64(u->field_length - u->field_pos);
            memcpy(buf + pos, &le64, 8);
            pos += 8;

            u->entry_state ++;
            continue;
        }

        case ENTRY_OUTRO:
            /* need space for '\n' */
            if (size - pos < 1)
                return pos;

            buf[pos++] = '\n';
            u->entry_state ++;
            u->entries_sent ++;

            return pos;

        default:
            assert_not_reached("WTF?");
        }
    }
    assert_not_reached("WTF?");
}
示例#6
0
文件: systemd.c 项目: Aconex/pcp
void systemd_refresh(void)
{
    /* Absorb any changes such as inotify() messages. */
    (void) sd_journal_process(journald_context);
    (void) sd_journal_process(journald_context_seeky);

    while (1) {
        char *cursor = NULL;
        char *timestamp_str = NULL;
        struct timeval timestamp;

        int rc = sd_journal_next(journald_context);

        if (rc == 0) /* No recent entries. */
            break;

        if (rc < 0) {
            __pmNotifyErr(LOG_ERR, "sd_journal_next failure: %s", strerror(-rc));
            break;
        }

        /* NB: we enqueue the journal cursor string, rather than the
           actual journal records. */
        rc = sd_journal_get_cursor(journald_context, &cursor);
        if (rc < 0) {
            __pmNotifyErr(LOG_ERR, "sd_journal_get_cursor failure: %s",
                          strerror(-rc));
            break;
        }

        /* Extract a timestamp from the journald event fields. */
        timestamp_str = my_sd_journal_get_data(journald_context,
                                               "_SOURCE_REALTIME_TIMESTAMP");
        if (timestamp_str == NULL)
            timestamp_str = my_sd_journal_get_data(journald_context,
                                                   "__REALTIME_TIMESTAMP");
        if (timestamp_str == NULL)
            rc = -ENOMEM;
        else {
            const char* curse;
            unsigned long long epoch_us;
            /* defined in systemd.journal-fields(7) as
               FIELD_NAME=NNNN, where NNNN is decimal us since epoch. */
            curse = strchr (timestamp_str, '=');
            if (curse == NULL)
                rc = -EINVAL;
            else {
                curse ++;
                epoch_us = strtoull (curse, NULL, 10);
                timestamp.tv_sec  = epoch_us / 1000000;
                timestamp.tv_usec = epoch_us % 1000000;
            }
            free (timestamp_str);
        }
        /* Improvise. */
        if (rc < 0)
            gettimeofday (& timestamp, NULL);

        /* Enqueue it to fresh visitors. */
        rc = pmdaEventQueueAppend(queue_entries,
                                  cursor, strlen(cursor)+1 /* \0 */, &timestamp);
        free(cursor); /* Already copied. */
        if (rc < 0) {
            __pmNotifyErr(LOG_ERR, "pmdaEventQueueAppend failure: %s", pmErrStr(rc));
            break;
        }
    }
}