summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--doc/property_replacer.html4
-rw-r--r--runtime/datetime.c112
-rw-r--r--runtime/datetime.h4
-rw-r--r--runtime/msg.c16
-rw-r--r--runtime/msg.h2
-rw-r--r--runtime/queue.c1
-rw-r--r--template.c5
-rw-r--r--template.h2
9 files changed, 145 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 3d0cfdab..8ac3f62c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
---------------------------------------------------------------------------
Version 6.3.8 [DEVEL] 2012-02-??
+- added "date-unixtimestamp" property replacer option to format as a
+ unix timestamp (seconds since epoch)
- added "json" property replacer option to support JSON encoding on a
per-property basis
- added omhiredis (contributed module)
diff --git a/doc/property_replacer.html b/doc/property_replacer.html
index f0ac3c94..3af56182 100644
--- a/doc/property_replacer.html
+++ b/doc/property_replacer.html
@@ -390,6 +390,10 @@ option when forwarding to remote hosts - they may treat the date as invalid
<td>format as RFC 3339 date</td>
</tr>
<tr>
+<td><b>date-unixtimestamp</b></td>
+<td>format as unix timestamp (seconds since epoch)</td>
+</tr>
+<tr>
<td><b>date-subseconds</b></td>
<td>just the subseconds of a timestamp (always 0 for a low precision timestamp)</td>
</tr>
diff --git a/runtime/datetime.c b/runtime/datetime.c
index d30c6e0b..830c67e3 100644
--- a/runtime/datetime.c
+++ b/runtime/datetime.c
@@ -850,6 +850,117 @@ int formatTimestamp3164(struct syslogTime *ts, char* pBuf, int bBuggyDay)
}
+/**
+ * format a timestamp as a UNIX timestamp; subsecond resolution is
+ * discarded.
+ * Note that this code can use some refactoring. I decided to use it
+ * because mktime() requires an upfront TZ update as it works on local
+ * time. In any case, it is worth reconsidering to move to mktime() or
+ * some other method.
+ * Important: pBuf must point to a buffer of at least 11 bytes.
+ * rgerhards, 2012-03-29
+ */
+int formatTimestampUnix(struct syslogTime *ts, char *pBuf)
+{
+ long MonthInDays, NumberOfYears, NumberOfDays, i;
+ int utcOffset;
+ time_t TimeInUnixFormat;
+
+ /* Counting how many Days have passed since the 01.01 of the
+ * selected Year (Month level), according to the selected Month*/
+
+ switch(ts->month)
+ {
+ case 1:
+ MonthInDays = 0; //until 01 of January
+ break;
+ case 2:
+ MonthInDays = 31; //until 01 of February - leap year handling down below!
+ break;
+ case 3:
+ MonthInDays = 59; //until 01 of March
+ break;
+ case 4:
+ MonthInDays = 90; //until 01 of April
+ break;
+ case 5:
+ MonthInDays = 120; //until 01 of Mai
+ break;
+ case 6:
+ MonthInDays = 151; //until 01 of June
+ break;
+ case 7:
+ MonthInDays = 181; //until 01 of July
+ break;
+ case 8:
+ MonthInDays = 212; //until 01 of August
+ break;
+ case 9:
+ MonthInDays = 243; //until 01 of September
+ break;
+ case 10:
+ MonthInDays = 273; //until 01 of Oktober
+ break;
+ case 11:
+ MonthInDays = 304; //until 01 of November
+ break;
+ case 12:
+ MonthInDays = 334; //until 01 of December
+ break;
+ }
+
+
+ /* 1) Counting how many Years have passed since 1970
+ 2) Counting how many Days have passed since the 01.01 of the selected Year
+ (Day level) according to the Selected Month and Day. Last day doesn't count,
+ it should be until last day
+ 3) Calculating this period (NumberOfDays) in seconds*/
+
+ NumberOfYears = ts->year - 1970;
+ NumberOfDays = MonthInDays + ts->day - 1;
+ TimeInUnixFormat = NumberOfYears * 31536000 + NumberOfDays * 86400;
+
+ /* Now we need to adjust the number of years for leap
+ * year processing. If we are in Jan or Feb, this year
+ * will never be considered - because we haven't arrived
+ * at then end of Feb right now. [Feb, 29th in a leap year
+ * is handled correctly, because the day (29) is correctly
+ * added to the date serial]
+ */
+ if(ts->month < 3)
+ NumberOfYears--;
+
+ /*...AND ADDING ONE DAY FOR EACH YEAR WITH 366 DAYS
+ * note that we do not handle 2000 any special, as it was a
+ * leap year. The current code works OK until 2100, when it will
+ * break. As we do not process future dates, we accept that fate...
+ * the whole thing could be refactored by a table-based approach.
+ */
+ for(i = 1;i <= NumberOfYears; i++)
+ {
+ /* If i = 2 we have 1972, which was a Year with 366 Days
+ and if (i + 2) Mod (4) = 0 we have a Year after 1972
+ which is also a Year with 366 Days (repeated every 4 Years) */
+ if ((i == 2) || (((i + 2) % 4) == 0))
+ { /*Year with 366 Days!!!*/
+ TimeInUnixFormat += 86400;
+ }
+ }
+
+ /*Add Hours, minutes and seconds */
+ TimeInUnixFormat += ts->hour*60*60;
+ TimeInUnixFormat += ts->minute*60;
+ TimeInUnixFormat += ts->second;
+ /* do UTC offset */
+ utcOffset = ts->OffsetHour*3600 + ts->OffsetMinute*60;
+ if(ts->OffsetMode == '+')
+ utcOffset *= -1; /* if timestamp is ahead, we need to "go back" to UTC */
+ TimeInUnixFormat += utcOffset;
+ snprintf(pBuf, 11, "%u", (unsigned) TimeInUnixFormat);
+ return 11;
+}
+
+
/* queryInterface function
* rgerhards, 2008-03-05
*/
@@ -874,6 +985,7 @@ CODESTARTobjQueryInterface(datetime)
pIf->formatTimestampSecFrac = formatTimestampSecFrac;
pIf->formatTimestamp3339 = formatTimestamp3339;
pIf->formatTimestamp3164 = formatTimestamp3164;
+ pIf->formatTimestampUnix = formatTimestampUnix;
finalize_it:
ENDobjQueryInterface(datetime)
diff --git a/runtime/datetime.h b/runtime/datetime.h
index acf54df5..bb5e5292 100644
--- a/runtime/datetime.h
+++ b/runtime/datetime.h
@@ -44,8 +44,10 @@ BEGINinterface(datetime) /* name must also be changed in ENDinterface macro! */
time_t (*GetTime)(time_t *ttSeconds);
/* v6, 2011-06-20 */
void (*timeval2syslogTime)(struct timeval *tp, struct syslogTime *t);
+ /* v7, 2012-03-29 */
+ int (*formatTimestampUnix)(struct syslogTime *ts, char*pBuf);
ENDinterface(datetime)
-#define datetimeCURR_IF_VERSION 6 /* increment whenever you change the interface structure! */
+#define datetimeCURR_IF_VERSION 7 /* increment whenever you change the interface structure! */
/* interface changes:
* 1 - initial version
* 2 - not compatible to 1 - bugfix required ParseTIMESTAMP3164 to accept char ** as
diff --git a/runtime/msg.c b/runtime/msg.c
index 548afb15..8f92565a 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -737,6 +737,8 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis)
pM->pszTimestamp3339[0] = '\0';
pM->pszTIMESTAMP_SecFrac[0] = '\0';
pM->pszRcvdAt_SecFrac[0] = '\0';
+ pM->pszTIMESTAMP_Unix[0] = '\0';
+ pM->pszRcvdAt_Unix[0] = '\0';
/* DEV debugging only! dbgprintf("msgConstruct\t0x%x, ref 1\n", (int)pM);*/
@@ -1337,6 +1339,13 @@ getTimeReported(msg_t *pM, enum tplFormatTypes eFmt)
}
MsgUnlock(pM);
return(pM->pszTIMESTAMP3339);
+ case tplFmtUnixDate:
+ MsgLock(pM);
+ if(pM->pszTIMESTAMP_Unix[0] == '\0') {
+ datetime.formatTimestampUnix(&pM->tTIMESTAMP, pM->pszTIMESTAMP_Unix);
+ }
+ MsgUnlock(pM);
+ return(pM->pszTIMESTAMP_Unix);
case tplFmtSecFrac:
if(pM->pszTIMESTAMP_SecFrac[0] == '\0') {
MsgLock(pM);
@@ -1416,6 +1425,13 @@ static inline char *getTimeGenerated(msg_t *pM, enum tplFormatTypes eFmt)
}
MsgUnlock(pM);
return(pM->pszRcvdAt3339);
+ case tplFmtUnixDate:
+ MsgLock(pM);
+ if(pM->pszRcvdAt_Unix[0] == '\0') {
+ datetime.formatTimestampUnix(&pM->tRcvdAt, pM->pszRcvdAt_Unix);
+ }
+ MsgUnlock(pM);
+ return(pM->pszRcvdAt_Unix);
case tplFmtSecFrac:
if(pM->pszRcvdAt_SecFrac[0] == '\0') {
MsgLock(pM);
diff --git a/runtime/msg.h b/runtime/msg.h
index 4c209b8f..ed2e9d04 100644
--- a/runtime/msg.h
+++ b/runtime/msg.h
@@ -121,6 +121,8 @@ struct msg {
char pszTimestamp3339[CONST_LEN_TIMESTAMP_3339 + 1];
char pszTIMESTAMP_SecFrac[7]; /* Note: a pointer is 64 bits/8 char, so this is actually fewer than a pointer! */
char pszRcvdAt_SecFrac[7]; /* same as above. Both are fractional seconds for their respective timestamp */
+ char pszTIMESTAMP_Unix[12]; /* almost as small as a pointer! */
+ char pszRcvdAt_Unix[12];
};
diff --git a/runtime/queue.c b/runtime/queue.c
index 5acf5f02..cd64b1fc 100644
--- a/runtime/queue.c
+++ b/runtime/queue.c
@@ -1933,7 +1933,6 @@ qqueueStart(qqueue_t *pThis) /* this is the ConstructionFinalizer */
int wrk;
uchar *qName;
size_t lenBuf;
- int iQueueSizeSave;
ASSERT(pThis != NULL);
diff --git a/template.c b/template.c
index bcdcc367..2326819c 100644
--- a/template.c
+++ b/template.c
@@ -521,6 +521,8 @@ static void doOptions(unsigned char **pp, struct templateEntry *pTpe)
pTpe->data.field.eDateFormat = tplFmtRFC3164BuggyDate;
} else if(!strcmp((char*)Buf, "date-rfc3339")) {
pTpe->data.field.eDateFormat = tplFmtRFC3339Date;
+ } else if(!strcmp((char*)Buf, "date-unixtimestamp")) {
+ pTpe->data.field.eDateFormat = tplFmtUnixDate;
} else if(!strcmp((char*)Buf, "date-subseconds")) {
pTpe->data.field.eDateFormat = tplFmtSecFrac;
} else if(!strcmp((char*)Buf, "lowercase")) {
@@ -1258,6 +1260,9 @@ void tplPrintList(rsconf_t *conf)
case tplFmtRFC3339Date:
dbgprintf("[Format as RFC3339-Date] ");
break;
+ case tplFmtUnixDate:
+ dbgprintf("[Format as Unix timestamp] ");
+ break;
default:
dbgprintf("[INVALID eDateFormat %d] ", pTpe->data.field.eDateFormat);
}
diff --git a/template.h b/template.h
index b2cef271..a9eff6b1 100644
--- a/template.h
+++ b/template.h
@@ -51,7 +51,7 @@ struct template {
enum EntryTypes { UNDEFINED = 0, CONSTANT = 1, FIELD = 2 };
enum tplFormatTypes { tplFmtDefault = 0, tplFmtMySQLDate = 1,
tplFmtRFC3164Date = 2, tplFmtRFC3339Date = 3, tplFmtPgSQLDate = 4,
- tplFmtSecFrac = 5, tplFmtRFC3164BuggyDate = 6};
+ tplFmtSecFrac = 5, tplFmtRFC3164BuggyDate = 6, tplFmtUnixDate};
enum tplFormatCaseConvTypes { tplCaseConvNo = 0, tplCaseConvUpper = 1, tplCaseConvLower = 2 };
#include "msg.h"