Merge branch 'master-integrate-dynstats' into master-candidate

Conflicts:
	.travis.yml
This commit is contained in:
Rainer Gerhards 2016-01-29 15:45:11 +01:00
commit 98463ed482
42 changed files with 1339 additions and 34 deletions

View File

@ -53,7 +53,7 @@ script:
# I set the second one here via an "if"
- if [ "x$GROK" == "xYES" ]; then export GROK="--enable-mmgrok"; fi
- if [ "$CC" == "clang" ]; then export NO_VALGRIND="--without-valgrind-testbench"; fi
- ./configure --prefix=/opt/rsyslog --build=x86_64-pc-linux-gnu --host=x86_64-pc-linux-gnu --mandir=/usr/share/man --infodir=/usr/share/info --datadir=/usr/share --sysconfdir=/etc --localstatedir=/var/lib --disable-dependency-tracking --enable-silent-rules --libdir=/usr/lib64 --docdir=/usr/share/doc/rsyslog --disable-generate-man-pages --enable-testbench --enable-imdiag --enable-imfile --enable-impstats --enable-imptcp --enable-mmanon --enable-mmaudit --enable-mmfields --enable-mmjsonparse --enable-mmpstrucdata --enable-mmsequence --enable-mmutf8fix --enable-mail --enable-omprog --enable-omruleset --enable-omstdout --enable-omuxsock --enable-pmaixforwardedfrom --enable-pmciscoios --enable-pmcisconames --enable-pmlastmsg --enable-pmsnare --enable-libgcrypt --enable-mmnormalize --disable-omudpspoof --enable-relp --disable-snmp --disable-mmsnmptrapd --enable-gnutls --enable-mysql --enable-gt-ksi --enable-libdbi --enable-pgsql --enable-omhttpfs --enable-elasticsearch $NO_VALGRIND $GROK
- ./configure --prefix=/opt/rsyslog --build=x86_64-pc-linux-gnu --host=x86_64-pc-linux-gnu --mandir=/usr/share/man --infodir=/usr/share/info --datadir=/usr/share --sysconfdir=/etc --localstatedir=/var/lib --disable-dependency-tracking --enable-silent-rules --libdir=/usr/lib64 --docdir=/usr/share/doc/rsyslog --disable-generate-man-pages --enable-testbench --enable-imdiag --enable-imfile --enable-impstats --enable-imptcp --enable-mmanon --enable-mmaudit --enable-mmfields --enable-mmjsonparse --enable-mmpstrucdata --enable-mmsequence --enable-mmutf8fix --enable-mail --enable-omprog --enable-omruleset --enable-omstdout --enable-omuxsock --enable-pmaixforwardedfrom --enable-pmciscoios --enable-pmcisconames --enable-pmlastmsg --enable-pmsnare --enable-libgcrypt --enable-mmnormalize --disable-omudpspoof --enable-relp --disable-snmp --disable-mmsnmptrapd --enable-gnutls --enable-mysql --enable-gt-ksi --enable-libdbi --enable-pgsql --enable-omhttpfs --enable-elasticsearch --enable-valgrind $NO_VALGRIND $GROK
- export USE_AUTO_DEBUG="off" # set to "on" to enable this for travis
- make
- if [ "x$CHECK" == "xYES" ] ; then make check ; fi

View File

@ -296,6 +296,14 @@ AC_CHECK_HEADERS(
[AC_MSG_FAILURE([pthread is missing])]
)
AC_CHECK_LIB(
[pthread],
[pthread_rwlockattr_setkind_np],
[AC_DEFINE(
[HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP],
[1],
[Set-kind available for rwlock attr.])])
AC_CHECK_FUNCS(
[pthread_setschedparam],
[

View File

@ -211,6 +211,8 @@ int fileno(FILE *stream);
BEGIN INOBJ; return BEGINOBJ; }
"lookup_table"[ \n\t]*"(" { yylval.objType = CNFOBJ_LOOKUP_TABLE;
BEGIN INOBJ; return BEGINOBJ; }
"dyn_stats"[ \n\t]*"(" { yylval.objType = CNFOBJ_DYN_STATS;
BEGIN INOBJ; return BEGINOBJ; }
"action"[ \n\t]*"(" { BEGIN INOBJ; return BEGIN_ACTION; }
^[ \t]*:\$?[a-z\-]+[ ]*,[ ]*!?[a-z]+[ ]*,[ ]*\"(\\\"|[^\"])*\" {
yylval.s = strdup(rmLeadingSpace(yytext));

View File

@ -1327,6 +1327,7 @@ static rsRetVal
doExtractFieldByChar(uchar *str, uchar delim, const int matchnbr, uchar **resstr)
{
int iCurrFld;
int allocLen;
int iLen;
uchar *pBuf;
uchar *pFld;
@ -1357,7 +1358,12 @@ doExtractFieldByChar(uchar *str, uchar delim, const int matchnbr, uchar **resstr
* step back a little not to copy it as part of the field. */
/* we got our end pointer, now do the copy */
iLen = pFldEnd - pFld + 1; /* the +1 is for an actual char, NOT \0! */
CHKmalloc(pBuf = MALLOC(iLen + 1));
allocLen = iLen + 1;
# ifdef VALGRIND
allocLen += (3 - (iLen % 4));
/*older versions of valgrind have a problem with strlen inspecting 4-bytes at a time*/
# endif
CHKmalloc(pBuf = MALLOC(allocLen));
/* now copy */
memcpy(pBuf, pFld, iLen);
pBuf[iLen] = '\0'; /* terminate it */
@ -1834,6 +1840,18 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct var *__restrict__ con
if(bMustFree) free(str);
varFreeMembers(&r[1]);
break;
case CNFFUNC_DYN_INC:
ret->datatype = 'N';
if(func->funcdata == NULL) {
ret->d.n = -1;
break;
}
cnfexprEval(func->expr[1], &r[1], usrptr);
str = (char*) var2CString(&r[1], &bMustFree);
ret->d.n = dynstats_inc(func->funcdata, (uchar*)str);
if(bMustFree) free(str);
varFreeMembers(&r[1]);
break;
default:
if(Debug) {
char *fname = es_str2cstr(func->fname, NULL);
@ -2485,7 +2503,7 @@ cnffuncDestruct(struct cnffunc *func)
break;
default:break;
}
if(func->fID != CNFFUNC_EXEC_TEMPLATE)
if(func->fID != CNFFUNC_EXEC_TEMPLATE && func->fID != CNFFUNC_DYN_INC)
free(func->funcdata);
free(func->fname);
}
@ -3785,6 +3803,8 @@ funcName2ID(es_str_t *fname, unsigned short nParams)
GENERATE_FUNC("prifilt", 1, CNFFUNC_PRIFILT);
} else if(FUNC_NAME("lookup")) {
GENERATE_FUNC("lookup", 2, CNFFUNC_LOOKUP);
} else if(FUNC_NAME("dyn_inc")) {
GENERATE_FUNC("dyn_inc", 2, CNFFUNC_DYN_INC);
} else if(FUNC_NAME("replace")) {
GENERATE_FUNC_WITH_ERR_MSG(
"replace", 3, CNFFUNC_REPLACE,
@ -3935,6 +3955,34 @@ finalize_it:
RETiRet;
}
static inline rsRetVal
initFunc_dyn_stats(struct cnffunc *func)
{
uchar *cstr = NULL;
DEFiRet;
if(func->nParams != 2) {
parser_errmsg("rsyslog logic error in line %d of file %s\n",
__LINE__, __FILE__);
FINALIZE;
}
func->funcdata = NULL;
if(func->expr[0]->nodetype != 'S') {
parser_errmsg("dyn-stats bucket-name (param 1) of dyn-stats manipulating functions like dyn_inc must be a constant string");
FINALIZE;
}
cstr = (uchar*)es_str2cstr(((struct cnfstringval*) func->expr[0])->estr, NULL);
if((func->funcdata = dynstats_findBucket(cstr)) == NULL) {
parser_errmsg("dyn-stats bucket '%s' not found", cstr);
FINALIZE;
}
finalize_it:
free(cstr);
RETiRet;
}
struct cnffunc *
cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst)
@ -3979,6 +4027,9 @@ cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst)
case CNFFUNC_EXEC_TEMPLATE:
initFunc_exec_template(func);
break;
case CNFFUNC_DYN_INC:
initFunc_dyn_stats(func);
break;
default:break;
}
}

View File

