journalctl: rework JSON output mode

This splits the JSON output mode into different modes: json and
json-pretty. The former printing one entry per line, the latter showing
JSON objects nicely indented and in multiple lines to make it easier to
read for humans.
This commit is contained in:
Lennart Poettering 2012-09-05 15:25:32 -07:00
parent 04bc4a3f47
commit a6e87e90ed
7 changed files with 59 additions and 55 deletions

6
TODO
View File

@ -49,6 +49,8 @@ Bugfixes:
Features:
* log fewer journal internal messages to the kernel kmsg
* move keymaps to /usr/lib/... rather than /usr/lib/udev/...
* journald: check whether it is OK if the client can still modify delivered journal entries
@ -72,7 +74,7 @@ Features:
* securityfs: don't mount in container
* slave/shared remount root fs in container
* slave/shared remount root fs in container might clash with CAP_SYS_MOUNTS
* ability to pass fds into systemd
@ -327,7 +329,7 @@ Features:
* dbus: in fedora, make the machine a symlink to /etc/machine-id
* dbus: on fedora, move dbus to early boot
* dbus: move dbus to early boot
* journald: reuse XZ context

View File

@ -189,6 +189,7 @@
<literal>verbose</literal>,
<literal>export</literal>,
<literal>json</literal>,
<literal>json-pretty</literal>,
<literal>cat</literal>. <literal>short</literal>
is the default and generates an output
that is mostly identical to the
@ -209,7 +210,13 @@
Export Format</ulink> for more
information). <literal>json</literal>
formats entries as JSON data
structures. <literal>cat</literal>
structures, one per
line. <literal>json-pretty</literal>
also formats entries as JSON data
structures, but formats them in
multiple lines in order to make them
more readable for
humans. <literal>cat</literal>
generates a very terse output only
showing the actual message of each
journal entry with no meta data, not

View File

