rebase to upstream version 8.1910.0
resolves: rhbz#1743537
This commit is contained in:
parent
3df0efa102
commit
f4d39b1b7f
2
.gitignore
vendored
2
.gitignore
vendored
@ -65,3 +65,5 @@ rsyslog-4.6.3.tar.gz
|
||||
/rsyslog-doc-8.1904.0.tar.gz
|
||||
/rsyslog-8.1907.0.tar.gz
|
||||
/rsyslog-doc-8.1907.0.tar.gz
|
||||
/rsyslog-8.1910.0.tar.gz
|
||||
/rsyslog-doc-8.1910.0.tar.gz
|
||||
|
752
imjournal-rewrite.patch
Normal file
752
imjournal-rewrite.patch
Normal file
@ -0,0 +1,752 @@
|
||||
From 78976a9bc0592317be2e41b7f3703803f7971e1e Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Vymazal <jvymazal@redhat.com>
|
||||
Date: Wed, 25 Sep 2019 15:18:57 +0200
|
||||
Subject: [PATCH] plugin code restructuring, added remote option
|
||||
|
||||
Decomposed ReadJournal() a bit, also now coupling journald
|
||||
variables in one struct, added few warning messages and debug
|
||||
prints to help with bug hunts in future, also got rid of two
|
||||
needless journald calls. WorkAroundJournalBug now deprecated.
|
||||
Added option to pull journald records from outside local machine.
|
||||
---
|
||||
plugins/imjournal/imjournal.c | 368 ++++++++++++++++++++--------------
|
||||
1 file changed, 214 insertions(+), 154 deletions(-)
|
||||
|
||||
diff --git a/plugins/imjournal/imjournal.c b/plugins/imjournal/imjournal.c
|
||||
index 2e27922b51..8008f159c4 100644
|
||||
--- a/plugins/imjournal/imjournal.c
|
||||
+++ b/plugins/imjournal/imjournal.c
|
||||
@@ -81,8 +81,9 @@ static struct configSettings_s {
|
||||
int iDfltFacility;
|
||||
int bUseJnlPID;
|
||||
char *usePid;
|
||||
- int bWorkAroundJournalBug;
|
||||
+ int bWorkAroundJournalBug; /* deprecated, left for backwards compatibility only */
|
||||
int bFsync;
|
||||
+ int bRemote;
|
||||
} cs;
|
||||
|
||||
static rsRetVal facilityHdlr(uchar **pp, void *pVal);
|
||||
@@ -100,7 +101,8 @@ static struct cnfparamdescr modpdescr[] = {
|
||||
{ "usepidfromsystem", eCmdHdlrBinary, 0 },
|
||||
{ "usepid", eCmdHdlrString, 0 },
|
||||
{ "workaroundjournalbug", eCmdHdlrBinary, 0 },
|
||||
- { "fsync", eCmdHdlrBinary, 0 }
|
||||
+ { "fsync", eCmdHdlrBinary, 0 },
|
||||
+ { "remote", eCmdHdlrBinary, 0 }
|
||||
};
|
||||
static struct cnfparamblk modpblk =
|
||||
{ CNFPARAMBLK_VERSION,
|
||||
@@ -120,8 +122,6 @@ static prop_t *pLocalHostIP = NULL; /* a pseudo-constant propterty for 127.0.0.1
|
||||
static const char *pidFieldName; /* read-only after startup */
|
||||
static int bPidFallBack;
|
||||
static ratelimit_t *ratelimiter = NULL;
|
||||
-static sd_journal *j;
|
||||
-static sbool reloaded = 0;
|
||||
static struct {
|
||||
statsobj_t *stats;
|
||||
STATSCOUNTER_DEF(ctrSubmitted, mutCtrSubmitted)
|
||||
@@ -134,34 +134,58 @@ static struct {
|
||||
uint64 ratelimitDiscardedInInterval;
|
||||
uint64 diskUsageBytes;
|
||||
} statsCounter;
|
||||
-static char *last_cursor = NULL;
|
||||
+struct journalContext_s { /* structure encapsulating all the journald_API-related stuff */
|
||||
+ sd_journal *j; /* main object encapsulating journal for us, has to be used in every sd_journal*() call */
|
||||
+ sbool reloaded; /* we have reloaded journal after detecting rotation */
|
||||
+ sbool atHead; /* true if we are at start of journal (no seek was done) */
|
||||
+ char *cursor; /* should point to last valid journald entry we processed */
|
||||
+};
|
||||
+static struct journalContext_s journalContext = {NULL, 0, 1, NULL};
|
||||
|
||||
#define J_PROCESS_PERIOD 1024 /* Call sd_journal_process() every 1,024 records */
|
||||
|
||||
-static rsRetVal persistJournalState(int trySave);
|
||||
+static rsRetVal persistJournalState(void);
|
||||
static rsRetVal loadJournalState(void);
|
||||
|
||||
static rsRetVal openJournal(void) {
|
||||
int r;
|
||||
DEFiRet;
|
||||
|
||||
- if ((r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY)) < 0) {
|
||||
- LogError(-r, RS_RET_IO_ERROR, "imjournal: sd_journal_open() failed");
|
||||
- iRet = RS_RET_IO_ERROR;
|
||||
+ if (journalContext.j) {
|
||||
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imjournal: opening journal when already opened.\n");
|
||||
}
|
||||
- if ((r = sd_journal_get_fd(j)) < 0) {
|
||||
- LogError(-r, RS_RET_IO_ERROR, "imjournal: sd_journal_get_fd() failed");
|
||||
+ if ((r = sd_journal_open(&journalContext.j, cs.bRemote? 0 : SD_JOURNAL_LOCAL_ONLY)) < 0) {
|
||||
+ LogError(-r, RS_RET_IO_ERROR, "imjournal: sd_journal_open() failed");
|
||||
iRet = RS_RET_IO_ERROR;
|
||||
}
|
||||
+ journalContext.atHead = 1;
|
||||
RETiRet;
|
||||
}
|
||||
|
||||
/* trySave shoulod only be true if there is no journald error preceeding this call */
|
||||
-static void closeJournal(int trySave) {
|
||||
- if (cs.stateFile) { /* can't persist without a state file */
|
||||
- persistJournalState(trySave);
|
||||
+static void closeJournal(void) {
|
||||
+ if (!journalContext.j) {
|
||||
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imjournal: closing NULL journal.\n");
|
||||
}
|
||||
- sd_journal_close(j);
|
||||
+ sd_journal_close(journalContext.j);
|
||||
+ journalContext.j = NULL; /* setting to NULL here as journald API will not do that for us... */
|
||||
+}
|
||||
+
|
||||
+static int journalGetData(const char *field, const void **data, size_t *length)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = sd_journal_get_data(journalContext.j, field, data, length);
|
||||
+ if (ret == -EADDRNOTAVAIL) {
|
||||
+ LogError(-ret, RS_RET_ERR, "imjournal: Tried to get data without a 'next' call.\n");
|
||||
+ if ((ret = sd_journal_next(journalContext.j)) < 0) {
|
||||
+ LogError(-ret, RS_RET_ERR, "imjournal: sd_journal_next() failed\n");
|
||||
+ } else {
|
||||
+ ret = sd_journal_get_data(journalContext.j, field, data, length);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -223,12 +247,84 @@ sanitizeValue(const char *in, size_t len, char **out)
|
||||
}
|
||||
|
||||
|
||||
+/* Read JSON part of single journald message and return it as JSON object
|
||||
+ */
|
||||
+static rsRetVal
|
||||
+readJSONfromJournalMsg(struct fjson_object **json)
|
||||
+{
|
||||
+ DEFiRet;
|
||||
+ const void *get;
|
||||
+ const void *equal_sign;
|
||||
+ struct fjson_object *jval;
|
||||
+ size_t l;
|
||||
+ long prefixlen = 0;
|
||||
+
|
||||
+ CHKmalloc(*json = fjson_object_new_object());
|
||||
+
|
||||
+ SD_JOURNAL_FOREACH_DATA(journalContext.j, get, l) {
|
||||
+ char *data;
|
||||
+ char *name;
|
||||
+
|
||||
+ /* locate equal sign, this is always present */
|
||||
+ equal_sign = memchr(get, '=', l);
|
||||
+
|
||||
+ /* ... but we know better than to trust the specs */
|
||||
+ if (equal_sign == NULL) {
|
||||
+ LogError(0, RS_RET_ERR, "SD_JOURNAL_FOREACH_DATA()"
|
||||
+ "returned a malformed field (has no '='): '%s'", (char*)get);
|
||||
+ continue; /* skip the entry */
|
||||
+ }
|
||||
+
|
||||
+ /* get length of journal data prefix */
|
||||
+ prefixlen = ((char *)equal_sign - (char *)get);
|
||||
+
|
||||
+ CHKmalloc(name = strndup(get, prefixlen));
|
||||
+
|
||||
+ prefixlen++; /* remove '=' */
|
||||
+
|
||||
+ CHKiRet_Hdlr(sanitizeValue(((const char *)get) + prefixlen, l - prefixlen, &data)) {
|
||||
+ free (name);
|
||||
+ FINALIZE;
|
||||
+ }
|
||||
+
|
||||
+ /* and save them to json object */
|
||||
+ jval = fjson_object_new_string((char *)data);
|
||||
+ fjson_object_object_add(*json, name, jval);
|
||||
+ free (data);
|
||||
+ free (name);
|
||||
+ }
|
||||
+finalize_it:
|
||||
+ RETiRet;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* Try to obtain current journald cursor and save it to journalContext struct.
|
||||
+ */
|
||||
+static rsRetVal
|
||||
+updateJournalCursor(void)
|
||||
+{
|
||||
+ DEFiRet;
|
||||
+ char *c = NULL;
|
||||
+ int r;
|
||||
+
|
||||
+ if ((r = sd_journal_get_cursor(journalContext.j, &c)) < 0) {
|
||||
+ LogError(-r, RS_RET_ERR, "imjournal: Could not get journald cursor!\n");
|
||||
+ ABORT_FINALIZE(RS_RET_ERR);
|
||||
+ }
|
||||
+ /* save journal cursor (at this point we can be sure it is valid) */
|
||||
+ free(journalContext.cursor);
|
||||
+ journalContext.cursor = c;
|
||||
+finalize_it:
|
||||
+ RETiRet;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* enqueue the the journal message into the message queue.
|
||||
* The provided msg string is not freed - thus must be done
|
||||
* by the caller.
|
||||
*/
|
||||
static rsRetVal
|
||||
-enqMsg(uchar *msg, uchar *pszTag, int iFacility, int iSeverity, struct timeval *tp, struct json_object *json,
|
||||
+enqMsg(uchar *msg, uchar *pszTag, int iFacility, int iSeverity, struct timeval *tp, struct fjson_object *json,
|
||||
int sharedJsonProperties)
|
||||
{
|
||||
struct syslogTime st;
|
||||
@@ -267,15 +363,17 @@ int sharedJsonProperties)
|
||||
STATSCOUNTER_INC(statsCounter.ctrSubmitted, statsCounter.mutCtrSubmitted);
|
||||
|
||||
finalize_it:
|
||||
- if (iRet == RS_RET_DISCARDMSG)
|
||||
+ if (iRet == RS_RET_DISCARDMSG) {
|
||||
STATSCOUNTER_INC(statsCounter.ctrDiscarded, statsCounter.mutCtrDiscarded);
|
||||
+ } else if (iRet != RS_RET_OK) {
|
||||
+ LogError(0, RS_RET_ERR, "imjournal: error during enqMsg().\n");
|
||||
+ }
|
||||
|
||||
RETiRet;
|
||||
}
|
||||
|
||||
|
||||
-/* Read journal log while data are available, each read() reads one
|
||||
- * record of printk buffer.
|
||||
+/* Read journal log while data are available, each read() reads one journald record.
|
||||
*/
|
||||
static rsRetVal
|
||||
readjournal(void)
|
||||
@@ -285,39 +383,32 @@ readjournal(void)
|
||||
struct timeval tv;
|
||||
uint64_t timestamp;
|
||||
|
||||
- struct json_object *json = NULL;
|
||||
+ struct fjson_object *json = NULL;
|
||||
int r;
|
||||
|
||||
/* Information from messages */
|
||||
char *message = NULL;
|
||||
char *sys_iden;
|
||||
char *sys_iden_help = NULL;
|
||||
- char *c = NULL;
|
||||
|
||||
const void *get;
|
||||
const void *pidget;
|
||||
size_t length;
|
||||
size_t pidlength;
|
||||
|
||||
- const void *equal_sign;
|
||||
- struct json_object *jval;
|
||||
- size_t l;
|
||||
-
|
||||
- long prefixlen = 0;
|
||||
-
|
||||
int severity = cs.iDfltSeverity;
|
||||
int facility = cs.iDfltFacility;
|
||||
|
||||
/* Get message text */
|
||||
- if (sd_journal_get_data(j, "MESSAGE", &get, &length) < 0) {
|
||||
- message = strdup("");
|
||||
+ if (journalGetData("MESSAGE", &get, &length) < 0) {
|
||||
+ CHKmalloc(message = strdup(""));
|
||||
} else {
|
||||
CHKiRet(sanitizeValue(((const char *)get) + 8, length - 8, &message));
|
||||
}
|
||||
STATSCOUNTER_INC(statsCounter.ctrRead, statsCounter.mutCtrRead);
|
||||
|
||||
/* Get message severity ("priority" in journald's terminology) */
|
||||
- if (sd_journal_get_data(j, "PRIORITY", &get, &length) >= 0) {
|
||||
+ if (journalGetData("PRIORITY", &get, &length) >= 0) {
|
||||
if (length == 10) {
|
||||
severity = ((char *)get)[9] - '0';
|
||||
if (severity < 0 || 7 < severity) {
|
||||
@@ -332,7 +423,7 @@ readjournal(void)
|
||||
}
|
||||
|
||||
/* Get syslog facility */
|
||||
- if (sd_journal_get_data(j, "SYSLOG_FACILITY", &get, &length) >= 0) {
|
||||
+ if (journalGetData("SYSLOG_FACILITY", &get, &length) >= 0) {
|
||||
// Note: the journal frequently contains invalid facilities!
|
||||
if (length == 17 || length == 18) {
|
||||
facility = ((char *)get)[16] - '0';
|
||||
@@ -352,14 +443,14 @@ readjournal(void)
|
||||
}
|
||||
|
||||
/* Get message identifier, client pid and add ':' */
|
||||
- if (sd_journal_get_data(j, "SYSLOG_IDENTIFIER", &get, &length) >= 0) {
|
||||
+ if (journalGetData("SYSLOG_IDENTIFIER", &get, &length) >= 0) {
|
||||
CHKiRet(sanitizeValue(((const char *)get) + 18, length - 18, &sys_iden));
|
||||
} else {
|
||||
CHKmalloc(sys_iden = strdup("journal"));
|
||||
}
|
||||
|
||||
/* trying to get PID, default is "SYSLOG_PID" property */
|
||||
- if (sd_journal_get_data(j, pidFieldName, &pidget, &pidlength) >= 0) {
|
||||
+ if (journalGetData(pidFieldName, &pidget, &pidlength) >= 0) {
|
||||
char *sys_pid;
|
||||
int val_ofs;
|
||||
|
||||
@@ -372,7 +463,7 @@ readjournal(void)
|
||||
free (sys_pid);
|
||||
} else {
|
||||
/* this is fallback, "SYSLOG_PID" doesn't exist so trying to get "_PID" property */
|
||||
- if (bPidFallBack && sd_journal_get_data(j, "_PID", &pidget, &pidlength) >= 0) {
|
||||
+ if (bPidFallBack && journalGetData("_PID", &pidget, &pidlength) >= 0) {
|
||||
char *sys_pid;
|
||||
int val_ofs;
|
||||
|
||||
@@ -396,55 +487,15 @@ readjournal(void)
|
||||
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
- json = json_object_new_object();
|
||||
-
|
||||
- SD_JOURNAL_FOREACH_DATA(j, get, l) {
|
||||
- char *data;
|
||||
- char *name;
|
||||
-
|
||||
- /* locate equal sign, this is always present */
|
||||
- equal_sign = memchr(get, '=', l);
|
||||
-
|
||||
- /* ... but we know better than to trust the specs */
|
||||
- if (equal_sign == NULL) {
|
||||
- LogError(0, RS_RET_ERR, "SD_JOURNAL_FOREACH_DATA()"
|
||||
- "returned a malformed field (has no '='): '%s'", (char*)get);
|
||||
- continue; /* skip the entry */
|
||||
- }
|
||||
-
|
||||
- /* get length of journal data prefix */
|
||||
- prefixlen = ((char *)equal_sign - (char *)get);
|
||||
-
|
||||
- name = strndup(get, prefixlen);
|
||||
- CHKmalloc(name);
|
||||
-
|
||||
- prefixlen++; /* remove '=' */
|
||||
-
|
||||
- CHKiRet_Hdlr(sanitizeValue(((const char *)get) + prefixlen, l - prefixlen, &data)) {
|
||||
- free (name);
|
||||
- FINALIZE;
|
||||
- }
|
||||
-
|
||||
- /* and save them to json object */
|
||||
- jval = json_object_new_string((char *)data);
|
||||
- json_object_object_add(json, name, jval);
|
||||
- free (data);
|
||||
- free (name);
|
||||
- }
|
||||
+ CHKiRet(readJSONfromJournalMsg(&json));
|
||||
|
||||
/* calculate timestamp */
|
||||
- if (sd_journal_get_realtime_usec(j, ×tamp) >= 0) {
|
||||
+ if (sd_journal_get_realtime_usec(journalContext.j, ×tamp) >= 0) {
|
||||
tv.tv_sec = timestamp / 1000000;
|
||||
tv.tv_usec = timestamp % 1000000;
|
||||
}
|
||||
|
||||
- if (cs.bWorkAroundJournalBug) {
|
||||
- /* save journal cursor (at this point we can be sure it is valid) */
|
||||
- if (!sd_journal_get_cursor(j, &c)) {
|
||||
- free(last_cursor);
|
||||
- last_cursor = c;
|
||||
- }
|
||||
- }
|
||||
+ iRet = updateJournalCursor();
|
||||
|
||||
/* submit message */
|
||||
enqMsg((uchar *)message, (uchar *) sys_iden_help, facility, severity, &tv, json, 0);
|
||||
@@ -456,32 +507,22 @@ readjournal(void)
|
||||
}
|
||||
|
||||
|
||||
-/* This function gets journal cursor and saves it into state file.
|
||||
- * If WorkAroundJournalBug option is turned on it does use cursor saved previously.
|
||||
- * If it is false and if "trySave" is false it skips altogether.
|
||||
+/* This function saves journal cursor into state file.
|
||||
+ * It must be checked that stateFile is configured prior to calling this.
|
||||
*/
|
||||
static rsRetVal
|
||||
-persistJournalState(int trySave)
|
||||
+persistJournalState(void)
|
||||
{
|
||||
DEFiRet;
|
||||
FILE *sf = NULL; /* state file */
|
||||
char tmp_sf[MAXFNAME];
|
||||
size_t n;
|
||||
|
||||
- if (cs.bWorkAroundJournalBug) {
|
||||
- /* first check that we have valid cursor */
|
||||
- if (!last_cursor) {
|
||||
- ABORT_FINALIZE(RS_RET_OK);
|
||||
- }
|
||||
- } else if (trySave) {
|
||||
- int ret;
|
||||
- free(last_cursor);
|
||||
- if ((ret = sd_journal_get_cursor(j, &last_cursor))) {
|
||||
- LogError(-ret, RS_RET_ERR, "imjournal: sd_journal_get_cursor() failed");
|
||||
- last_cursor = NULL;
|
||||
- ABORT_FINALIZE(RS_RET_ERR);
|
||||
- }
|
||||
- } else { /* not trying to get cursor out of invalid journal state */
|
||||
+ DBGPRINTF("Persisting journal position, cursor: %s, at head? %d\n",
|
||||
+ journalContext.cursor, journalContext.atHead);
|
||||
+
|
||||
+ /* first check that we have valid cursor */
|
||||
+ if (!journalContext.cursor) {
|
||||
ABORT_FINALIZE(RS_RET_OK);
|
||||
}
|
||||
|
||||
@@ -500,7 +541,7 @@ persistJournalState(int trySave)
|
||||
ABORT_FINALIZE(RS_RET_FOPEN_FAILURE);
|
||||
}
|
||||
|
||||
- if(fputs(last_cursor, sf) == EOF) {
|
||||
+ if(fputs(journalContext.cursor, sf) == EOF) {
|
||||
LogError(errno, RS_RET_IO_ERROR, "imjournal: failed to save cursor to: '%s'", tmp_sf);
|
||||
ABORT_FINALIZE(RS_RET_IO_ERROR);
|
||||
}
|
||||
@@ -541,43 +582,59 @@ persistJournalState(int trySave)
|
||||
|
||||
static rsRetVal skipOldMessages(void);
|
||||
|
||||
-#define POLL_TIMEOUT 900000 /* timeout for poll is 900ms */
|
||||
-
|
||||
static rsRetVal
|
||||
-pollJournal(void)
|
||||
+handleRotation(void)
|
||||
{
|
||||
DEFiRet;
|
||||
- int err;
|
||||
+ int r;
|
||||
|
||||
- err = sd_journal_wait(j, POLL_TIMEOUT);
|
||||
- if (err == SD_JOURNAL_INVALIDATE && !reloaded) {
|
||||
- STATSCOUNTER_INC(statsCounter.ctrRotations, statsCounter.mutCtrRotations);
|
||||
- closeJournal(0);
|
||||
+ LogMsg(0, RS_RET_OK, LOG_NOTICE, "imjournal: journal files changed, reloading...\n");
|
||||
+ STATSCOUNTER_INC(statsCounter.ctrRotations, statsCounter.mutCtrRotations);
|
||||
+ closeJournal();
|
||||
|
||||
- iRet = openJournal();
|
||||
- if (iRet != RS_RET_OK) {
|
||||
- ABORT_FINALIZE(RS_RET_ERR);
|
||||
- }
|
||||
+ iRet = openJournal();
|
||||
+ if (iRet != RS_RET_OK) {
|
||||
+ ABORT_FINALIZE(RS_RET_ERR);
|
||||
+ }
|
||||
|
||||
- /* If we have locally saved cursor there is no need to read it from state file */
|
||||
- if (cs.bWorkAroundJournalBug && last_cursor)
|
||||
- {
|
||||
- if (sd_journal_seek_cursor(j, last_cursor) != 0) {
|
||||
- LogError(0, RS_RET_ERR, "imjournal: "
|
||||
- "couldn't seek to cursor `%s'\n", last_cursor);
|
||||
- iRet = RS_RET_ERR;
|
||||
- }
|
||||
- /* Need to advance because cursor points at last processed message */
|
||||
- sd_journal_next(j);
|
||||
+ /* If we have locally saved cursor there is no need to read it from state file */
|
||||
+ if (journalContext.cursor)
|
||||
+ {
|
||||
+ if (sd_journal_seek_cursor(journalContext.j, journalContext.cursor) != 0) {
|
||||
+ LogError(0, RS_RET_ERR, "imjournal: "
|
||||
+ "couldn't seek to cursor `%s'\n", journalContext.cursor);
|
||||
+ iRet = RS_RET_ERR;
|
||||
}
|
||||
- else if (cs.stateFile) {
|
||||
- iRet = loadJournalState();
|
||||
+ journalContext.atHead = 0;
|
||||
+ /* Need to advance because cursor points at last processed message */
|
||||
+ if ((r = sd_journal_next(journalContext.j)) < 0) {
|
||||
+ LogError(-r, RS_RET_ERR, "imjournal: sd_journal_next() failed");
|
||||
+ iRet = RS_RET_ERR;
|
||||
}
|
||||
- LogMsg(0, RS_RET_OK, LOG_NOTICE, "imjournal: journal reloaded...");
|
||||
- reloaded = 1;
|
||||
+ }
|
||||
+ else if (cs.stateFile) {
|
||||
+ iRet = loadJournalState();
|
||||
+ }
|
||||
+ journalContext.reloaded = 1;
|
||||
+
|
||||
+finalize_it:
|
||||
+ RETiRet;
|
||||
+}
|
||||
+
|
||||
+#define POLL_TIMEOUT 900000 /* timeout for poll is 900ms */
|
||||
+
|
||||
+static rsRetVal
|
||||
+pollJournal(void)
|
||||
+{
|
||||
+ DEFiRet;
|
||||
+ int err;
|
||||
+
|
||||
+ err = sd_journal_wait(journalContext.j, POLL_TIMEOUT);
|
||||
+ if (err == SD_JOURNAL_INVALIDATE && !journalContext.reloaded) {
|
||||
+ CHKiRet(handleRotation());
|
||||
}
|
||||
else {
|
||||
- reloaded = 0;
|
||||
+ journalContext.reloaded = 0;
|
||||
}
|
||||
|
||||
finalize_it:
|
||||
@@ -591,12 +648,13 @@ skipOldMessages(void)
|
||||
int r;
|
||||
DEFiRet;
|
||||
|
||||
- if ((r = sd_journal_seek_tail(j)) < 0) {
|
||||
+ if ((r = sd_journal_seek_tail(journalContext.j)) < 0) {
|
||||
LogError(-r, RS_RET_ERR,
|
||||
"imjournal: sd_journal_seek_tail() failed");
|
||||
ABORT_FINALIZE(RS_RET_ERR);
|
||||
}
|
||||
- if ((r = sd_journal_previous(j)) < 0) {
|
||||
+ journalContext.atHead = 0;
|
||||
+ if ((r = sd_journal_previous(journalContext.j)) < 0) {
|
||||
LogError(-r, RS_RET_ERR,
|
||||
"imjournal: sd_journal_previous() failed");
|
||||
ABORT_FINALIZE(RS_RET_ERR);
|
||||
@@ -615,6 +673,9 @@ loadJournalState(void)
|
||||
int r;
|
||||
FILE *r_sf;
|
||||
|
||||
+ DBGPRINTF("Loading journal position, at head? %d, reloaded? %d\n",
|
||||
+ journalContext.atHead, journalContext.reloaded);
|
||||
+
|
||||
if (cs.stateFile[0] != '/') {
|
||||
char *new_stateFile;
|
||||
if (-1 == asprintf(&new_stateFile, "%s/%s", (char *)glbl.GetWorkDir(), cs.stateFile)) {
|
||||
@@ -639,13 +700,14 @@ loadJournalState(void)
|
||||
if ((r_sf = fopen(cs.stateFile, "rb")) != NULL) {
|
||||
char readCursor[128 + 1];
|
||||
if (fscanf(r_sf, "%128s\n", readCursor) != EOF) {
|
||||
- if (sd_journal_seek_cursor(j, readCursor) != 0) {
|
||||
+ if (sd_journal_seek_cursor(journalContext.j, readCursor) != 0) {
|
||||
LogError(0, RS_RET_ERR, "imjournal: "
|
||||
"couldn't seek to cursor `%s'\n", readCursor);
|
||||
iRet = RS_RET_ERR;
|
||||
} else {
|
||||
+ journalContext.atHead = 0;
|
||||
char * tmp_cursor = NULL;
|
||||
- sd_journal_next(j);
|
||||
+ sd_journal_next(journalContext.j);
|
||||
/*
|
||||
* This is resolving the situation when system is after reboot and boot_id
|
||||
* doesn't match so cursor pointing into "future".
|
||||
@@ -658,14 +720,15 @@ loadJournalState(void)
|
||||
* but if cursor has been intentionally compromised it could stop logging even
|
||||
* with persistent journal.
|
||||
* */
|
||||
- if ((r = sd_journal_get_cursor(j, &tmp_cursor)) < 0) {
|
||||
+ if ((r = sd_journal_get_cursor(journalContext.j, &tmp_cursor)) < 0) {
|
||||
LogError(-r, RS_RET_IO_ERROR, "imjournal: "
|
||||
"loaded invalid cursor, seeking to the head of journal\n");
|
||||
- if ((r = sd_journal_seek_head(j)) < 0) {
|
||||
+ if ((r = sd_journal_seek_head(journalContext.j)) < 0) {
|
||||
LogError(-r, RS_RET_ERR, "imjournal: "
|
||||
"sd_journal_seek_head() failed, when cursor is invalid\n");
|
||||
iRet = RS_RET_ERR;
|
||||
}
|
||||
+ journalContext.atHead = 1;
|
||||
}
|
||||
free(tmp_cursor);
|
||||
}
|
||||
@@ -680,18 +743,15 @@ loadJournalState(void)
|
||||
if (iRet != RS_RET_OK && cs.bIgnoreNonValidStatefile) {
|
||||
/* ignore state file errors */
|
||||
iRet = RS_RET_OK;
|
||||
- LogError(0, NO_ERRCODE, "imjournal: ignoring invalid state file %s",
|
||||
- cs.stateFile);
|
||||
+ LogError(0, NO_ERRCODE, "imjournal: ignoring invalid state file %s", cs.stateFile);
|
||||
if (cs.bIgnorePrevious) {
|
||||
skipOldMessages();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
- LogError(0, RS_RET_FOPEN_FAILURE, "imjournal: "
|
||||
- "open on state file `%s' failed\n", cs.stateFile);
|
||||
+ LogError(0, RS_RET_FOPEN_FAILURE, "imjournal: open on state file `%s' failed\n", cs.stateFile);
|
||||
if (cs.bIgnorePrevious) {
|
||||
- /* Seek to the very end of the journal and ignore all
|
||||
- * older messages. */
|
||||
+ /* Seek to the very end of the journal and ignore all older messages. */
|
||||
skipOldMessages();
|
||||
}
|
||||
}
|
||||
@@ -704,7 +764,7 @@ static void
|
||||
tryRecover(void) {
|
||||
LogMsg(0, RS_RET_OK, LOG_INFO, "imjournal: trying to recover from journal error");
|
||||
STATSCOUNTER_INC(statsCounter.ctrRecoveryAttempts, statsCounter.mutCtrRecoveryAttempts);
|
||||
- closeJournal(0);
|
||||
+ closeJournal();
|
||||
srSleep(10, 0); // do not hammer machine with too-frequent retries
|
||||
openJournal();
|
||||
}
|
||||
@@ -723,8 +783,7 @@ CODESTARTrunInput
|
||||
/* Load our position in the journal from the state file. */
|
||||
CHKiRet(loadJournalState());
|
||||
} else if (cs.bIgnorePrevious) {
|
||||
- /* Seek to the very end of the journal and ignore all
|
||||
- * older messages. */
|
||||
+ /* Seek to the very end of the journal and ignore all older messages. */
|
||||
skipOldMessages();
|
||||
}
|
||||
|
||||
@@ -758,7 +817,7 @@ CODESTARTrunInput
|
||||
while (glbl.GetGlobalInputTermState() == 0) {
|
||||
int r;
|
||||
|
||||
- r = sd_journal_next(j);
|
||||
+ r = sd_journal_next(journalContext.j);
|
||||
if (r < 0) {
|
||||
LogError(-r, RS_RET_ERR, "imjournal: sd_journal_next() failed");
|
||||
tryRecover();
|
||||
@@ -766,8 +825,12 @@ CODESTARTrunInput
|
||||
}
|
||||
|
||||
if (r == 0) {
|
||||
+ if (journalContext.atHead) {
|
||||
+ LogMsg(0, RS_RET_OK, LOG_WARNING, "imjournal: "
|
||||
+ "Journal indicates no msgs when positioned at head.\n");
|
||||
+ }
|
||||
/* No new messages, wait for activity. */
|
||||
- if (pollJournal() != RS_RET_OK && !reloaded) {
|
||||
+ if (pollJournal() != RS_RET_OK && !journalContext.reloaded) {
|
||||
tryRecover();
|
||||
}
|
||||
continue;
|
||||
@@ -776,7 +839,7 @@ CODESTARTrunInput
|
||||
/*
|
||||
* update journal disk usage before reading the new message.
|
||||
*/
|
||||
- const int e = sd_journal_get_usage(j, (uint64_t *)&statsCounter.diskUsageBytes);
|
||||
+ const int e = sd_journal_get_usage(journalContext.j, (uint64_t *)&statsCounter.diskUsageBytes);
|
||||
if (e < 0) {
|
||||
LogError(-e, RS_RET_ERR, "imjournal: sd_get_usage() failed");
|
||||
}
|
||||
@@ -787,21 +850,12 @@ CODESTARTrunInput
|
||||
}
|
||||
|
||||
count++;
|
||||
-
|
||||
- if ((count % J_PROCESS_PERIOD) == 0) {
|
||||
- /* Give the journal a periodic chance to detect rotated journal files to be cleaned up. */
|
||||
- r = sd_journal_process(j);
|
||||
- if (r < 0) {
|
||||
- LogError(-r, RS_RET_ERR, "imjournal: sd_journal_process() failed");
|
||||
- tryRecover();
|
||||
- continue;
|
||||
- }
|
||||
- }
|
||||
+ journalContext.atHead = 0;
|
||||
|
||||
if (cs.stateFile) { /* can't persist without a state file */
|
||||
/* TODO: This could use some finer metric. */
|
||||
if ((count % cs.iPersistStateInterval) == 0) {
|
||||
- persistJournalState(1);
|
||||
+ persistJournalState();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -825,6 +879,7 @@ CODESTARTbeginCnfLoad
|
||||
cs.usePid = NULL;
|
||||
cs.bWorkAroundJournalBug = 1;
|
||||
cs.bFsync = 0;
|
||||
+ cs.bRemote = 0;
|
||||
ENDbeginCnfLoad
|
||||
|
||||
|
||||
@@ -881,7 +936,7 @@ BEGINfreeCnf
|
||||
CODESTARTfreeCnf
|
||||
free(cs.stateFile);
|
||||
free(cs.usePid);
|
||||
- free(last_cursor);
|
||||
+ free(journalContext.cursor);
|
||||
statsobj.Destruct(&(statsCounter.stats));
|
||||
ENDfreeCnf
|
||||
|
||||
@@ -894,7 +949,10 @@ ENDwillRun
|
||||
/* close journal */
|
||||
BEGINafterRun
|
||||
CODESTARTafterRun
|
||||
- closeJournal(1);
|
||||
+ if (cs.stateFile) { /* can't persist without a state file */
|
||||
+ persistJournalState();
|
||||
+ }
|
||||
+ closeJournal();
|
||||
ratelimitDestruct(ratelimiter);
|
||||
ENDafterRun
|
||||
|
||||
@@ -966,6 +1024,8 @@ CODESTARTsetModCnf
|
||||
cs.bWorkAroundJournalBug = (int) pvals[i].val.d.n;
|
||||
} else if (!strcmp(modpblk.descr[i].name, "fsync")) {
|
||||
cs.bFsync = (int) pvals[i].val.d.n;
|
||||
+ } else if (!strcmp(modpblk.descr[i].name, "remote")) {
|
||||
+ cs.bRemote = (int) pvals[i].val.d.n;
|
||||
} else {
|
||||
dbgprintf("imjournal: program error, non-handled "
|
||||
"param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
|
||||
diff --git a/plugins/imjournal/imjournal.c b/plugins/imjournal/imjournal.c
|
||||
index 8008f159c4..18e4d25ebb 100644
|
||||
--- a/plugins/imjournal/imjournal.c
|
||||
+++ b/plugins/imjournal/imjournal.c
|
||||
@@ -3,7 +3,7 @@
|
||||
* To test under Linux:
|
||||
* emmit log message into systemd journal
|
||||
*
|
||||
- * Copyright (C) 2008-2017 Adiscon GmbH
|
||||
+ * Copyright (C) 2008-2019 Adiscon GmbH
|
||||
*
|
||||
* This file is part of rsyslog.
|
||||
*
|
||||
@@ -676,16 +676,6 @@ loadJournalState(void)
|
||||
DBGPRINTF("Loading journal position, at head? %d, reloaded? %d\n",
|
||||
journalContext.atHead, journalContext.reloaded);
|
||||
|
||||
- if (cs.stateFile[0] != '/') {
|
||||
- char *new_stateFile;
|
||||
- if (-1 == asprintf(&new_stateFile, "%s/%s", (char *)glbl.GetWorkDir(), cs.stateFile)) {
|
||||
- LogError(0, RS_RET_OUT_OF_MEMORY, "imjournal: asprintf failed\n");
|
||||
- ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
|
||||
- }
|
||||
- free (cs.stateFile);
|
||||
- cs.stateFile = new_stateFile;
|
||||
- }
|
||||
-
|
||||
/* if state file not exists (on very first run), skip */
|
||||
if (access(cs.stateFile, F_OK|R_OK) == -1 && errno == ENOENT) {
|
||||
if (cs.bIgnorePrevious) {
|
||||
@@ -885,6 +875,17 @@ ENDbeginCnfLoad
|
||||
|
||||
BEGINendCnfLoad
|
||||
CODESTARTendCnfLoad
|
||||
+ /* bad trick to handle old and new style config all in old-style var */
|
||||
+ if(cs.stateFile != NULL && cs.stateFile[0] != '/') {
|
||||
+ char *new_stateFile;
|
||||
+ if (-1 == asprintf(&new_stateFile, "%s/%s", (char *)glbl.GetWorkDir(), cs.stateFile)) {
|
||||
+ LogError(0, RS_RET_OUT_OF_MEMORY, "imjournal: asprintf failed\n");
|
||||
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
|
||||
+ }
|
||||
+ free (cs.stateFile);
|
||||
+ cs.stateFile = new_stateFile;
|
||||
+ }
|
||||
+finalize_it:
|
||||
ENDendCnfLoad
|
||||
|
||||
|
||||
@@ -1032,7 +1033,6 @@ CODESTARTsetModCnf
|
||||
}
|
||||
}
|
||||
|
||||
-
|
||||
finalize_it:
|
||||
if (pvals != NULL)
|
||||
cnfparamvalsDestruct(pvals, &modpblk);
|
10
rsyslog.spec
10
rsyslog.spec
@ -8,8 +8,8 @@
|
||||
|
||||
Summary: Enhanced system logging and kernel message trapping daemon
|
||||
Name: rsyslog
|
||||
Version: 8.1907.0
|
||||
Release: 2%{?dist}
|
||||
Version: 8.1910.0
|
||||
Release: 1%{?dist}
|
||||
License: (GPLv3+ and ASL 2.0)
|
||||
URL: http://www.rsyslog.com/
|
||||
Source0: http://www.rsyslog.com/files/download/rsyslog/%{name}-%{version}.tar.gz
|
||||
@ -45,6 +45,7 @@ Obsoletes: sysklogd < 1.5-11
|
||||
|
||||
# tweak the upstream service file to honour configuration from /etc/sysconfig/rsyslog
|
||||
Patch0: rsyslog-8.34.0-sd-service.patch
|
||||
Patch1: imjournal-rewrite.patch
|
||||
|
||||
%package crypto
|
||||
Summary: Encryption support
|
||||
@ -246,6 +247,7 @@ mv build doc
|
||||
# set up rsyslog sources
|
||||
%setup -q -D
|
||||
%patch0 -p1
|
||||
%patch1 -p1
|
||||
|
||||
autoreconf -iv
|
||||
|
||||
@ -479,6 +481,10 @@ done
|
||||
%doc %{rsyslog_docdir}/k8s_container_name.rulebase
|
||||
|
||||
%changelog
|
||||
* Thu Oct 17 2019 Jiri Vymazal <jvymazal@redhat.com> - 8.1910.0-1
|
||||
- rebase to upstream version 8.1910.0
|
||||
resolves: rhbz#1743537
|
||||
|
||||
* Fri Jul 26 2019 Fedora Release Engineering <releng@fedoraproject.org> - 8.1907.0-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
|
||||
|
||||
|
4
sources
4
sources
@ -1,2 +1,2 @@
|
||||
SHA512 (rsyslog-8.1907.0.tar.gz) = 2aa3f6106e48fa63c6d4389f83e7a3212817c626d04881682236055792cf5c9d8a941638c9a508c470b6a24c934ef5cb0eda65ea25179d98831afbe2a27c1519
|
||||
SHA512 (rsyslog-doc-8.1907.0.tar.gz) = 72dcddef6e36a92d2bdcf54072fff7516b6c731f43a53ef8f5d4ebdbe46bc7aeb63bbc3e739a6e5897602ea7705c4bdd8f57aa10796955ed772a6c7cf552c5e5
|
||||
SHA512 (rsyslog-8.1910.0.tar.gz) = 85f5df91a6357ecb38708b4d569d26804a50ca28c928a636ac7749595f1a7105c3450fbd521835a436ebdfdcac33a33986e09a09026745ea4d1a2897406770d5
|
||||
SHA512 (rsyslog-doc-8.1910.0.tar.gz) = e46f14e40ae690efbe3114a859c1c94c8f9573ca5ebdb533ad4b5ed76c3a930c887cc205e7279fcc546fda3ce624eae507ce08d5d10ee1eb167a957edd742bf2
|
||||
|
Loading…
Reference in New Issue
Block a user