@ -46,6 +46,7 @@ enum cnfobjType {
CNFOBJ_LOOKUP_TABLE,
CNFOBJ_PARSER,
CNFOBJ_TIMEZONE,
CNFOBJ_DYN_STATS,
CNFOBJ_INVALID = 0
};
@ -81,6 +82,8 @@ cnfobjType2str(enum cnfobjType ot)
return "main_queue";
case CNFOBJ_LOOKUP_TABLE:
return "lookup_table";
case CNFOBJ_DYN_STATS:
return "dyn_stats";
break;
default:return "error: invalid cnfobjType";
}
@ -272,7 +275,8 @@ enum cnffuncid {
CNFFUNC_EXEC_TEMPLATE,
CNFFUNC_REPLACE,
CNFFUNC_WRAP,
CNFFUNC_RANDOM
CNFFUNC_RANDOM,
CNFFUNC_DYN_INC
};
struct cnffunc {

View File

@ -195,21 +195,16 @@ finalize_it:
RETiRet;
}
/* actually submit a message to the rsyslog core
/* submit a generated numeric-suffix message to the rsyslog core
*/
static rsRetVal
doInjectMsg(int iNum, ratelimit_t *ratelimiter)
doInjectMsg(uchar *szMsg, ratelimit_t *ratelimiter)
{
uchar szMsg[1024];
msg_t *pMsg;
struct syslogTime stTime;
time_t ttGenTime;
DEFiRet;
snprintf((char*)szMsg, sizeof(szMsg),
"<167>Mar 1 01:00:00 172.20.245.8 tag msgnum:%8.8d:", iNum);
datetime.getCurrTime(&stTime, &ttGenTime, TIME_IN_LOCALTIME);
/* we now create our own message object and submit it to the queue */
CHKiRet(msgConstructWithTime(&pMsg, &stTime, ttGenTime));
@ -225,6 +220,19 @@ finalize_it:
RETiRet;
}
/* submit a generated numeric-suffix message to the rsyslog core
*/
static rsRetVal
doInjectNumericSuffixMsg(int iNum, ratelimit_t *ratelimiter)
{
uchar szMsg[1024];
DEFiRet;
snprintf((char*)szMsg, sizeof(szMsg)/sizeof(uchar),
"<167>Mar 1 01:00:00 172.20.245.8 tag msgnum:%8.8d:", iNum);
CHKiRet(doInjectMsg(szMsg, ratelimiter));
finalize_it:
RETiRet;
}
/* This function injects messages. Command format:
* injectmsg <fromnbr> <number-of-messages>
@ -234,29 +242,38 @@ static rsRetVal
injectMsg(uchar *pszCmd, tcps_sess_t *pSess)
{
uchar wordBuf[1024];
int iFrom;
int nMsgs;
int iFrom, nMsgs;
uchar *litteralMsg;
int i;
ratelimit_t *ratelimit = NULL;
DEFiRet;
litteralMsg = NULL;
CHKiRet(ratelimitNew(&ratelimit, "imdiag", "injectmsg"));
/* we do not check errors here! */
getFirstWord(&pszCmd, wordBuf, sizeof(wordBuf), TO_LOWERCASE);
if (ustrcmp(UCHAR_CONSTANT("litteral"), wordBuf) == 0) {
/* user has provided content for a message */
++pszCmd; /* ignore following space */
CHKiRet(doInjectMsg(pszCmd, ratelimit));
nMsgs = 1;
} else { /* assume 2 args, (from_idx, to_idx) */
iFrom = atoi((char*)wordBuf);
getFirstWord(&pszCmd, wordBuf, sizeof(wordBuf), TO_LOWERCASE);
nMsgs = atoi((char*)wordBuf);
CHKiRet(ratelimitNew(&ratelimit, "imdiag", "injectmsg"));
for(i = 0 ; i < nMsgs ; ++i) {
doInjectMsg(i + iFrom, ratelimit);
CHKiRet(doInjectNumericSuffixMsg(i + iFrom, ratelimit));
}
}
CHKiRet(sendResponse(pSess, "%d messages injected\n", nMsgs));
DBGPRINTF("imdiag: %d messages injected\n", nMsgs);
finalize_it:
if(ratelimit != NULL)
ratelimitDestruct(ratelimit);
free(litteralMsg);
RETiRet;
}

View File

@ -470,6 +470,7 @@ CODESTARTfreeCnf
if(runModConf->logfd != -1)
close(runModConf->logfd);
free(runModConf->logfile);
free(runModConf->pszBindRuleset);
ENDfreeCnf

View File

@ -152,7 +152,7 @@ BEGINparse2
long long msgcounter;
int lenMsg;
int i;
int iHostname;
int iHostname = 0;
uchar bufParseTAG[512];
uchar bufParseHOSTNAME[CONF_HOSTNAME_MAXSIZE]; /* used by origin */
CODESTARTparse2

View File

@ -55,6 +55,9 @@ librsyslog_la_SOURCES = \
modules.h \
statsobj.c \
statsobj.h \
dynstats.c \
dynstats.h \
statsobj.h \
stream.c \
stream.h \
var.c \

View File

@ -194,6 +194,7 @@
*/
#ifdef HAVE_ATOMIC_BUILTINS64
# define ATOMIC_INC_uint64(data, phlpmut) ((void) __sync_fetch_and_add(data, 1))
# define ATOMIC_ADD_uint64(data, phlpmut, value) ((void) __sync_fetch_and_add(data, value))
# define ATOMIC_DEC_unit64(data, phlpmut) ((void) __sync_sub_and_fetch(data, 1))
# define ATOMIC_INC_AND_FETCH_uint64(data, phlpmut) __sync_fetch_and_add(data, 1)
@ -206,6 +207,11 @@
++(*(data)); \
pthread_mutex_unlock(phlpmut); \
}
# define ATOMIC_ADD_uint64(data, phlpmut, value) { \
pthread_mutex_lock(phlpmut); \
*data += value; \
pthread_mutex_unlock(phlpmut); \
}
# define ATOMIC_DEC_uint64(data, phlpmut) { \
pthread_mutex_lock(phlpmut); \
--(*(data)); \

524
runtime/dynstats.c Normal file
View File