@ -439,7 +439,7 @@ _public_ int sd_journal_stream_fd(const char *identifier, int priority, int leve
memcpy(header, identifier, l);
header[l++] = '\n';
header[l++] = '\n';
header[l++] = '\n'; /* unit id */
header[l++] = '0' + priority;
header[l++] = '\n';
header[l++] = '0' + !!level_prefix;

View File

@ -87,7 +87,7 @@ static int help(void) {
" -n --lines=INTEGER Journal entries to show\n"
" --no-tail Show all lines, even in follow mode\n"
" -o --output=STRING Change journal output mode (short, short-monotonic,\n"
" verbose, export, json, cat)\n"
" verbose, export, json, json-pretty, cat)\n"
" -q --quiet Don't show privilege warning\n"
" -l --local Only local entries\n"
" -b --this-boot Show data only from current boot\n"
@ -821,11 +821,6 @@ int main(int argc, char *argv[]) {
on_tty();
have_pager = !arg_no_pager && !arg_follow && pager_open();
if (arg_output == OUTPUT_JSON) {
fputc('[', stdout);
fflush(stdout);
}
for (;;) {
for (;;) {
sd_id128_t boot_id;
@ -874,9 +869,6 @@ int main(int argc, char *argv[]) {
}
}
if (arg_output == OUTPUT_JSON)
fputs("\n]\n", stdout);
finish:
if (j)
sd_journal_close(j);

View File

@ -76,7 +76,7 @@ static bool shall_print(bool show_all, char *p, size_t l) {
return true;
}
static int output_short(sd_journal *j, unsigned line, unsigned n_columns,
static int output_short(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns,
OutputFlags flags) {
int r;
const void *data;
@ -152,7 +152,7 @@ static int output_short(sd_journal *j, unsigned line, unsigned n_columns,
if (priority_len == 1 && *priority >= '0' && *priority <= '7')
p = *priority - '0';
if (flags & OUTPUT_MONOTONIC_MODE) {
if (mode == OUTPUT_SHORT_MONOTONIC) {
uint64_t t;
sd_id128_t boot_id;
@ -278,17 +278,7 @@ finish:
return r;
}
static int output_short_realtime(sd_journal *j, unsigned line,
unsigned n_columns, OutputFlags flags) {
return output_short(j, line, n_columns, flags & ~OUTPUT_MONOTONIC_MODE);
}
static int output_short_monotonic(sd_journal *j, unsigned line,
unsigned n_columns, OutputFlags flags) {
return output_short(j, line, n_columns, flags | OUTPUT_MONOTONIC_MODE);
}
static int output_verbose(sd_journal *j, unsigned line,
static int output_verbose(sd_journal *j, OutputMode mode, unsigned line,
unsigned n_columns, OutputFlags flags) {
const void *data;
size_t length;
@ -340,7 +330,7 @@ static int output_verbose(sd_journal *j, unsigned line,
return 0;
}
static int output_export(sd_journal *j, unsigned line,
static int output_export(sd_journal *j, OutputMode mode, unsigned line,
unsigned n_columns, OutputFlags flags) {
sd_id128_t boot_id;
char sid[33];
@ -452,7 +442,7 @@ static void json_escape(const char* p, size_t l) {
}
}
static int output_json(sd_journal *j, unsigned line,
static int output_json(sd_journal *j, OutputMode mode, unsigned line,
unsigned n_columns, OutputFlags flags) {
uint64_t realtime, monotonic;
char *cursor;
@ -482,21 +472,25 @@ static int output_json(sd_journal *j, unsigned line,
return r;
}
if (line == 1)
fputc('\n', stdout);
if (mode == OUTPUT_JSON_PRETTY)
printf("{\n"
"\t\"__CURSOR\" : \"%s\",\n"
"\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n"
"\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n"
"\t\"_BOOT_ID\" : \"%s\"",
cursor,
(unsigned long long) realtime,
(unsigned long long) monotonic,
sd_id128_to_string(boot_id, sid));
else
fputs(",\n", stdout);
printf("{\n"
"\t\"__CURSOR\" : \"%s\",\n"
"\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n"
"\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n"
"\t\"_BOOT_ID\" : \"%s\"",
cursor,
(unsigned long long) realtime,
(unsigned long long) monotonic,
sd_id128_to_string(boot_id, sid));
printf("{ \"__CURSOR\" : \"%s\", "
"\"__REALTIME_TIMESTAMP\" : \"%llu\", "
"\"__MONOTONIC_TIMESTAMP\" : \"%llu\", "
"\"_BOOT_ID\" : \"%s\"",
cursor,
(unsigned long long) realtime,
(unsigned long long) monotonic,
sd_id128_to_string(boot_id, sid));
free(cursor);
SD_JOURNAL_FOREACH_DATA(j, data, length) {
@ -514,18 +508,25 @@ static int output_json(sd_journal *j, unsigned line,
return -EINVAL;
}
fputs(",\n\t", stdout);
if (mode == OUTPUT_JSON_PRETTY)
fputs(",\n\t", stdout);
else
fputs(", ", stdout);
json_escape(data, c - (const char*) data);
fputs(" : ", stdout);
json_escape(c + 1, length - (c - (const char*) data) - 1);
}
fputs("\n}", stdout);
if (mode == OUTPUT_JSON_PRETTY)
fputs("\n}\n", stdout);
else
fputs(" }\n", stdout);
return 0;
}
static int output_cat(sd_journal *j, unsigned line,
static int output_cat(sd_journal *j, OutputMode mode, unsigned line,
unsigned n_columns, OutputFlags flags) {
const void *data;
size_t l;
@ -547,13 +548,14 @@ static int output_cat(sd_journal *j, unsigned line,
return 0;
}
static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line,
static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, OutputMode mode, unsigned line,
unsigned n_columns, OutputFlags flags) = {
[OUTPUT_SHORT] = output_short_realtime,
[OUTPUT_SHORT_MONOTONIC] = output_short_monotonic,
[OUTPUT_SHORT] = output_short,
[OUTPUT_SHORT_MONOTONIC] = output_short,
[OUTPUT_VERBOSE] = output_verbose,
[OUTPUT_EXPORT] = output_export,
[OUTPUT_JSON] = output_json,
[OUTPUT_JSON_PRETTY] = output_json,
[OUTPUT_CAT] = output_cat
};
@ -566,7 +568,7 @@ int output_journal(sd_journal *j, OutputMode mode, unsigned line,
if (n_columns <= 0)
n_columns = columns();
ret = output_funcs[mode](j, line, n_columns, flags);
ret = output_funcs[mode](j, mode, line, n_columns, flags);
fflush(stdout);
return ret;
}
@ -736,6 +738,7 @@ static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
[OUTPUT_VERBOSE] = "verbose",
[OUTPUT_EXPORT] = "export",
[OUTPUT_JSON] = "json",
[OUTPUT_JSON_PRETTY] = "json-pretty",
[OUTPUT_CAT] = "cat"
};

View File

@ -33,6 +33,7 @@ typedef enum OutputMode {
OUTPUT_VERBOSE,
OUTPUT_EXPORT,
OUTPUT_JSON,
OUTPUT_JSON_PRETTY,
OUTPUT_CAT,
_OUTPUT_MODE_MAX,
_OUTPUT_MODE_INVALID = -1
@ -40,11 +41,10 @@ typedef enum OutputMode {
typedef enum OutputFlags {
OUTPUT_SHOW_ALL = 1 << 0,
OUTPUT_MONOTONIC_MODE = 1 << 1,
OUTPUT_FOLLOW = 1 << 2,
OUTPUT_WARN_CUTOFF = 1 << 3,
OUTPUT_FULL_WIDTH = 1 << 4,
OUTPUT_COLOR = 1 << 5
OUTPUT_FOLLOW = 1 << 1,
OUTPUT_WARN_CUTOFF = 1 << 2,
OUTPUT_FULL_WIDTH = 1 << 3,
OUTPUT_COLOR = 1 << 4
} OutputFlags;
int output_journal(sd_journal *j, OutputMode mode, unsigned line,

View File

@ -3871,7 +3871,7 @@ static int systemctl_help(void) {
" -n --lines=INTEGER Journal entries to show\n"
" --follow Follow journal\n"
" -o --output=STRING Change journal output mode (short, short-monotonic,\n"
" verbose, export, json, cat)\n\n"
" verbose, export, json, json-pretty, cat)\n\n"
"Unit Commands:\n"
" list-units List loaded units\n"
" start [NAME...] Start (activate) one or more units\n"