From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <d.csapak@proxmox.com> Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 2BD4F81754 for <pve-devel@lists.proxmox.com>; Wed, 24 Nov 2021 15:48:20 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 255FA21750 for <pve-devel@lists.proxmox.com>; Wed, 24 Nov 2021 15:47:50 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 2A9852173D for <pve-devel@lists.proxmox.com>; Wed, 24 Nov 2021 15:47:49 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 04E88447C8 for <pve-devel@lists.proxmox.com>; Wed, 24 Nov 2021 15:47:49 +0100 (CET) From: Dominik Csapak <d.csapak@proxmox.com> To: pve-devel@lists.proxmox.com Date: Wed, 24 Nov 2021 15:47:46 +0100 Message-Id: <20211124144748.68687-2-d.csapak@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211124144748.68687-1-d.csapak@proxmox.com> References: <20211124144748.68687-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.201 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pve-devel] [PATCH mini-journalreader 1/1] add '-j' flag to output json X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion <pve-devel.lists.proxmox.com> List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pve-devel>, <mailto:pve-devel-request@lists.proxmox.com?subject=unsubscribe> List-Archive: <http://lists.proxmox.com/pipermail/pve-devel/> List-Post: <mailto:pve-devel@lists.proxmox.com> List-Help: <mailto:pve-devel-request@lists.proxmox.com?subject=help> List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel>, <mailto:pve-devel-request@lists.proxmox.com?subject=subscribe> X-List-Received-Date: Wed, 24 Nov 2021 14:48:20 -0000 in the format: {"data":[... log lines ...],"success":1} this is chosen so that we can achieve api compatibility when we stream this output to an api client strings are escaped by replacing '"', '\' and all values <= 0x1F by their \uXXXX representation invalid utf8 sequences will be returned as they are (jq and the browser can handle that) Signed-off-by: Dominik Csapak <d.csapak@proxmox.com> --- src/mini-journalreader.c | 66 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/src/mini-journalreader.c b/src/mini-journalreader.c index 92176ac..7ce7857 100644 --- a/src/mini-journalreader.c +++ b/src/mini-journalreader.c @@ -32,6 +32,8 @@ #define BUFSIZE 4096 static char BUF[BUFSIZE]; +bool json = false; +bool first_line = true; static uint64_t get_timestamp(sd_journal *j) { uint64_t timestamp; @@ -63,8 +65,19 @@ static void print_cursor(sd_journal *j) { fprintf(stderr, "Failed to get cursor: %s\n", strerror(-r)); exit(1); } + if (json) { + if (!first_line) { + print_to_buf(",\"", 2); + } else { + print_to_buf("\"", 1); + } + } print_to_buf(cursor, strlen(cursor)); + if (json) { + print_to_buf("\"", 1); + } print_to_buf("\n", 1); + first_line = false; free(cursor); } @@ -93,7 +106,15 @@ static void print_reboot(sd_journal *j) { if (bootid[0] != '\0') { // we have some bootid if (memcmp(bootid, d, l)) { // a new bootid found memcpy(bootid, d, l); - print_to_buf("-- Reboot --\n", 13); + if (json) { + if (!first_line) { + print_to_buf(",", 1); + } + print_to_buf("\"-- Reboot --\"\n", 15); + first_line = false; + } else { + print_to_buf("-- Reboot --\n", 13); + } } } else { memcpy(bootid, d, l); @@ -149,13 +170,35 @@ static bool print_field(sd_journal *j, const char *field) { size_t fieldlen = strlen(field)+1; d += fieldlen; l -= fieldlen; - print_to_buf(d, l); + + if (json) { + char tmp[7]; + for (size_t i = 0; i < l;i++) { + if (d[i] == '"' || d[i] == '\\' || (d[i] >= 0 && d[i] <= 0x1F)) { + sprintf(tmp, "\\u%04X", d[i]); + print_to_buf(tmp, 6); + } else { + print_to_buf(d+i, 1); + } + } + } else { + print_to_buf(d, l); + } return true; } static void print_line(sd_journal *j) { print_reboot(j); + + if (json) { + if (!first_line) { + print_to_buf(",", 1); + } + print_to_buf("\"", 1); + first_line = false; + } + print_timestamp(j); print_to_buf(" ", 1); print_field(j, "_HOSTNAME"); @@ -167,6 +210,11 @@ static void print_line(sd_journal *j) { print_pid(j); print_to_buf(": ", 2); print_field(j, "MESSAGE"); + + if (json) { + print_to_buf("\"", 1); + } + print_to_buf("\n", 1); } @@ -184,6 +232,7 @@ _Noreturn static void usage(char *error) { " -n <integer>\t\tprint the last number entries logged\n" " -f <cursor>\t\tprint from this cursor\n" " -t <cursor>\t\tprint to this cursor\n" + " -j \t\t\tprint as json" " -h \t\t\tthis help\n" "\n" "Passing no range option will dump all the available journal\n" @@ -217,7 +266,7 @@ int main(int argc, char *argv[]) { progname = argv[0]; - while ((c = (char)getopt (argc, argv, "b:e:d:n:f:t:h")) != -1) { + while ((c = (char)getopt (argc, argv, "b:e:d:n:f:t:jh")) != -1) { switch (c) { case 'b': begin = arg_to_uint64(optarg); @@ -239,6 +288,9 @@ int main(int argc, char *argv[]) { case 't': endcursor = optarg; break; + case 'j': + json = true; + break; case 'h': usage(NULL); case '?': @@ -285,6 +337,10 @@ int main(int argc, char *argv[]) { return 1; } + if (json) { + print_to_buf("{\"data\":[", 9); + } + // if we want to print the last x entries, seek to cursor or end, // then x entries back, print the cursor and finally print the // entries until end or cursor @@ -350,6 +406,10 @@ int main(int argc, char *argv[]) { print_cursor(j); sd_journal_close(j); + if (json) { + print_to_buf("],\"success\":1}", 14); + } + // print remaining buffer fflush_unlocked(stdout); -- 2.30.2