summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-06-06 17:33:58 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2008-06-06 17:33:58 +0200
commit2687d0010ca0ec691235a69c9da021719b61e8cd (patch)
treed8275d258253ed44fce7d163b2f5f1448fd8a7d4
parent6343cf730acbb454765d0593d68032aebcb3d15c (diff)
downloadrsyslog-2687d0010ca0ec691235a69c9da021719b61e8cd.tar.gz
rsyslog-2687d0010ca0ec691235a69c9da021719b61e8cd.tar.xz
rsyslog-2687d0010ca0ec691235a69c9da021719b61e8cd.zip
added new property replacer option "time-subseconds"
enables to query just the subsecond part of a high-precision timestamp
-rw-r--r--ChangeLog2
-rw-r--r--doc/property_replacer.html4
-rw-r--r--runtime/datetime.c40
-rw-r--r--runtime/datetime.h3
-rw-r--r--runtime/msg.c26
-rw-r--r--runtime/msg.h2
-rw-r--r--template.c2
-rw-r--r--template.h3
8 files changed, 80 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 3e68d990..e193e83b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
---------------------------------------------------------------------------
Version 3.19.7 (rgerhards), 2008-06-??
+- added new property replacer option "time-subseconds" that enables
+ to query just the subsecond part of a high-precision timestamp
---------------------------------------------------------------------------
Version 3.19.6 (rgerhards), 2008-06-06
- enhanced property replacer to support multiple regex matches
diff --git a/doc/property_replacer.html b/doc/property_replacer.html
index 86d28274..2675e8fb 100644
--- a/doc/property_replacer.html
+++ b/doc/property_replacer.html
@@ -284,6 +284,10 @@ Especially useful for PIX.</td>
<td>format as RFC 3339 date</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>
+<tr>
<td><b>escape-cc</b></td>
<td>replace control characters (ASCII value 127 and values
less then 32) with an escape sequence. The sequnce is
diff --git a/runtime/datetime.c b/runtime/datetime.c
index d72cac3c..5211b78a 100644
--- a/runtime/datetime.c
+++ b/runtime/datetime.c
@@ -492,6 +492,45 @@ int formatTimestampToPgSQL(struct syslogTime *ts, char *pDst, size_t iLenDst)
ts->year, ts->month, ts->day, ts->hour, ts->minute, ts->second));
}
+
+/**
+ * Format a syslogTimestamp to just the fractional seconds.
+ * The caller must provide the timestamp as well as a character
+ * buffer that will receive the resulting string. The function
+ * returns the size of the timestamp written in bytes (without
+ * the string terminator). If 0 is returend, an error occured.
+ * The buffer must be at least 10 bytes large.
+ * rgerhards, 2008-06-06
+ */
+int formatTimestampSecFrac(struct syslogTime *ts, char* pBuf, size_t iLenBuf)
+{
+ int lenRet;
+ char szFmtStr[64];
+
+ assert(ts != NULL);
+ assert(pBuf != NULL);
+ assert(iLenBuf >= 10);
+
+ if(ts->secfracPrecision > 0)
+ { /* We must look at
+ * the precision specified. For example, if we have millisec precision (3 digits), a
+ * secFrac value of 12 is not equivalent to ".12" but ".012". Obviously, this
+ * is a huge difference ;). To avoid this, we first create a format string with
+ * the specific precision and *then* use that format string to do the actual formating.
+ */
+ /* be careful: there is ONE actual %d in the format string below ;) */
+ snprintf(szFmtStr, sizeof(szFmtStr), "%%0%dd", ts->secfracPrecision);
+ lenRet = snprintf(pBuf, iLenBuf, szFmtStr, ts->secfrac);
+ } else {
+ pBuf[0] = '0';
+ pBuf[1] = '1';
+ lenRet = 1;
+ }
+
+ return(lenRet);
+}
+
+
/**
* Format a syslogTimestamp to a RFC3339 timestamp string (as
* specified in syslog-protocol).
@@ -610,6 +649,7 @@ CODESTARTobjQueryInterface(datetime)
pIf->ParseTIMESTAMP3164 = ParseTIMESTAMP3164;
pIf->formatTimestampToMySQL = formatTimestampToMySQL;
pIf->formatTimestampToPgSQL = formatTimestampToPgSQL;
+ pIf->formatTimestampSecFrac = formatTimestampSecFrac;
pIf->formatTimestamp3339 = formatTimestamp3339;
pIf->formatTimestamp3164 = formatTimestamp3164;
finalize_it:
diff --git a/runtime/datetime.h b/runtime/datetime.h
index fcb78172..1012ccc1 100644
--- a/runtime/datetime.h
+++ b/runtime/datetime.h
@@ -43,8 +43,9 @@ BEGINinterface(datetime) /* name must also be changed in ENDinterface macro! */
int (*formatTimestampToPgSQL)(struct syslogTime *ts, char *pDst, size_t iLenDst);
int (*formatTimestamp3339)(struct syslogTime *ts, char* pBuf, size_t iLenBuf);
int (*formatTimestamp3164)(struct syslogTime *ts, char* pBuf, size_t iLenBuf);
+ int (*formatTimestampSecFrac)(struct syslogTime *ts, char* pBuf, size_t iLenBuf);
ENDinterface(datetime)
-#define datetimeCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+#define datetimeCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */
/* prototypes */
PROTOTYPEObj(datetime);
diff --git a/runtime/msg.c b/runtime/msg.c
index f195d3bd..e2d0b54c 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -279,6 +279,8 @@ CODESTARTobjDestruct(msg)
free(pThis->pszRcvdAt3164);
if(pThis->pszRcvdAt3339 != NULL)
free(pThis->pszRcvdAt3339);
+ if(pThis->pszRcvdAt_SecFrac != NULL)
+ free(pThis->pszRcvdAt_SecFrac);
if(pThis->pszRcvdAt_MySQL != NULL)
free(pThis->pszRcvdAt_MySQL);
if(pThis->pszRcvdAt_PgSQL != NULL)
@@ -287,6 +289,8 @@ CODESTARTobjDestruct(msg)
free(pThis->pszTIMESTAMP3164);
if(pThis->pszTIMESTAMP3339 != NULL)
free(pThis->pszTIMESTAMP3339);
+ if(pThis->pszTIMESTAMP_SecFrac != NULL)
+ free(pThis->pszTIMESTAMP_SecFrac);
if(pThis->pszTIMESTAMP_MySQL != NULL)
free(pThis->pszTIMESTAMP_MySQL);
if(pThis->pszTIMESTAMP_PgSQL != NULL)
@@ -738,6 +742,17 @@ char *getTimeReported(msg_t *pM, enum tplFormatTypes eFmt)
}
MsgUnlock(pM);
return(pM->pszTIMESTAMP3339);
+ case tplFmtSecFrac:
+ MsgLock(pM);
+ if(pM->pszTIMESTAMP_SecFrac == NULL) {
+ if((pM->pszTIMESTAMP_SecFrac = malloc(10)) == NULL) {
+ MsgUnlock(pM);
+ return ""; /* TODO: check this: can it cause a free() of constant memory?) */
+ }
+ datetime.formatTimestampSecFrac(&pM->tTIMESTAMP, pM->pszTIMESTAMP3339, 10);
+ }
+ MsgUnlock(pM);
+ return(pM->pszTIMESTAMP_SecFrac);
}
return "INVALID eFmt OPTION!";
}
@@ -803,6 +818,17 @@ char *getTimeGenerated(msg_t *pM, enum tplFormatTypes eFmt)
}
MsgUnlock(pM);
return(pM->pszRcvdAt3339);
+ case tplFmtSecFrac:
+ MsgLock(pM);
+ if(pM->pszRcvdAt_SecFrac == NULL) {
+ if((pM->pszRcvdAt_SecFrac = malloc(10)) == NULL) {
+ MsgUnlock(pM);
+ return ""; /* TODO: check this: can it cause a free() of constant memory?) */
+ }
+ datetime.formatTimestampSecFrac(&pM->tRcvdAt, pM->pszRcvdAt_SecFrac, 10);
+ }
+ MsgUnlock(pM);
+ return(pM->pszRcvdAt_SecFrac);
}
return "INVALID eFmt OPTION!";
}
diff --git a/runtime/msg.h b/runtime/msg.h
index 084123b7..c428237a 100644
--- a/runtime/msg.h
+++ b/runtime/msg.h
@@ -100,6 +100,7 @@ struct msg {
struct syslogTime tRcvdAt;/* time the message entered this program */
char *pszRcvdAt3164; /* time as RFC3164 formatted string (always 15 charcters) */
char *pszRcvdAt3339; /* time as RFC3164 formatted string (32 charcters at most) */
+ char *pszRcvdAt_SecFrac;/* time just as fractional seconds (6 charcters) */
char *pszRcvdAt_MySQL; /* rcvdAt as MySQL formatted string (always 14 charcters) */
char *pszRcvdAt_PgSQL; /* rcvdAt as PgSQL formatted string (always 21 characters) */
struct syslogTime tTIMESTAMP;/* (parsed) value of the timestamp */
@@ -107,6 +108,7 @@ struct msg {
char *pszTIMESTAMP3339; /* TIMESTAMP as RFC3339 formatted string (32 charcters at most) */
char *pszTIMESTAMP_MySQL;/* TIMESTAMP as MySQL formatted string (always 14 charcters) */
char *pszTIMESTAMP_PgSQL;/* TIMESTAMP as PgSQL formatted string (always 21 characters) */
+ char *pszTIMESTAMP_SecFrac;/* TIMESTAMP fractional seconds (always 6 characters) */
int msgFlags; /* flags associated with this message */
};
diff --git a/template.c b/template.c
index e85be4be..524789bd 100644
--- a/template.c
+++ b/template.c
@@ -440,6 +440,8 @@ static void doOptions(unsigned char **pp, struct templateEntry *pTpe)
pTpe->data.field.eDateFormat = tplFmtRFC3164Date;
} else if(!strcmp((char*)Buf, "date-rfc3339")) {
pTpe->data.field.eDateFormat = tplFmtRFC3339Date;
+ } else if(!strcmp((char*)Buf, "date-subseconds")) {
+ pTpe->data.field.eDateFormat = tplFmtSecFrac;
} else if(!strcmp((char*)Buf, "lowercase")) {
pTpe->data.field.eCaseConv = tplCaseConvLower;
} else if(!strcmp((char*)Buf, "uppercase")) {
diff --git a/template.h b/template.h
index baf33d4e..3f35ebca 100644
--- a/template.h
+++ b/template.h
@@ -47,7 +47,8 @@ struct template {
enum EntryTypes { UNDEFINED = 0, CONSTANT = 1, FIELD = 2 };
enum tplFormatTypes { tplFmtDefault = 0, tplFmtMySQLDate = 1,
- tplFmtRFC3164Date = 2, tplFmtRFC3339Date = 3, tplFmtPgSQLDate = 4 };
+ tplFmtRFC3164Date = 2, tplFmtRFC3339Date = 3, tplFmtPgSQLDate = 4,
+ tplFmtSecFrac = 5};
enum tplFormatCaseConvTypes { tplCaseConvNo = 0, tplCaseConvUpper = 1, tplCaseConvLower = 2 };
#include "msg.h"