@ -0,0 +1,524 @@
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <assert.h>
#include "rsyslog.h"
#include "srUtils.h"
#include "errmsg.h"
#include "rsconf.h"
#include "unicode-helper.h"
/* definitions for objects we access */
DEFobjStaticHelpers
DEFobjCurrIf(errmsg)
DEFobjCurrIf(statsobj)
#define DYNSTATS_PARAM_NAME "name"
#define DYNSTATS_PARAM_RESETTABLE "resettable"
#define DYNSTATS_PARAM_MAX_CARDINALITY "maxCardinality"
#define DYNSTATS_PARAM_UNUSED_METRIC_LIFE "unusedMetricLife" /* in seconds */
#define DYNSTATS_DEFAULT_RESETTABILITY 1
#define DYNSTATS_DEFAULT_MAX_CARDINALITY 2000
#define DYNSTATS_DEFAULT_UNUSED_METRIC_LIFE 3600 /* seconds */
#define DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH 100
#define DYNSTATS_METRIC_NAME_SEPARATOR '.'
#define DYNSTATS_HASHTABLE_SIZE_OVERPROVISIONING 1.25
static struct cnfparamdescr modpdescr[] = {
{ DYNSTATS_PARAM_NAME, eCmdHdlrString, CNFPARAM_REQUIRED },
{ DYNSTATS_PARAM_RESETTABLE, eCmdHdlrBinary, 0 },
{ DYNSTATS_PARAM_MAX_CARDINALITY, eCmdHdlrPositiveInt, 0},
{ DYNSTATS_PARAM_UNUSED_METRIC_LIFE, eCmdHdlrPositiveInt, 0} /* in minutes */
};
static struct cnfparamblk modpblk =
{ CNFPARAMBLK_VERSION,
sizeof(modpdescr)/sizeof(struct cnfparamdescr),
modpdescr
};
rsRetVal
dynstatsClassInit(void) {
DEFiRet;
CHKiRet(objGetObjInterface(&obj));
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(statsobj, CORE_COMPONENT));
finalize_it:
RETiRet;
}
static inline void
dynstats_destroyCtr(dynstats_bucket_t *b, dynstats_ctr_t *ctr, uint8_t destructStatsCtr) {
if (destructStatsCtr) {
statsobj.DestructCounter(b->stats, ctr->pCtr);
}
free(ctr->metric);
free(ctr);
}
static inline void /* assumes exclusive access to bucket */
dynstats_destroyCounters(dynstats_bucket_t *b) {
dynstats_ctr_t *ctr;
hashtable_destroy(b->table, 0);
statsobj.DestructAllCounters(b->stats);
while(1) {
ctr = b->ctrs;
if (ctr == NULL) {
break;
} else {
b->ctrs = ctr->next;
dynstats_destroyCtr(b, ctr, 0);
}
}
STATSCOUNTER_BUMP(b->ctrMetricsPurged, b->mutCtrMetricsPurged, b->metricCount);
}
void
dynstats_destroyBucket(dynstats_bucket_t* b) {
dynstats_buckets_t *bkts;
bkts = &loadConf->dynstats_buckets;
pthread_rwlock_wrlock(&b->lock);
dynstats_destroyCounters(b);
statsobj.Destruct(&b->stats);
free(b->name);
pthread_rwlock_unlock(&b->lock);
pthread_rwlock_destroy(&b->lock);
pthread_mutex_destroy(&b->mutMetricCount);
statsobj.DestructCounter(bkts->global_stats, b->pOpsOverflowCtr);
statsobj.DestructCounter(bkts->global_stats, b->pNewMetricAddCtr);
statsobj.DestructCounter(bkts->global_stats, b->pNoMetricCtr);
statsobj.DestructCounter(bkts->global_stats, b->pMetricsPurgedCtr);
statsobj.DestructCounter(bkts->global_stats, b->pOpsIgnoredCtr);
free(b);
}
static rsRetVal
dynstats_addBucketMetrics(dynstats_buckets_t *bkts, dynstats_bucket_t *b, const uchar* name) {
uchar *metric_name_buff, *metric_suffix;
const uchar *suffix_litteral;
int name_len;
DEFiRet;
name_len = ustrlen(name);
CHKmalloc(metric_name_buff = malloc((name_len + DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH + 1) * sizeof(uchar)));
ustrncpy(metric_name_buff, name, name_len);
metric_suffix = metric_name_buff + name_len;
*metric_suffix = DYNSTATS_METRIC_NAME_SEPARATOR;
metric_suffix++;
suffix_litteral = UCHAR_CONSTANT("ops_overflow");
ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
STATSCOUNTER_INIT(b->ctrOpsOverflow, b->mutCtrOpsOverflow);
CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
CTR_FLAG_RESETTABLE, &(b->ctrOpsOverflow), &b->pOpsOverflowCtr));
suffix_litteral = UCHAR_CONSTANT("new_metric_add");
ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
STATSCOUNTER_INIT(b->ctrNewMetricAdd, b->mutCtrNewMetricAdd);
CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
CTR_FLAG_RESETTABLE, &(b->ctrNewMetricAdd), &b->pNewMetricAddCtr));
suffix_litteral = UCHAR_CONSTANT("no_metric");
ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
STATSCOUNTER_INIT(b->ctrNoMetric, b->mutCtrNoMetric);
CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
CTR_FLAG_RESETTABLE, &(b->ctrNoMetric), &b->pNoMetricCtr));
suffix_litteral = UCHAR_CONSTANT("metrics_purged");
ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
STATSCOUNTER_INIT(b->ctrMetricsPurged, b->mutCtrMetricsPurged);
CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
CTR_FLAG_RESETTABLE, &(b->ctrMetricsPurged), &b->pMetricsPurgedCtr));
suffix_litteral = UCHAR_CONSTANT("ops_ignored");
ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
STATSCOUNTER_INIT(b->ctrOpsIgnored, b->mutCtrOpsIgnored);
CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
CTR_FLAG_RESETTABLE, &(b->ctrOpsIgnored), &b->pOpsIgnoredCtr));
finalize_it:
free(metric_name_buff);
if (iRet != RS_RET_OK) {
if (b->pOpsOverflowCtr != NULL) {
statsobj.DestructCounter(bkts->global_stats, b->pOpsOverflowCtr);
}
if (b->pNewMetricAddCtr != NULL) {
statsobj.DestructCounter(bkts->global_stats, b->pNewMetricAddCtr);
}
if (b->pNoMetricCtr != NULL) {
statsobj.DestructCounter(bkts->global_stats, b->pNoMetricCtr);
}
if (b->pMetricsPurgedCtr != NULL) {
statsobj.DestructCounter(bkts->global_stats, b->pMetricsPurgedCtr);
}
if (b->pOpsIgnoredCtr != NULL) {
statsobj.DestructCounter(bkts->global_stats, b->pOpsIgnoredCtr);
}
}
RETiRet;
}
static void
no_op_free(void __attribute__((unused)) *ignore) {}
static rsRetVal
dynstats_resetBucket(dynstats_bucket_t *b, uint8_t do_purge) {
size_t htab_sz;
DEFiRet;
htab_sz = (size_t) (DYNSTATS_HASHTABLE_SIZE_OVERPROVISIONING * b->maxCardinality + 1);
pthread_rwlock_wrlock(&b->lock);
if (do_purge) {
dynstats_destroyCounters(b);
}
ATOMIC_STORE_0_TO_INT(&b->metricCount, &b->mutMetricCount);
b->ctrs = NULL;
if ((b->table = create_hashtable(htab_sz, hash_from_string, key_equals_string, no_op_free)) == NULL) {
errmsg.LogError(errno, RS_RET_INTERNAL_ERROR, "error trying to initialize hash-table for dyn-stats bucket named: %s", b->name);
ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
}
timeoutComp(&b->metricCleanupTimeout, b->unusedMetricLife);
finalize_it:
pthread_rwlock_unlock(&b->lock);
if (iRet != RS_RET_OK) {
statsobj.Destruct(&b->stats);
}
RETiRet;
}
static inline void
dynstats_resetIfExpired(dynstats_bucket_t *b) {
long timeout;
pthread_rwlock_rdlock(&b->lock);
timeout = timeoutVal(&b->metricCleanupTimeout);
pthread_rwlock_unlock(&b->lock);
if (timeout == 0) {
errmsg.LogMsg(0, RS_RET_TIMED_OUT, LOG_INFO, "dynstats: bucket '%s' is being reset", b->name);
dynstats_resetBucket(b, 1);
}
}
static void
dynstats_readCallback(statsobj_t __attribute__((unused)) *ignore, void *b) {
dynstats_buckets_t *bkts;
bkts = &loadConf->dynstats_buckets;
pthread_rwlock_rdlock(&bkts->lock);
dynstats_resetIfExpired((dynstats_bucket_t *) b);
pthread_rwlock_unlock(&bkts->lock);
}
static inline rsRetVal
dynstats_initNewBucketStats(dynstats_bucket_t *b) {
DEFiRet;
CHKiRet(statsobj.Construct(&b->stats));
CHKiRet(statsobj.SetOrigin(b->stats, UCHAR_CONSTANT("dynstats.bucket")));
CHKiRet(statsobj.SetName(b->stats, b->name));
statsobj.SetReadNotifier(b->stats, dynstats_readCallback, b);
CHKiRet(statsobj.ConstructFinalize(b->stats));
finalize_it:
RETiRet;
}
static rsRetVal
dynstats_newBucket(const uchar* name, uint8_t resettable, uint32_t maxCardinality, uint32_t unusedMetricLife) {
dynstats_bucket_t *b;
dynstats_buckets_t *bkts;
uint8_t lock_initialized, metric_count_mutex_initialized;
pthread_rwlockattr_t bucket_lock_attr;
DEFiRet;
lock_initialized = metric_count_mutex_initialized = 0;
b = NULL;
bkts = &loadConf->dynstats_buckets;
if (bkts->initialized) {
CHKmalloc(b = calloc(1, sizeof(dynstats_bucket_t)));
b->resettable = resettable;
b->maxCardinality = maxCardinality;
b->unusedMetricLife = 1000 * unusedMetricLife;
CHKmalloc(b->name = ustrdup(name));
pthread_rwlockattr_init(&bucket_lock_attr);
#ifdef HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP
pthread_rwlockattr_setkind_np(&bucket_lock_attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
#endif
pthread_rwlock_init(&b->lock, &bucket_lock_attr);
lock_initialized = 1;
pthread_mutex_init(&b->mutMetricCount, NULL);
metric_count_mutex_initialized = 1;
CHKiRet(dynstats_initNewBucketStats(b));
CHKiRet(dynstats_resetBucket(b, 0));
CHKiRet(dynstats_addBucketMetrics(bkts, b, name));
pthread_rwlock_wrlock(&bkts->lock);
if (bkts->list == NULL) {
bkts->list = b;
} else {
b->next = bkts->list;
bkts->list = b;
}
pthread_rwlock_unlock(&bkts->lock);
} else {
errmsg.LogError(0, RS_RET_INTERNAL_ERROR, "dynstats: bucket creation failed, as global-initialization of buckets was unsuccessful");
ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
}
finalize_it:
if (iRet != RS_RET_OK) {
if (metric_count_mutex_initialized) {
pthread_mutex_destroy(&b->mutMetricCount);
}
if (lock_initialized) {
pthread_rwlock_destroy(&b->lock);
}
if (b != NULL) {
free(b->name);
free(b);
}
}
RETiRet;
}
rsRetVal
dynstats_processCnf(struct cnfobj *o) {
struct cnfparamvals *pvals;
short i;
uchar *name = NULL;
uint8_t resettable = DYNSTATS_DEFAULT_RESETTABILITY;
uint32_t maxCardinality = DYNSTATS_DEFAULT_MAX_CARDINALITY;
uint32_t unusedMetricLife = DYNSTATS_DEFAULT_UNUSED_METRIC_LIFE;
DEFiRet;
pvals = nvlstGetParams(o->nvlst, &modpblk, NULL);
if(pvals == NULL) {
ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
}
for(i = 0 ; i < modpblk.nParams ; ++i) {
if(!pvals[i].bUsed)
continue;
if(!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_NAME)) {
CHKmalloc(name = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL));
} else if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_RESETTABLE)) {
resettable = (pvals[i].val.d.n != 0);
} else if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_MAX_CARDINALITY)) {
maxCardinality = (uint32_t) pvals[i].val.d.n;
} else if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_UNUSED_METRIC_LIFE)) {
unusedMetricLife = (uint32_t) pvals[i].val.d.n;
} else {
dbgprintf("dyn_stats: program error, non-handled "
"param '%s'\n", modpblk.descr[i].name);
}
}
if (name != NULL) {
CHKiRet(dynstats_newBucket(name, resettable, maxCardinality, unusedMetricLife));
}
finalize_it:
free(name);
cnfparamvalsDestruct(pvals, &modpblk);
RETiRet;
}
rsRetVal
dynstats_initCnf(dynstats_buckets_t *bkts) {
DEFiRet;
bkts->initialized = 0;
bkts->list = NULL;
CHKiRet(statsobj.Construct(&bkts->global_stats));
CHKiRet(statsobj.SetOrigin(bkts->global_stats, UCHAR_CONSTANT("dynstats")));
CHKiRet(statsobj.SetName(bkts->global_stats, UCHAR_CONSTANT("global")));
CHKiRet(statsobj.ConstructFinalize(bkts->global_stats));
pthread_rwlock_init(&bkts->lock, NULL);
bkts->initialized = 1;
finalize_it:
if (iRet != RS_RET_OK) {
statsobj.Destruct(&bkts->global_stats);
}
RETiRet;
}
void
dynstats_destroyAllBuckets() {
dynstats_buckets_t *bkts;
dynstats_bucket_t *b;
bkts = &loadConf->dynstats_buckets;
if (bkts->initialized) {
pthread_rwlock_wrlock(&bkts->lock);
while(1) {
b = bkts->list;
if (b == NULL) {
break;
} else {
bkts->list = b->next;
dynstats_destroyBucket(b);
}
}
pthread_rwlock_unlock(&bkts->lock);
pthread_rwlock_destroy(&bkts->lock);
}
}
dynstats_bucket_t *
dynstats_findBucket(const uchar* name) {
dynstats_buckets_t *bkts;
dynstats_bucket_t *b;
bkts = &loadConf->dynstats_buckets;
if (bkts->initialized) {
pthread_rwlock_rdlock(&bkts->lock);
b = bkts->list;
while(b != NULL) {
if (! ustrcmp(name, b->name)) {
break;
}
b = b->next;
}
pthread_rwlock_unlock(&bkts->lock);
} else {
b = NULL;
errmsg.LogError(0, RS_RET_INTERNAL_ERROR, "dynstats: bucket lookup failed, as global-initialization of buckets was unsuccessful");
}
return b;
}
static rsRetVal
dynstats_createCtr(dynstats_bucket_t *b, const uchar* metric, dynstats_ctr_t **ctr) {
DEFiRet;
CHKmalloc(*ctr = calloc(1, sizeof(dynstats_ctr_t)));
CHKmalloc((*ctr)->metric = ustrdup(metric));
STATSCOUNTER_INIT((*ctr)->ctr, (*ctr)->mutCtr);
CHKiRet(statsobj.AddManagedCounter(b->stats, metric, ctrType_IntCtr,
b->resettable, &(*ctr)->ctr, &(*ctr)->pCtr));
finalize_it:
if (iRet != RS_RET_OK) {
if ((*ctr) != NULL) {
free((*ctr)->metric);
free(*ctr);
*ctr = NULL;
}
}
RETiRet;
}
static rsRetVal
dynstats_addNewCtr(dynstats_bucket_t *b, const uchar* metric, uint8_t doInitialIncrement) {
dynstats_ctr_t *ctr;
dynstats_ctr_t *found_ctr;
int created;
uchar *copy_of_key = NULL;
DEFiRet;
created = 0;
ctr = NULL;
if (ATOMIC_FETCH_32BIT(&b->metricCount, &b->mutMetricCount) >= b->maxCardinality) {
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
CHKiRet(dynstats_createCtr(b, metric, &ctr));
pthread_rwlock_wrlock(&b->lock);
found_ctr = (dynstats_ctr_t*) hashtable_search(b->table, ctr->metric);
if (found_ctr != NULL) {
if (doInitialIncrement) {
STATSCOUNTER_INC(found_ctr->ctr, found_ctr->mutCtr);
}
} else {
copy_of_key = ustrdup(ctr->metric);
if (copy_of_key != NULL) {
created = hashtable_insert(b->table, copy_of_key, ctr);
}
if (created) {
if (b->ctrs == NULL) {
b->ctrs = ctr;
} else {
ctr->next = b->ctrs;
b->ctrs = ctr;
}
if (doInitialIncrement) {
STATSCOUNTER_INC(ctr->ctr, ctr->mutCtr);
}
}
}
pthread_rwlock_unlock(&b->lock);
if (found_ctr != NULL) {
//ignore
} else if (created) {
ATOMIC_INC(&b->metricCount, &b->mutMetricCount);
STATSCOUNTER_INC(b->ctrNewMetricAdd, b->mutCtrNewMetricAdd);
} else {
if (copy_of_key != NULL) {
free(copy_of_key);
}
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
finalize_it:
if ((! created) && (ctr != NULL)) {
dynstats_destroyCtr(b, ctr, 1);
}
RETiRet;
}
rsRetVal
dynstats_inc(dynstats_bucket_t *b, uchar* metric) {
dynstats_ctr_t *ctr;
DEFiRet;
if (! GatherStats) {
FINALIZE;
}
if (ustrlen(metric) == 0) {
STATSCOUNTER_INC(b->ctrNoMetric, b->mutCtrNoMetric);
FINALIZE;
}
if (pthread_rwlock_tryrdlock(&b->lock) == 0) {
ctr = (dynstats_ctr_t *) hashtable_search(b->table, metric);
if (ctr != NULL) {
STATSCOUNTER_INC(ctr->ctr, ctr->mutCtr);
}
pthread_rwlock_unlock(&b->lock);
} else {
ABORT_FINALIZE(RS_RET_NOENTRY);
}
if (ctr == NULL) {
CHKiRet(dynstats_addNewCtr(b, metric, 1));
}
finalize_it:
if (iRet != RS_RET_OK) {
if (iRet == RS_RET_NOENTRY) {
/* NOTE: this is not tested (because it requires very strong orchestration to gurantee contended lock for testing) */
STATSCOUNTER_INC(b->ctrOpsIgnored, b->mutCtrOpsIgnored);
} else {
STATSCOUNTER_INC(b->ctrOpsOverflow, b->mutCtrOpsOverflow);
}
}
RETiRet;
}

56
runtime/dynstats.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef INCLUDED_DYNSTATS_H
#define INCLUDED_DYNSTATS_H
#include "hashtable.h"
typedef struct hashtable htable;
struct dynstats_ctr_s {
STATSCOUNTER_DEF(ctr, mutCtr);
ctr_t *pCtr;
uchar *metric;
struct dynstats_ctr_s *next; /* linked list ptr */
};
struct dynstats_bucket_s {
htable *table;
uchar *name;
pthread_rwlock_t lock;
statsobj_t *stats;
STATSCOUNTER_DEF(ctrOpsOverflow, mutCtrOpsOverflow);
ctr_t *pOpsOverflowCtr;
STATSCOUNTER_DEF(ctrNewMetricAdd, mutCtrNewMetricAdd);
ctr_t *pNewMetricAddCtr;
STATSCOUNTER_DEF(ctrNoMetric, mutCtrNoMetric);
ctr_t *pNoMetricCtr;
STATSCOUNTER_DEF(ctrMetricsPurged, mutCtrMetricsPurged);
ctr_t *pMetricsPurgedCtr;
STATSCOUNTER_DEF(ctrOpsIgnored, mutCtrOpsIgnored);
ctr_t *pOpsIgnoredCtr;
struct dynstats_bucket_s *next; /* linked list ptr */
struct dynstats_ctr_s *ctrs;
uint32_t maxCardinality;
uint32_t metricCount;
pthread_mutex_t mutMetricCount;
uint32_t unusedMetricLife;
uint32_t lastResetTs;
struct timespec metricCleanupTimeout;
uint8_t resettable;
};
struct dynstats_buckets_s {
struct dynstats_bucket_s *list;
statsobj_t *global_stats;
pthread_rwlock_t lock;
uint8_t initialized;
};
rsRetVal dynstats_initCnf(dynstats_buckets_t *b);
rsRetVal dynstats_processCnf(struct cnfobj *o);
dynstats_bucket_t * dynstats_findBucket(const uchar* name);
rsRetVal dynstats_inc(dynstats_bucket_t *bucket, uchar* metric);
void dynstats_destroyAllBuckets();
void dynstats_resetExpired();
rsRetVal dynstatsClassInit(void);
#endif /* #ifndef INCLUDED_DYNSTATS_H */

View File

@ -167,6 +167,7 @@ void cnfSetDefaults(rsconf_t *pThis)
BEGINobjConstruct(rsconf) /* be sure to specify the object type also in END macro! */
cnfSetDefaults(pThis);
lookupInitCnf(&pThis->lu_tabs);
CHKiRet(dynstats_initCnf(&pThis->dynstats_buckets));
CHKiRet(llInit(&pThis->rulesets.llRulesets, rulesetDestructForLinkedList,
rulesetKeyDestruct, strcasecmp));
finalize_it:
@ -208,6 +209,7 @@ BEGINobjDestruct(rsconf) /* be sure to specify the object type also in END and C
CODESTARTobjDestruct(rsconf)
freeCnf(pThis);
tplDeleteAll(pThis);
dynstats_destroyAllBuckets();
free(pThis->globals.mainQ.pszMainMsgQFName);
free(pThis->globals.pszConfDAGFile);
llDestroy(&(pThis->rulesets.llRulesets));
@ -426,6 +428,9 @@ void cnfDoObj(struct cnfobj *o)
case CNFOBJ_LOOKUP_TABLE:
lookupProcessCnf(o);
break;
case CNFOBJ_DYN_STATS:
dynstats_processCnf(o);
break;
case CNFOBJ_PARSER:
parserProcessCnf(o);
break;

View File

@ -26,6 +26,7 @@
#include "linkedlist.h"
#include "queue.h"
#include "lookup.h"
#include "dynstats.h"
/* --- configuration objects (the plan is to have ALL upper layers in this file) --- */
@ -145,6 +146,7 @@ struct rsconf_s {
defaults_t defaults;
templates_t templates;
lookup_tables_t lu_tabs;
dynstats_buckets_t dynstats_buckets;
outchannels_t och;
actions_t actions;
rulesets_t rulesets;

View File

@ -195,6 +195,8 @@ rsrtInit(char **ppErrObj, obj_if_t *pObjIF)
CHKiRet(rsconfClassInit(NULL));
if(ppErrObj != NULL) *ppErrObj = "lookup";
CHKiRet(lookupClassInit());
if(ppErrObj != NULL) *ppErrObj = "dynstats";
CHKiRet(dynstatsClassInit());
/* dummy "classes" */
if(ppErrObj != NULL) *ppErrObj = "str";

View File

@ -106,6 +106,7 @@ BEGINobjConstruct(statsobj) /* be sure to specify the object type also in END ma
pthread_mutex_init(&pThis->mutCtr, NULL);
pThis->ctrLast = NULL;
pThis->ctrRoot = NULL;
pThis->read_notifier = NULL;
ENDobjConstruct(statsobj)
@ -120,6 +121,17 @@ statsobjConstructFinalize(statsobj_t *pThis)
RETiRet;
}
/* set read_notifier (a function which is invoked after stats are read).
*/
static rsRetVal
setReadNotifier(statsobj_t *pThis, statsobj_read_notifier_t notifier, void* ctx)
{
DEFiRet;
pThis->read_notifier = notifier;
pThis->read_notifier_ctx = ctx;
RETiRet;
}
/* set origin (module name, etc).
* Note that we make our own copy of the memory, caller is
@ -156,17 +168,18 @@ finalize_it:
* is called.
*/
static rsRetVal
addCounter(statsobj_t *pThis, uchar *ctrName, statsCtrType_t ctrType, int8_t flags, void *pCtr)
addManagedCounter(statsobj_t *pThis, const uchar *ctrName, statsCtrType_t ctrType, int8_t flags, void *pCtr, ctr_t **entryRef)
{
ctr_t *ctr;
DEFiRet;
CHKmalloc(ctr = malloc(sizeof(ctr_t)));
*entryRef = NULL;
CHKmalloc(ctr = calloc(1, sizeof(ctr_t)));
ctr->next = NULL;
ctr->prev = NULL;
if((ctr->name = ustrdup(ctrName)) == NULL) {
DBGPRINTF("addCounter: OOM in strdup()\n");
free(ctr);
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
ctr->flags = flags;
@ -180,8 +193,50 @@ addCounter(statsobj_t *pThis, uchar *ctrName, statsCtrType_t ctrType, int8_t fla
break;
}
addCtrToList(pThis, ctr);
*entryRef = ctr;
finalize_it:
if (iRet != RS_RET_OK) {
if (ctr != NULL) {
free(ctr->name);
free(ctr);
}
}
RETiRet;
}
static rsRetVal
addCounter(statsobj_t *pThis, const uchar *ctrName, statsCtrType_t ctrType, int8_t flags, void *pCtr)
{
ctr_t *ctr;
DEFiRet;
CHKiRet(addManagedCounter(pThis, ctrName, ctrType, flags, pCtr, &ctr));
finalize_it:
RETiRet;
}
static rsRetVal
destructCounter(statsobj_t *pThis, ctr_t *pCtr)
{
DEFiRet;
pthread_mutex_lock(&pThis->mutCtr);
if (pCtr->prev != NULL) {
pCtr->prev->next = pCtr->next;
}
if (pCtr->next != NULL) {
pCtr->next->prev = pCtr->prev;
}
if (pThis->ctrLast == pCtr) {
pThis->ctrLast = pCtr->prev;
}
if (pThis->ctrRoot == pCtr) {
pThis->ctrRoot = pCtr->next;
}
pthread_mutex_unlock(&pThis->mutCtr);
free(pCtr->name);
free(pCtr);
RETiRet;
}
@ -351,6 +406,9 @@ getAllStatsLines(rsRetVal(*cb)(void*, cstr_t*), void *usrptr, statsFmtType_t fmt
}
CHKiRet(cb(usrptr, cstr));
rsCStrDestruct(&cstr);
if (o->read_notifier != NULL) {
o->read_notifier(o, o->read_notifier_ctx);
}
}
finalize_it:
@ -368,14 +426,11 @@ enableStats()
return RS_RET_OK;
}
/* destructor for the statsobj object */
BEGINobjDestruct(statsobj) /* be sure to specify the object type also in END and CODESTART macros! */
static rsRetVal
destructAllCounters(statsobj_t *pThis) {
DEFiRet;
ctr_t *ctr, *ctrToDel;
CODESTARTobjDestruct(statsobj)
removeFromObjList(pThis);
/* destruct counters */
ctr = pThis->ctrRoot;
while(ctr != NULL) {
ctrToDel = ctr;
@ -384,6 +439,21 @@ CODESTARTobjDestruct(statsobj)
free(ctrToDel);
}
pThis->ctrLast = NULL;
pThis->ctrRoot = NULL;
RETiRet;
}
/* destructor for the statsobj object */
BEGINobjDestruct(statsobj) /* be sure to specify the object type also in END and CODESTART macros! */
CODESTARTobjDestruct(statsobj)
removeFromObjList(pThis);
/* destruct counters */
CHKiRet(destructAllCounters(pThis));
pthread_mutex_destroy(&pThis->mutCtr);
free(pThis->name);
free(pThis->origin);
@ -416,9 +486,13 @@ CODESTARTobjQueryInterface(statsobj)
pIf->DebugPrint = statsobjDebugPrint;
pIf->SetName = setName;
pIf->SetOrigin = setOrigin;
pIf->SetReadNotifier = setReadNotifier;
//pIf->GetStatsLine = getStatsLine;
pIf->GetAllStatsLines = getAllStatsLines;
pIf->AddCounter = addCounter;
pIf->AddManagedCounter = addManagedCounter;
pIf->DestructCounter = destructCounter;
pIf->DestructAllCounters = destructAllCounters;
pIf->EnableStats = enableStats;
finalize_it:
ENDobjQueryInterface(statsobj)

View File

@ -72,6 +72,8 @@ struct statsobj_s {
BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
uchar *name;
uchar *origin;
statsobj_read_notifier_t read_notifier;
void *read_notifier_ctx;
pthread_mutex_t mutCtr; /* to guard counter linked-list ops */
ctr_t *ctrRoot; /* doubly-linked list of statsobj counters */
ctr_t *ctrLast;
@ -89,9 +91,13 @@ BEGINinterface(statsobj) /* name must also be changed in ENDinterface macro! */
rsRetVal (*Destruct)(statsobj_t **ppThis);
rsRetVal (*SetName)(statsobj_t *pThis, uchar *name);
rsRetVal (*SetOrigin)(statsobj_t *pThis, uchar *name); /* added v12, 2014-09-08 */
rsRetVal (*SetReadNotifier)(statsobj_t *pThis, statsobj_read_notifier_t notifier, void* ctx);
//rsRetVal (*GetStatsLine)(statsobj_t *pThis, cstr_t **ppcstr);
rsRetVal (*GetAllStatsLines)(rsRetVal(*cb)(void*, cstr_t*), void *usrptr, statsFmtType_t fmt, int8_t bResetCtr);
rsRetVal (*AddCounter)(statsobj_t *pThis, uchar *ctrName, statsCtrType_t ctrType, int8_t flags, void *pCtr);
rsRetVal (*AddCounter)(statsobj_t *pThis, const uchar *ctrName, statsCtrType_t ctrType, int8_t flags, void *pCtr);
rsRetVal (*AddManagedCounter)(statsobj_t *pThis, const uchar *ctrName, statsCtrType_t ctrType, int8_t flags, void *pCtr, ctr_t **ref);
rsRetVal (*DestructCounter)(statsobj_t *pThis, ctr_t *ref);
rsRetVal (*DestructAllCounters)(statsobj_t *pThis);
rsRetVal (*EnableStats)(void);
ENDinterface(statsobj)
#define statsobjCURR_IF_VERSION 12 /* increment whenever you change the interface structure! */
@ -152,6 +158,10 @@ PROTOTYPEObj(statsobj);
if(GatherStats) \
ATOMIC_INC_uint64(&ctr, &mut);
#define STATSCOUNTER_BUMP(ctr, mut, delta) \
if(GatherStats) \
ATOMIC_ADD_uint64(&ctr, &mut, delta);
#define STATSCOUNTER_DEC(ctr, mut) \
if(GatherStats) \
ATOMIC_DEC_uint64(&ctr, mut);

View File

@ -84,6 +84,7 @@ typedef struct parserList_s parserList_t;
typedef struct strgen_s strgen_t;
typedef struct strgenList_s strgenList_t;
typedef struct statsobj_s statsobj_t;
typedef void (*statsobj_read_notifier_t)(statsobj_t *, void *);
typedef struct nsd_epworkset_s nsd_epworkset_t;
typedef struct templates_s templates_t;
typedef struct queuecnf_s queuecnf_t;
@ -110,6 +111,9 @@ typedef uint64 qDeqID; /* queue Dequeue order ID. 32 bits is considered dangerou
typedef struct tcpLstnPortList_s tcpLstnPortList_t; // TODO: rename?
typedef struct strmLstnPortList_s strmLstnPortList_t; // TODO: rename?
typedef struct actWrkrIParams actWrkrIParams_t;
typedef struct dynstats_bucket_s dynstats_bucket_t;
typedef struct dynstats_buckets_s dynstats_buckets_t;
typedef struct dynstats_ctr_s dynstats_ctr_t;
/* under Solaris (actually only SPARC), we need to redefine some types
* to be void, so that we get void* pointers. Otherwise, we will see

View File

@ -160,7 +160,8 @@ TESTS += \
failover-no-rptd-vg.sh \
udp-msgreduc-vg.sh \
udp-msgreduc-orgmsg-vg.sh \
tcp-msgreduc-vg.sh
tcp-msgreduc-vg.sh \
rscript_field-vg.sh
endif # HAVE_VALGRIND
@ -188,6 +189,21 @@ endif
endif
endif
if ENABLE_IMPSTATS
TESTS += \
dynstats.sh \
dynstats_overflow.sh \
dynstats_reset.sh \
dynstats_ctr_reset.sh \
dynstats_nometric.sh
if HAVE_VALGRIND
TESTS += \
dynstats-vg.sh \
dynstats_reset-vg.sh \
dynstats_overflow-vg.sh
endif
endif
if ENABLE_IMPTCP
# note that some tests simply USE imptcp, but they also
# need to be disabled if we do not have this module
@ -459,6 +475,7 @@ EXTRA_DIST= \
rscript_contains.sh \
testsuites/rscript_contains.conf \
rscript_field.sh \
rscript_field-vg.sh \
testsuites/rscript_field.conf \
rscript_stop.sh \
testsuites/rscript_stop.conf \
@ -861,6 +878,27 @@ EXTRA_DIST= \
mmpstrucdata-invalid-vg.sh \
testsuites/mmpstrucdata-invalid.conf \
libdbi-basic-vg.sh \
dynstats_ctr_reset.sh \
dynstats_nometric.sh \
dynstats_overflow.sh \
dynstats_overflow-vg.sh \
dynstats_reset.sh \
dynstats_reset-vg.sh \
dynstats.sh \
dynstats-vg.sh \
testsuites/dynstats.conf \
testsuites/dynstats_ctr_reset.conf \
testsuites/dynstats_empty_input \
testsuites/dynstats_input \
testsuites/dynstats_input_1 \
testsuites/dynstats_input_2 \
testsuites/dynstats_input_3 \
testsuites/dynstats_input_more_0 \
testsuites/dynstats_input_more_1 \
testsuites/dynstats_input_more_2 \
testsuites/dynstats_nometric.conf \
testsuites/dynstats_overflow.conf \
testsuites/dynstats_reset.conf \
mmnormalize_variable.sh \
mmnormalize_tokenized.sh \
testsuites/mmnormalize_variable.conf \

View File

@ -130,6 +130,10 @@ case $1 in
. $srcdir/diag.sh wait-startup $3
echo startup-vg still running
;;
'msleep')
$srcdir/msleep $2
;;
'wait-startup') # wait for rsyslogd startup ($2 is the instance)
i=0
while test ! -f rsyslog$2.pid; do
@ -239,6 +243,11 @@ case $1 in
echo injectmsg $2 $3 $4 $5 | ./diagtalker || . $srcdir/diag.sh error-exit $?
# TODO: some return state checking? (does it really make sense here?)
;;
'injectmsg-litteral') # inject litteral-payload via our inject interface (imdiag)
echo injecting msg payload from: $2
cat $2 | sed -e 's/^/injectmsg litteral /g' | ./diagtalker || . $srcdir/diag.sh error-exit $?
# TODO: some return state checking? (does it really make sense here?)
;;
'check-mainq-spool') # check if mainqueue spool files exist, if not abort (we just check .qi).
echo There must exist some files now:
ls -l test-spool
@ -277,11 +286,24 @@ case $1 in
'content-check')
cat rsyslog.out.log | grep -qF "$2"
if [ "$?" -ne "0" ]; then
echo content-check failed, content is
echo content-check failed to find "'$2'", content is
cat rsyslog.out.log
. $srcdir/diag.sh error-exit 1
fi
;;
'wait-for-stats-flush')
echo "will wait for stats push"
while [[ ! -f $2 ]]; do
echo waiting for stats file "'$2'" to be created
./msleep 100
done
prev_count=$(cat $2 | grep 'BEGIN$' | wc -l)
new_count=$prev_count
while [[ "x$prev_count" == "x$new_count" ]]; do
new_count=$(cat $2 | grep 'BEGIN$' | wc -l) # busy spin, because it allows as close timing-coordination in actual test run as possible
done
echo "stats push registered"
;;
'custom-content-check')
cat $3 | grep -qF "$2"
if [ "$?" -ne "0" ]; then
@ -289,6 +311,20 @@ case $1 in
. $srcdir/diag.sh error-exit 1
fi
;;
'first-column-sum-check')
sum=$(cat $4 | grep $3 | sed -e $2 | awk '{s+=$1} END {print s}')
if [ "x${sum}" != "x$5" ]; then
echo sum of first column with edit-expr "'$2'" run over lines from file "'$4'" matched by "'$3'" equals "'$sum'" which is not equal to expected value of "'$5'"
. $srcdir/diag.sh error-exit 1
fi
;;
'assert-first-column-sum-greater-than')
sum=$(cat $4 | grep $3 | sed -e $2 | awk '{s+=$1} END {print s}')
if [ ! $sum -gt $5 ]; then
echo sum of first column with edit-expr "'$2'" run over lines from file "'$4'" matched by "'$3'" equals "'$sum'" which is smaller than expected lower-limit of "'$5'"
. $srcdir/diag.sh error-exit 1
fi
;;
'content-pattern-check')
cat rsyslog.out.log | grep -q "$2"
if [ "$?" -ne "0" ]; then
@ -299,6 +335,14 @@ case $1 in
'assert-content-missing')
cat rsyslog.out.log | grep -qF "$2"
if [ "$?" -eq "0" ]; then
echo content-missing assertion failed, some line matched pattern "'$2'"
. $srcdir/diag.sh error-exit 1
fi
;;
'custom-assert-content-missing')
cat $3 | grep -qF "$2"
if [ "$?" -eq "0" ]; then
echo content-missing assertion failed, some line in "'$3'" matched pattern "'$2'"
. $srcdir/diag.sh error-exit 1
fi
;;

27
tests/dynstats-vg.sh Executable file
View File

@ -0,0 +1,27 @@
#!/bin/bash
# added 2015-11-13 by singh.janmejay
# This file is part of the rsyslog project, released under ASL 2.0
echo ===============================================================================
echo \[dynstats-vg.sh\]: test for gathering stats over dynamic metric names with valgrind
. $srcdir/diag.sh init
. $srcdir/diag.sh startup-vg dynstats.conf
. $srcdir/diag.sh wait-for-stats-flush 'rsyslog.out.stats.log'
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input
. $srcdir/diag.sh wait-queueempty
. $srcdir/diag.sh content-check "foo 001 0"
. $srcdir/diag.sh content-check "bar 002 0"
. $srcdir/diag.sh content-check "baz 003 0"
. $srcdir/diag.sh content-check "foo 004 0"
. $srcdir/diag.sh content-check "baz 005 0"
. $srcdir/diag.sh content-check "foo 006 0"
. $srcdir/diag.sh msleep 1100 # wait for stats flush
echo doing shutdown
. $srcdir/diag.sh shutdown-when-empty
echo wait on shutdown
. $srcdir/diag.sh wait-shutdown-vg
. $srcdir/diag.sh check-exit-vg
. $srcdir/diag.sh custom-content-check 'bar=1' 'rsyslog.out.stats.log'
. $srcdir/diag.sh first-column-sum-check 's/.*foo=\([0-9]\+\)/\1/g' 'foo=' 'rsyslog.out.stats.log' 3
. $srcdir/diag.sh first-column-sum-check 's/.*bar=\([0-9]\+\)/\1/g' 'bar=' 'rsyslog.out.stats.log' 1
. $srcdir/diag.sh first-column-sum-check 's/.*baz=\([0-9]\+\)/\1/g' 'baz=' 'rsyslog.out.stats.log' 2
. $srcdir/diag.sh exit

26
tests/dynstats.sh Executable file
View File

@ -0,0 +1,26 @@
#!/bin/bash
# added 2015-11-10 by singh.janmejay
# This file is part of the rsyslog project, released under ASL 2.0
echo ===============================================================================
echo \[dynstats.sh\]: test for gathering stats over dynamic metric names
. $srcdir/diag.sh init
. $srcdir/diag.sh startup dynstats.conf
. $srcdir/diag.sh wait-for-stats-flush 'rsyslog.out.stats.log'
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input
. $srcdir/diag.sh wait-queueempty
. $srcdir/diag.sh content-check "foo 001 0"
. $srcdir/diag.sh content-check "bar 002 0"
. $srcdir/diag.sh content-check "baz 003 0"
. $srcdir/diag.sh content-check "foo 004 0"
. $srcdir/diag.sh content-check "baz 005 0"
. $srcdir/diag.sh content-check "foo 006 0"
. $srcdir/diag.sh msleep 1100 # wait for stats flush
echo doing shutdown
. $srcdir/diag.sh shutdown-when-empty
echo wait on shutdown
. $srcdir/diag.sh wait-shutdown
. $srcdir/diag.sh custom-content-check 'bar=1' 'rsyslog.out.stats.log'
. $srcdir/diag.sh first-column-sum-check 's/.*foo=\([0-9]\+\)/\1/g' 'foo=' 'rsyslog.out.stats.log' 3
. $srcdir/diag.sh first-column-sum-check 's/.*bar=\([0-9]\+\)/\1/g' 'bar=' 'rsyslog.out.stats.log' 1
. $srcdir/diag.sh first-column-sum-check 's/.*baz=\([0-9]\+\)/\1/g' 'baz=' 'rsyslog.out.stats.log' 2
. $srcdir/diag.sh exit

30
tests/dynstats_ctr_reset.sh Executable file
View File

@ -0,0 +1,30 @@
#!/bin/bash
# added 2015-11-16 by singh.janmejay
# This file is part of the rsyslog project, released under ASL 2.0
echo ===============================================================================
echo \[dynstats_ctr_reset.sh\]: test to ensure correctness of stats-ctr reset
. $srcdir/diag.sh init
. $srcdir/diag.sh startup dynstats_ctr_reset.conf
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input_1
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input_2
. $srcdir/diag.sh wait-queueempty
sleep 1
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input_3
. $srcdir/diag.sh wait-queueempty
sleep 1
echo doing shutdown
. $srcdir/diag.sh shutdown-when-empty
echo wait on shutdown
. $srcdir/diag.sh wait-shutdown
. $srcdir/diag.sh content-check "foo 006"
. $srcdir/diag.sh custom-content-check 'bar=1' 'rsyslog.out.stats.log'
. $srcdir/diag.sh first-column-sum-check 's/.*foo=\([0-9]\+\)/\1/g' 'msg_stats_resettable_on.\+foo=' 'rsyslog.out.stats.log' 3
. $srcdir/diag.sh first-column-sum-check 's/.*bar=\([0-9]\+\)/\1/g' 'msg_stats_resettable_on.\+bar=' 'rsyslog.out.stats.log' 1
. $srcdir/diag.sh first-column-sum-check 's/.*baz=\([0-9]\+\)/\1/g' 'msg_stats_resettable_on.\+baz=' 'rsyslog.out.stats.log' 2
. $srcdir/diag.sh assert-first-column-sum-greater-than 's/.*foo=\([0-9]\+\)/\1/g' 'msg_stats_resettable_off.\+foo=' 'rsyslog.out.stats.log' 3
. $srcdir/diag.sh assert-first-column-sum-greater-than 's/.*bar=\([0-9]\+\)/\1/g' 'msg_stats_resettable_off.\+bar=' 'rsyslog.out.stats.log' 1
. $srcdir/diag.sh assert-first-column-sum-greater-than 's/.*baz=\([0-9]\+\)/\1/g' 'msg_stats_resettable_off.\+baz=' 'rsyslog.out.stats.log' 2
. $srcdir/diag.sh first-column-sum-check 's/.*foo=\([0-9]\+\)/\1/g' 'msg_stats_resettable_default.\+foo=' 'rsyslog.out.stats.log' 3
. $srcdir/diag.sh first-column-sum-check 's/.*bar=\([0-9]\+\)/\1/g' 'msg_stats_resettable_default.\+bar=' 'rsyslog.out.stats.log' 1
. $srcdir/diag.sh first-column-sum-check 's/.*baz=\([0-9]\+\)/\1/g' 'msg_stats_resettable_default.\+baz=' 'rsyslog.out.stats.log' 2
. $srcdir/diag.sh exit

26
tests/dynstats_nometric.sh Executable file
View File

@ -0,0 +1,26 @@
#!/bin/bash
# added 2015-11-17 by singh.janmejay
# This file is part of the rsyslog project, released under ASL 2.0
echo ===============================================================================
echo \[dynstats_nometric.sh\]: test for dyn-stats meta-metric behavior with zero-length metric name
. $srcdir/diag.sh init
. $srcdir/diag.sh startup dynstats_nometric.conf
. $srcdir/diag.sh wait-for-stats-flush 'rsyslog.out.stats.log'
. $srcdir/diag.sh wait-queueempty
rm $srcdir/rsyslog.out.stats.log
. $srcdir/diag.sh issue-HUP #reopen stats file
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_empty_input
. $srcdir/diag.sh wait-queueempty
. $srcdir/diag.sh msleep 1100 # wait for stats flush
echo doing shutdown
. $srcdir/diag.sh shutdown-when-empty
echo wait on shutdown
. $srcdir/diag.sh wait-shutdown
. $srcdir/diag.sh first-column-sum-check 's/.*no_metric=\([0-9]\+\)/\1/g' 'no_metric=' 'rsyslog.out.stats.log' 5
. $srcdir/diag.sh custom-assert-content-missing 'foo' 'rsyslog.out.stats.log'
. $srcdir/diag.sh custom-assert-content-missing 'bar' 'rsyslog.out.stats.log'
. $srcdir/diag.sh custom-assert-content-missing 'baz' 'rsyslog.out.stats.log'
. $srcdir/diag.sh custom-assert-content-missing 'corge' 'rsyslog.out.stats.log'
. $srcdir/diag.sh custom-content-check 'quux=1' 'rsyslog.out.stats.log'
. $srcdir/diag.sh custom-content-check 'grault=1' 'rsyslog.out.stats.log'
. $srcdir/diag.sh exit

55
tests/dynstats_overflow-vg.sh Executable file
View File

@ -0,0 +1,55 @@
#!/bin/bash
# added 2015-11-13 by singh.janmejay
# This file is part of the rsyslog project, released under ASL 2.0
echo ===============================================================================
echo \[dynstats_overflow-vg.sh\]: test for gathering stats when metrics exceed provisioned capacity
. $srcdir/diag.sh init
. $srcdir/diag.sh startup-vg dynstats_overflow.conf
. $srcdir/diag.sh wait-for-stats-flush 'rsyslog.out.stats.log'
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input_more_0
. $srcdir/diag.sh wait-queueempty
. $srcdir/diag.sh msleep 800
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input_more_1
. $srcdir/diag.sh wait-queueempty
. $srcdir/diag.sh msleep 1300 #sleep above + this = 2 seconds, so metric-names reset should have happened
. $srcdir/diag.sh wait-queueempty
. $srcdir/diag.sh first-column-sum-check 's/.*foo=\([0-9]\+\)/\1/g' 'foo=' 'rsyslog.out.stats.log' 5
. $srcdir/diag.sh first-column-sum-check 's/.*bar=\([0-9]\+\)/\1/g' 'bar=' 'rsyslog.out.stats.log' 1
. $srcdir/diag.sh first-column-sum-check 's/.*baz=\([0-9]\+\)/\1/g' 'baz=' 'rsyslog.out.stats.log' 2
. $srcdir/diag.sh custom-assert-content-missing 'quux' 'rsyslog.out.stats.log'
. $srcdir/diag.sh custom-assert-content-missing 'corge' 'rsyslog.out.stats.log'
. $srcdir/diag.sh custom-assert-content-missing 'grault' 'rsyslog.out.stats.log'
rm $srcdir/rsyslog.out.stats.log
. $srcdir/diag.sh issue-HUP #reopen stats file
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input_more_2
. $srcdir/diag.sh msleep 2100
echo doing shutdown
. $srcdir/diag.sh shutdown-when-empty
echo wait on shutdown
. $srcdir/diag.sh wait-shutdown-vg
. $srcdir/diag.sh check-exit-vg
. $srcdir/diag.sh content-check "foo 001 0"
. $srcdir/diag.sh content-check "bar 002 0"
. $srcdir/diag.sh content-check "baz 003 0"
. $srcdir/diag.sh content-check "foo 004 0"
. $srcdir/diag.sh content-check "baz 005 0"
. $srcdir/diag.sh content-check "foo 006 0"
. $srcdir/diag.sh content-check "quux 007 -6"
. $srcdir/diag.sh content-check "corge 008 -6"
. $srcdir/diag.sh content-check "quux 009 -6"
. $srcdir/diag.sh content-check "foo 010 0"
. $srcdir/diag.sh content-check "corge 011 -6"
. $srcdir/diag.sh content-check "grault 012 -6"
. $srcdir/diag.sh content-check "foo 013 0"
. $srcdir/diag.sh content-check "corge 014 0"
. $srcdir/diag.sh content-check "grault 015 0"
. $srcdir/diag.sh content-check "quux 016 0"
. $srcdir/diag.sh content-check "foo 017 -6"
. $srcdir/diag.sh content-check "corge 018 0"
. $srcdir/diag.sh first-column-sum-check 's/.*corge=\([0-9]\+\)/\1/g' 'corge=' 'rsyslog.out.stats.log' 2
. $srcdir/diag.sh first-column-sum-check 's/.*grault=\([0-9]\+\)/\1/g' 'grault=' 'rsyslog.out.stats.log' 1
. $srcdir/diag.sh first-column-sum-check 's/.*quux=\([0-9]\+\)/\1/g' 'quux=' 'rsyslog.out.stats.log' 1
. $srcdir/diag.sh custom-assert-content-missing 'foo' 'rsyslog.out.stats.log'
. $srcdir/diag.sh exit

67
tests/dynstats_overflow.sh Executable file
View File

@ -0,0 +1,67 @@
#!/bin/bash
# added 2015-11-13 by singh.janmejay
# This file is part of the rsyslog project, released under ASL 2.0
echo ===============================================================================
echo \[dynstats_overflow.sh\]: test for gathering stats when metrics exceed provisioned capacity
. $srcdir/diag.sh init
. $srcdir/diag.sh startup dynstats_overflow.conf
. $srcdir/diag.sh wait-for-stats-flush 'rsyslog.out.stats.log'
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input_more_0
. $srcdir/diag.sh wait-queueempty
. $srcdir/diag.sh msleep 800
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input_more_1
. $srcdir/diag.sh wait-queueempty
. $srcdir/diag.sh msleep 1300 #sleep above + this = 2 seconds, so metric-names reset should have happened
. $srcdir/diag.sh wait-queueempty
. $srcdir/diag.sh first-column-sum-check 's/.*foo=\([0-9]\+\)/\1/g' 'foo=' 'rsyslog.out.stats.log' 5
. $srcdir/diag.sh first-column-sum-check 's/.*bar=\([0-9]\+\)/\1/g' 'bar=' 'rsyslog.out.stats.log' 1
. $srcdir/diag.sh first-column-sum-check 's/.*baz=\([0-9]\+\)/\1/g' 'baz=' 'rsyslog.out.stats.log' 2
. $srcdir/diag.sh custom-assert-content-missing 'quux' 'rsyslog.out.stats.log'
. $srcdir/diag.sh custom-assert-content-missing 'corge' 'rsyslog.out.stats.log'
. $srcdir/diag.sh custom-assert-content-missing 'grault' 'rsyslog.out.stats.log'
. $srcdir/diag.sh first-column-sum-check 's/.*new_metric_add=\([0-9]\+\)/\1/g' 'new_metric_add=' 'rsyslog.out.stats.log' 3
. $srcdir/diag.sh first-column-sum-check 's/.*ops_overflow=\([0-9]\+\)/\1/g' 'ops_overflow=' 'rsyslog.out.stats.log' 5
. $srcdir/diag.sh first-column-sum-check 's/.*no_metric=\([0-9]\+\)/\1/g' 'no_metric=' 'rsyslog.out.stats.log' 0
. $srcdir/diag.sh first-column-sum-check 's/.*metrics_purged=\([0-9]\+\)/\1/g' 'metrics_purged=' 'rsyslog.out.stats.log' 3
rm $srcdir/rsyslog.out.stats.log
. $srcdir/diag.sh issue-HUP #reopen stats file
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input_more_2
. $srcdir/diag.sh msleep 2100
echo doing shutdown
. $srcdir/diag.sh shutdown-when-empty
echo wait on shutdown
. $srcdir/diag.sh wait-shutdown
. $srcdir/diag.sh content-check "foo 001 0"
. $srcdir/diag.sh content-check "bar 002 0"
. $srcdir/diag.sh content-check "baz 003 0"
. $srcdir/diag.sh content-check "foo 004 0"
. $srcdir/diag.sh content-check "baz 005 0"
. $srcdir/diag.sh content-check "foo 006 0"
. $srcdir/diag.sh content-check "quux 007 -6"
. $srcdir/diag.sh content-check "corge 008 -6"
. $srcdir/diag.sh content-check "quux 009 -6"
. $srcdir/diag.sh content-check "foo 010 0"
. $srcdir/diag.sh content-check "corge 011 -6"
. $srcdir/diag.sh content-check "grault 012 -6"
. $srcdir/diag.sh content-check "foo 013 0"
. $srcdir/diag.sh content-check "corge 014 0"
. $srcdir/diag.sh content-check "grault 015 0"
. $srcdir/diag.sh content-check "quux 016 0"
. $srcdir/diag.sh content-check "foo 017 -6"
. $srcdir/diag.sh content-check "corge 018 0"
. $srcdir/diag.sh first-column-sum-check 's/.*corge=\([0-9]\+\)/\1/g' 'corge=' 'rsyslog.out.stats.log' 2
. $srcdir/diag.sh first-column-sum-check 's/.*grault=\([0-9]\+\)/\1/g' 'grault=' 'rsyslog.out.stats.log' 1
. $srcdir/diag.sh first-column-sum-check 's/.*quux=\([0-9]\+\)/\1/g' 'quux=' 'rsyslog.out.stats.log' 1
. $srcdir/diag.sh first-column-sum-check 's/.*new_metric_add=\([0-9]\+\)/\1/g' 'new_metric_add=' 'rsyslog.out.stats.log' 3
. $srcdir/diag.sh first-column-sum-check 's/.*ops_overflow=\([0-9]\+\)/\1/g' 'ops_overflow=' 'rsyslog.out.stats.log' 1
. $srcdir/diag.sh first-column-sum-check 's/.*no_metric=\([0-9]\+\)/\1/g' 'no_metric=' 'rsyslog.out.stats.log' 0
. $srcdir/diag.sh first-column-sum-check 's/.*metrics_purged=\([0-9]\+\)/\1/g' 'metrics_purged=' 'rsyslog.out.stats.log' 3
. $srcdir/diag.sh custom-assert-content-missing 'foo' 'rsyslog.out.stats.log'
. $srcdir/diag.sh exit

35
tests/dynstats_reset-vg.sh Executable file
View File

@ -0,0 +1,35 @@
#!/bin/bash
# added 2015-11-13 by singh.janmejay
# This file is part of the rsyslog project, released under ASL 2.0
echo ===============================================================================
echo \[dynstats_reset-vg.sh\]: test for gathering stats with a known-dyn-metrics reset in-between
. $srcdir/diag.sh init
. $srcdir/diag.sh startup-vg dynstats_reset.conf
. $srcdir/diag.sh wait-for-stats-flush 'rsyslog.out.stats.log'
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input_1
. $srcdir/diag.sh msleep 1100
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input_2
. $srcdir/diag.sh msleep 1100
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input_3
. $srcdir/diag.sh msleep 1100
. $srcdir/diag.sh wait-queueempty
. $srcdir/diag.sh content-check "foo 001 0"
. $srcdir/diag.sh content-check "bar 002 0"
. $srcdir/diag.sh content-check "baz 003 0"
. $srcdir/diag.sh content-check "foo 004 0"
. $srcdir/diag.sh content-check "baz 005 0"
. $srcdir/diag.sh content-check "foo 006 0"
echo doing shutdown
. $srcdir/diag.sh shutdown-when-empty
echo wait on shutdown
. $srcdir/diag.sh wait-shutdown-vg
. $srcdir/diag.sh check-exit-vg
# because dyn-metrics would be reset before it can accumulate and report high counts, sleep between msg-injection ensures that
. $srcdir/diag.sh custom-assert-content-missing 'baz=2' 'rsyslog.out.stats.log'
. $srcdir/diag.sh custom-assert-content-missing 'foo=2' 'rsyslog.out.stats.log'
. $srcdir/diag.sh custom-assert-content-missing 'foo=3' 'rsyslog.out.stats.log'
# but actual reported stats (aggregate) should match
. $srcdir/diag.sh first-column-sum-check 's/.*foo=\([0-9]\+\)/\1/g' 'foo=' 'rsyslog.out.stats.log' 3
. $srcdir/diag.sh first-column-sum-check 's/.*bar=\([0-9]\+\)/\1/g' 'bar=' 'rsyslog.out.stats.log' 1
. $srcdir/diag.sh first-column-sum-check 's/.*baz=\([0-9]\+\)/\1/g' 'baz=' 'rsyslog.out.stats.log' 2
. $srcdir/diag.sh exit

38
tests/dynstats_reset.sh Executable file
View File

@ -0,0 +1,38 @@
#!/bin/bash
# added 2015-11-13 by singh.janmejay
# This file is part of the rsyslog project, released under ASL 2.0
echo ===============================================================================
echo \[dynstats_reset.sh\]: test for gathering stats with a known-dyn-metrics reset inbetween
. $srcdir/diag.sh init
. $srcdir/diag.sh startup dynstats_reset.conf
. $srcdir/diag.sh wait-for-stats-flush 'rsyslog.out.stats.log'
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input_1
. $srcdir/diag.sh msleep 1100
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input_2
. $srcdir/diag.sh msleep 1100
. $srcdir/diag.sh injectmsg-litteral $srcdir/testsuites/dynstats_input_3
. $srcdir/diag.sh msleep 1100
. $srcdir/diag.sh wait-queueempty
. $srcdir/diag.sh content-check "foo 001 0"
. $srcdir/diag.sh content-check "bar 002 0"
. $srcdir/diag.sh content-check "baz 003 0"
. $srcdir/diag.sh content-check "foo 004 0"
. $srcdir/diag.sh content-check "baz 005 0"
. $srcdir/diag.sh content-check "foo 006 0"
echo doing shutdown
. $srcdir/diag.sh shutdown-when-empty
echo wait on shutdown
. $srcdir/diag.sh wait-shutdown
# because dyn-metrics would be reset before it can accumulate and report high counts, sleep between msg-injection ensures that
. $srcdir/diag.sh custom-assert-content-missing 'baz=2' 'rsyslog.out.stats.log'
. $srcdir/diag.sh custom-assert-content-missing 'foo=2' 'rsyslog.out.stats.log'
. $srcdir/diag.sh custom-assert-content-missing 'foo=3' 'rsyslog.out.stats.log'
# but actual reported stats (aggregate) should match
. $srcdir/diag.sh first-column-sum-check 's/.*foo=\([0-9]\+\)/\1/g' 'foo=' 'rsyslog.out.stats.log' 3
. $srcdir/diag.sh first-column-sum-check 's/.*bar=\([0-9]\+\)/\1/g' 'bar=' 'rsyslog.out.stats.log' 1
. $srcdir/diag.sh first-column-sum-check 's/.*baz=\([0-9]\+\)/\1/g' 'baz=' 'rsyslog.out.stats.log' 2
. $srcdir/diag.sh first-column-sum-check 's/.*new_metric_add=\([0-9]\+\)/\1/g' 'new_metric_add=' 'rsyslog.out.stats.log' 6
. $srcdir/diag.sh first-column-sum-check 's/.*ops_overflow=\([0-9]\+\)/\1/g' 'ops_overflow=' 'rsyslog.out.stats.log' 0
. $srcdir/diag.sh first-column-sum-check 's/.*no_metric=\([0-9]\+\)/\1/g' 'no_metric=' 'rsyslog.out.stats.log' 0
. $srcdir/diag.sh first-column-sum-check 's/.*metrics_purged=\([0-9]\+\)/\1/g' 'metrics_purged=' 'rsyslog.out.stats.log' 6
. $srcdir/diag.sh exit

15
tests/rscript_field-vg.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash
# added 2012-09-20 by rgerhards
# This file is part of the rsyslog project, released under ASL 2.0
echo ===============================================================================
echo \[rscript_field-vg.sh\]: testing rainerscript field\(\) function
. $srcdir/diag.sh init
. $srcdir/diag.sh startup-vg rscript_field.conf
. $srcdir/diag.sh injectmsg 0 5000
echo doing shutdown
. $srcdir/diag.sh shutdown-when-empty
echo wait on shutdown
. $srcdir/diag.sh wait-shutdown-vg
. $srcdir/diag.sh check-exit-vg
. $srcdir/diag.sh seq-check 0 4999
. $srcdir/diag.sh exit

View File

@ -0,0 +1,17 @@
$IncludeConfig diag-common.conf
ruleset(name="stats") {
action(type="omfile" file="./rsyslog.out.stats.log")
}
module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n")
dyn_stats(name="msg_stats")
set $.msg_prefix = field($msg, 32, 1);
set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix);
action(type="omfile" file="./rsyslog.out.log" template="outfmt")

View File

@ -0,0 +1,21 @@
$IncludeConfig diag-common.conf
ruleset(name="stats") {
action(type="omfile" file="./rsyslog.out.stats.log")
}
module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
template(name="outfmt" type="string" string="%msg%\n")
dyn_stats(name="msg_stats_resettable_on" resettable="on")
dyn_stats(name="msg_stats_resettable_off" resettable="off")
dyn_stats(name="msg_stats_resettable_default")
set $.msg_prefix = field($msg, 32, 1);
set $.x = dyn_inc("msg_stats_resettable_on", $.msg_prefix);
set $.y = dyn_inc("msg_stats_resettable_off", $.msg_prefix);
set $.z = dyn_inc("msg_stats_resettable_default", $.msg_prefix);
action(type="omfile" file="./rsyslog.out.log" template="outfmt")

View File

@ -0,0 +1,7 @@
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:prefix foo 001
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:prefix bar 002
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:prefix baz 003
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:prefix quux 004
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:prefix corge 005
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:prefix foo 006
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:prefix grault 007

View File

@ -0,0 +1,6 @@
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 001
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:bar 002
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:baz 003
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 004
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:baz 005
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 006

View File

@ -0,0 +1,2 @@
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 001
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:bar 002

View File

@ -0,0 +1,2 @@
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:baz 003
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 004

View File

@ -0,0 +1,2 @@
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:baz 005
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 006

View File

@ -0,0 +1,10 @@
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 001
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:bar 002
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:baz 003
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 004
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:baz 005
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 006
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:quux 007
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:corge 008
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:quux 009
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 010

View File

@ -0,0 +1,3 @@
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:corge 011
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:grault 012
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 013

View File

@ -0,0 +1,5 @@
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:corge 014
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:grault 015
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:quux 016
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 017
<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:corge 018

View File

@ -0,0 +1,17 @@
$IncludeConfig diag-common.conf
ruleset(name="stats") {
action(type="omfile" file="./rsyslog.out.stats.log")
}
module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n")
dyn_stats(name="msg_stats")
set $.msg_prefix = field($msg, 32, 2);
set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix);
action(type="omfile" file="./rsyslog.out.log" template="outfmt")

View File

@ -0,0 +1,22 @@
$IncludeConfig diag-common.conf
ruleset(name="stats") {
action(type="omfile" file="./rsyslog.out.stats.log")
}
module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n")
dyn_stats(name="msg_stats" unusedMetricLife="2" maxCardinality="3")
set $.msg_prefix = field($msg, 32, 1);
if (re_match($.msg_prefix, "foo|bar|baz|quux|corge|grault")) then {
set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix);
} else {
set $.increment_successful = -1;
}
action(type="omfile" file="./rsyslog.out.log" template="outfmt")

View File

@ -0,0 +1,21 @@
$IncludeConfig diag-common.conf
ruleset(name="stats") {
action(type="omfile" file="./rsyslog.out.stats.log")
}
module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n")
dyn_stats(name="msg_stats" unusedMetricLife="1")
set $.msg_prefix = field($msg, 32, 1);
if (re_match($.msg_prefix, "foo|bar|baz|quux|corge|grault")) then {
set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix);
} else {
set $.increment_successful = -1;
}
action(type="omfile" file="./rsyslog.out.log" template="outfmt")