diff --git a/src/probes/journal.c b/src/probes/journal.c index 5f5fcde..bce0be2 100644 --- a/src/probes/journal.c +++ b/src/probes/journal.c @@ -1,7 +1,7 @@ /* * This program is part of the Clear Linux Project * - * Copyright 2015 Intel Corporation + * Copyright 2015-2017 Intel Corporation * * This program is free software; you can redistribute it and/or modify it under * the terms and conditions of the GNU Lesser General Public License, as @@ -61,11 +61,11 @@ static inline void tm_journal_match_err(int ret) static void add_to_payload(const void *data, size_t length) { if (payload != NULL) { - g_string_append_printf(payload, "%.*s", (int)length, + g_string_append_printf(payload, "%.*s\n", (int)length, (char *)data); } else { payload = g_string_new(NULL); - g_string_printf(payload, "%.*s", (int)length, + g_string_printf(payload, "%.*s\n", (int)length, (char *)data); } } @@ -77,7 +77,7 @@ static bool send_data(char *class) if ((ret = tm_create_record(&handle, severity, class, payload_version)) < 0) { - telem_log(LOG_ERR, "Failed to create record: %s", + telem_log(LOG_ERR, "Failed to create record: %s\n", strerror(-ret)); goto fail; } @@ -86,7 +86,7 @@ static bool send_data(char *class) payload = NULL; if ((ret = tm_set_payload(handle, (char *)payload_str)) < 0) { - telem_log(LOG_ERR, "Failed to set payload: %s", strerror(-ret)); + telem_log(LOG_ERR, "Failed to set payload: %s\n", strerror(-ret)); free(payload_str); tm_free_record(handle); goto fail; @@ -95,7 +95,7 @@ static bool send_data(char *class) free(payload_str); if ((ret = tm_send_record(handle)) < 0) { - telem_log(LOG_ERR, "Failed to send record: %s", strerror(-ret)); + telem_log(LOG_ERR, "Failed to send record: %s\n", strerror(-ret)); tm_free_record(handle); goto fail; } @@ -122,6 +122,16 @@ static int read_new_entries(sd_journal *journal) add_to_payload(data, length); + // For now, we send one record per log message, in case the + // there is a large backlog of messages and we exceed the + // payload size limit (8KB). And ignore errors, hoping that it's + // a transient problem. + + if (!send_data(error_class)) { + telem_log(LOG_ERR, "Failed to send data. Ignoring.\n"); + return num_entries; + } + num_entries++; } @@ -148,19 +158,13 @@ static bool process_existing_entries(sd_journal *journal) return false; } - if (!read_new_entries(journal)) { + ret = read_new_entries(journal); + if (ret < 0) { return false; - } - - if (!payload) { - telem_log(LOG_DEBUG, "No existing entries found\n"); + } else if (ret == 0) { return true; } - if (!send_data(error_class)) { - return false; - } - return true; } @@ -185,6 +189,33 @@ static bool get_boot_id(char **data) return true; } +#define JOURNAL_MATCH(data) \ + do { \ + r = sd_journal_add_match(journal, data, 0); \ + if (r < 0) { \ + tm_journal_match_err(r); \ + return false; \ + } \ + } while (0); + +#define JOURNAL_AND \ + do { \ + r = sd_journal_add_conjunction(journal); \ + if (r < 0) { \ + tm_journal_match_err(r); \ + return false; \ + } \ + } while (0); + +#define JOURNAL_OR \ + do { \ + r = sd_journal_add_disjunction(journal); \ + if (r < 0) { \ + tm_journal_match_err(r); \ + return false; \ + } \ + } while (0); + static bool add_filters(sd_journal *journal) { char *data = NULL; @@ -194,24 +225,29 @@ static bool add_filters(sd_journal *journal) return false; } - r = sd_journal_add_match(journal, data, 0); - if (r < 0) { - tm_journal_match_err(r); - return false; - } - free(data); - - r = sd_journal_add_match(journal, "SYSLOG_IDENTIFIER=crashprobe", 0); - if (r < 0) { - tm_journal_match_err(r); - return false; - } + /* The semantics of how journal entry matching works is described in + * detail in sd_journal_add_match(3). + * + * The matches declared here correspond to the logical expression: + * + * BOOTID && ((P0 || P1 || P2 || P3) || EXITED) + * + * BOOTID is short for _BOOT_ID=VAL, where VAL is the boot ID for the + * current boot. P0, P1, etc stand for PRIORITY=0, etc. And EXITED is + * short for EXIT_CODE=exited. + */ - r = sd_journal_add_match(journal, "PRIORITY=3", 0); - if (r < 0) { - tm_journal_match_err(r); - return false; - } + JOURNAL_MATCH(data); + free(data); + JOURNAL_AND; + // The four highest log levels, all indicating errors + JOURNAL_MATCH("PRIORITY=0"); + JOURNAL_MATCH("PRIORITY=1"); + JOURNAL_MATCH("PRIORITY=2"); + JOURNAL_MATCH("PRIORITY=3"); + JOURNAL_OR; + // Only set for service-level error conditions + JOURNAL_MATCH("EXIT_CODE=exited"); return true; } @@ -258,10 +294,6 @@ static bool process_journal(void) } else if (r < 0) { return false; } - - if (!send_data(error_class)) { - return false; - } } } }