Exemple #1
0
static int journal_get_monotonic_usec (lua_State *L) {
	sd_journal *j = check_journal(L, 1);
	uint64_t usec;
	sd_id128_t *boot_id = lua_newuserdata(L, sizeof(sd_id128_t));
	int err = sd_journal_get_monotonic_usec(j, &usec, boot_id);
	if (err != 0) return handle_error(L, -err);
	lua_pushuint64(L, usec);
	lua_insert(L, 2); /* put below boot_id */
	luaL_setmetatable(L, ID128_METATABLE);
	return 2;
}
Exemple #2
0
static int output_timestamp_monotonic(FILE *f, sd_journal *j, const char *monotonic) {
        sd_id128_t boot_id;
        uint64_t t;
        int r;

        assert(f);
        assert(j);

        r = -ENXIO;
        if (monotonic)
                r = safe_atou64(monotonic, &t);
        if (r < 0)
                r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
        if (r < 0)
                return log_error_errno(r, "Failed to get monotonic timestamp: %m");

        fprintf(f, "[%5"PRI_USEC".%06"PRI_USEC"]", t / USEC_PER_SEC, t % USEC_PER_SEC);
        return 1 + 5 + 1 + 6 + 1;
}
/**
 * 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?");
}
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);
    }
Exemple #5
0
int main(int argc, char *argv[]) {
        int r;
        sd_journal *j = NULL;
        unsigned line = 0;
        bool need_seek = false;
        sd_id128_t previous_boot_id;
        bool previous_boot_id_valid = false;
        bool have_pager;

        log_parse_environment();
        log_open();

        r = parse_argv(argc, argv);
        if (r <= 0)
                goto finish;

        if (arg_new_id128) {
                r = generate_new_id128();
                goto finish;
        }

#ifdef HAVE_ACL
        if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0)
                log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this message off.");
#endif

        if (arg_directory)
                r = sd_journal_open_directory(&j, arg_directory, 0);
        else
                r = sd_journal_open(&j, arg_local ? SD_JOURNAL_LOCAL_ONLY : 0);

        if (r < 0) {
                log_error("Failed to open journal: %s", strerror(-r));
                goto finish;
        }

        if (arg_print_header) {
                journal_print_header(j);
                r = 0;
                goto finish;
        }

        r = add_this_boot(j);
        if (r < 0)
                goto finish;

        r = add_matches(j, argv + optind);
        if (r < 0)
                goto finish;

        if (!arg_quiet) {
                usec_t start, end;
                char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];

                r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
                if (r < 0) {
                        log_error("Failed to get cutoff: %s", strerror(-r));
                        goto finish;
                }

                if (r > 0) {
                        if (arg_follow)
                                printf("Logs begin at %s.\n", format_timestamp(start_buf, sizeof(start_buf), start));
                        else
                                printf("Logs begin at %s, end at %s.\n",
                                       format_timestamp(start_buf, sizeof(start_buf), start),
                                       format_timestamp(end_buf, sizeof(end_buf), end));
                }
        }

        if (arg_lines >= 0) {
                r = sd_journal_seek_tail(j);
                if (r < 0) {
                        log_error("Failed to seek to tail: %s", strerror(-r));
                        goto finish;
                }

                r = sd_journal_previous_skip(j, arg_lines);
        } else {
                r = sd_journal_seek_head(j);
                if (r < 0) {
                        log_error("Failed to seek to head: %s", strerror(-r));
                        goto finish;
                }

                r = sd_journal_next(j);
        }

        if (r < 0) {
                log_error("Failed to iterate through journal: %s", strerror(-r));
                goto finish;
        }

        have_pager = !arg_no_pager && !arg_follow;
        if (have_pager) {
                columns();
                pager_open();
        }

        if (arg_output == OUTPUT_JSON) {
                fputc('[', stdout);
                fflush(stdout);
        }

        for (;;) {
                for (;;) {
                        sd_id128_t boot_id;
                        int flags = (arg_show_all*OUTPUT_SHOW_ALL |
                                     have_pager*OUTPUT_FULL_WIDTH);

                        if (need_seek) {
                                r = sd_journal_next(j);
                                if (r < 0) {
                                        log_error("Failed to iterate through journal: %s", strerror(-r));
                                        goto finish;
                                }
                        }

                        if (r == 0)
                                break;

                        r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
                        if (r >= 0) {
                                if (previous_boot_id_valid &&
                                    !sd_id128_equal(boot_id, previous_boot_id))
                                        printf(ANSI_HIGHLIGHT_ON "----- Reboot -----" ANSI_HIGHLIGHT_OFF "\n");

                                previous_boot_id = boot_id;
                                previous_boot_id_valid = true;
                        }

                        line ++;

                        r = output_journal(j, arg_output, line, 0, flags);
                        if (r < 0)
                                goto finish;

                        need_seek = true;
                }

                if (!arg_follow)
                        break;

                r = sd_journal_wait(j, (uint64_t) -1);
                if (r < 0) {
                        log_error("Couldn't wait for log event: %s", strerror(-r));
                        goto finish;
                }
        }

        if (arg_output == OUTPUT_JSON)
                fputs("\n]\n", stdout);

finish:
        if (j)
                sd_journal_close(j);

        pager_close();

        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}