Go to the documentation of this file.
45 #define STATS_WUT_TTS 3
48 #define STATS_MGMTT_TTS 8
92 static void *stats_thread_data = NULL;
94 static time_t stats_start_time;
98 static bool stats_enabled =
true;
112 static StatsTable stats_table = { NULL, NULL, 0, 0, 0, {0 , 0}};
114 static int stats_loggers_active = 1;
116 static uint16_t counters_global_id = 0;
120 return stats_enabled;
149 #if defined (UNITTESTS) || defined (FUZZ)
170 #if defined (UNITTESTS) || defined (FUZZ)
191 #if defined(UNITTESTS) || defined(FUZZ)
213 #if defined (UNITTESTS) || defined (FUZZ)
241 if (strcmp(node->
val,
"stats") == 0) {
242 return node->head.tqh_first;
252 static void StatsInitCtxPreOutput(
void)
259 stats_enabled =
false;
265 if (gstats == NULL) {
267 "Stats enabled through legacy stats.log. "
268 "See %s/configuration/suricata-yaml.html#stats",
273 if (interval != NULL)
276 "interval: \"%s\". Resetting to %d.",
291 const char *prefix = NULL;
292 if (
ConfGet(
"stats.decoder-events-prefix", &prefix) != 1) {
293 prefix =
"decoder.event";
300 static void StatsInitCtxPostOutput(
void)
304 time(&stats_start_time);
312 stats_loggers_active = 0;
317 SCLogWarning(
"stats are enabled but no loggers are active");
318 stats_enabled =
false;
330 static void StatsReleaseCtx(
void)
332 if (stats_ctx == NULL) {
333 SCLogDebug(
"Counter module has been disabled");
339 sts = stats_ctx->
sts;
341 while (sts != NULL) {
342 if (sts->
head != NULL)
353 counters_global_id = 0;
362 if (stats_table.
tstats != NULL) {
364 stats_table.
tstats = NULL;
367 if (stats_table.
stats != NULL) {
369 stats_table.
stats = NULL;
371 memset(&stats_table, 0,
sizeof(stats_table));
384 static void *StatsMgmtThread(
void *arg)
397 if (stats_ctx == NULL) {
399 "StatsInitCounterApi() has to be called first");
406 int r = tm->
ThreadInit(tv_local, NULL, &stats_thread_data);
407 if (r != 0 || stats_thread_data == NULL) {
409 "ThreadInit failed");
413 SCLogDebug(
"stats_thread_data %p", &stats_thread_data);
423 struct timeval cur_timev;
424 gettimeofday(&cur_timev, NULL);
426 cond_time.tv_sec += (stats_tts);
435 StatsOutput(tv_local);
449 "ThreadDeinit failed");
464 static void *StatsWakeupThread(
void *arg)
477 if (stats_ctx == NULL) {
479 "StatsInitCounterApi() has to be called first");
493 struct timeval cur_timev;
494 gettimeofday(&cur_timev, NULL);
516 if (
tv->
inq != NULL) {
577 static uint16_t StatsRegisterQualifiedCounter(
const char *name,
const char *tm_name,
579 int type_q, uint64_t (*Func)(
void))
586 if (name == NULL || pctx == NULL) {
587 SCLogDebug(
"Counter name, StatsPublicThreadContext NULL");
592 while (temp != NULL) {
595 if (strcmp(name, temp->
name) == 0) {
616 if (strrchr(name,
'.') != NULL) {
617 pc->
short_name = &name[strrchr(name,
'.') - name + 1];
656 void *td = stats_thread_data;
658 if (counters_global_id == 0)
661 if (stats_table.
nstats == 0) {
664 uint32_t nstats = counters_global_id;
666 stats_table.
nstats = nstats;
668 if (stats_table.
stats == NULL) {
670 SCLogError(
"could not alloc memory for stats");
677 if (stats_table.
tstats == NULL) {
679 SCLogError(
"could not alloc memory for stats");
686 const uint16_t max_id = counters_global_id;
692 struct CountersMergeTable {
696 } merge_table[max_id];
697 memset(&merge_table, 0x00,
698 max_id *
sizeof(
struct CountersMergeTable));
700 int thread = stats_ctx->
sts_cnt - 1;
705 sts = stats_ctx->
sts;
707 while (sts != NULL) {
715 struct CountersMergeTable thread_table[max_id];
716 memset(&thread_table, 0x00,
717 max_id *
sizeof(
struct CountersMergeTable));
722 SCLogDebug(
"Counter %s (%u:%u) value %"PRIu64,
725 thread_table[pc->
gid].type = pc->
type;
728 if (pc->
Func != NULL)
729 thread_table[pc->
gid].value = pc->
Func();
733 thread_table[pc->
gid].value = pc->
value;
745 for (uint16_t c = 0; c < max_id; c++) {
746 struct CountersMergeTable *e = &thread_table[c];
754 if (e->value > merge_table[c].value)
755 merge_table[c].value = e->value;
758 merge_table[c].value = e->value;
762 merge_table[c].value += e->value;
765 merge_table[c].updates += e->updates;
766 merge_table[c].type = e->type;
770 for (uint16_t c = 0; c < max_id; c++) {
771 struct CountersMergeTable *e = &thread_table[c];
788 if (e->value > 0 && e->updates > 0) {
789 r->
value = (uint64_t)(e->value / e->updates);
803 for (uint16_t x = 0; x < max_id; x++) {
809 struct CountersMergeTable *
m = &merge_table[x];
812 if (
m->value > table[x].value)
813 table[x].
value =
m->value;
816 if (
m->value > 0 &&
m->updates > 0) {
817 table[x].
value = (uint64_t)(
m->value /
m->updates);
821 table[x].
value +=
m->value;
827 if (stats_loggers_active) {
833 #ifdef BUILD_UNIX_SOCKET
836 TmEcode StatsOutputCounterSocket(json_t *cmd,
837 json_t *answer,
void *data)
839 json_t *message = NULL;
842 if (!stats_enabled) {
844 message = json_string(
"stats are disabled in the config");
849 message = json_string(
"stats not yet synchronized");
855 json_object_set_new(answer,
"message", message);
860 static void StatsLogSummary(
void)
862 if (!stats_enabled) {
869 for (uint32_t u = 0; u < st->
nstats; u++) {
871 if (name == NULL || strcmp(name,
"detect.alert") != 0)
887 BUG_ON(stats_ctx != NULL);
889 FatalError(
"Fatal error encountered in StatsInitCtx. Exiting...");
897 StatsInitCtxPreOutput();
902 StatsInitCtxPostOutput();
916 if (!stats_enabled) {
925 StatsWakeupThread, 1);
926 if (tv_wakeup == NULL) {
933 "StatsWakeupThread");
939 if (tv_mgmt == NULL) {
940 FatalError(
"TmThreadCreateMgmtThread failed");
945 "StatsWakeupThread");
963 uint16_t
id = StatsRegisterQualifiedCounter(name,
983 uint16_t
id = StatsRegisterQualifiedCounter(name,
1003 uint16_t
id = StatsRegisterQualifiedCounter(name,
1021 #if defined (UNITTESTS) || defined (FUZZ)
1022 if (stats_ctx == NULL)
1025 BUG_ON(stats_ctx == NULL);
1027 uint16_t
id = StatsRegisterQualifiedCounter(name, NULL,
1039 static uint32_t CountersIdHashFunc(
HashTable *ht,
void *data, uint16_t datalen)
1045 for (
int i = 0; i <
len; i++)
1052 static char CountersIdHashCompareFunc(
void *data1, uint16_t datalen1,
1053 void *data2, uint16_t datalen2)
1060 if (t1 == NULL || t2 == NULL)
1066 len1 = strlen(t1->
string);
1067 len2 = strlen(t2->
string);
1069 if (len1 == len2 && memcmp(t1->
string, t2->
string, len1) == 0) {
1076 static void CountersIdHashFreeFunc(
void *data)
1093 if (stats_ctx == NULL) {
1094 SCLogDebug(
"Counter module has been disabled");
1098 if (thread_name == NULL || pctx == NULL) {
1099 SCLogDebug(
"supplied argument(s) to StatsThreadRegister NULL");
1106 CountersIdHashCompareFunc,
1107 CountersIdHashFreeFunc);
1111 while (pc != NULL) {
1117 id->id = counters_global_id++;
1118 id->string = pc->
name;
1133 temp->
name = thread_name;
1136 stats_ctx->
sts = temp;
1153 static int StatsGetCounterArrayRange(uint16_t s_id, uint16_t e_id,
1160 if (pctx == NULL || pca == NULL) {
1165 if (s_id < 1 || e_id < 1 || s_id > e_id) {
1171 SCLogDebug(
"end id is greater than the max id for this tv");
1180 while (pc->
id != s_id)
1184 while ((pc != NULL) && (pc->
id <= e_id)) {
1207 if (pctx == NULL ||
private == NULL)
1210 return StatsGetCounterArrayRange(1, pctx->
curr_id, pctx,
private);
1216 StatsGetAllCountersArray(&(
tv)->perf_public_ctx, &(
tv)->perf_private_ctx);
1219 &(
tv)->perf_public_ctx);
1235 if (pca == NULL || pctx == NULL) {
1236 SCLogDebug(
"pca or pctx is NULL inside StatsUpdateCounterArray");
1242 for (uint32_t i = 1; i <= pca->
size; i++) {
1243 StatsCopyCounterValue(&pcae[i]);
1288 while (
head != NULL) {
1291 StatsReleaseCounter(pc);
1304 if (pca->
head != NULL) {
1335 static uint16_t RegisterCounter(
const char *name,
const char *tm_name,
1338 uint16_t
id = StatsRegisterQualifiedCounter(name, tm_name, pctx,
1343 static int StatsTestCounterReg02(
void)
1349 return RegisterCounter(NULL, NULL, &pctx) == 0;
1352 static int StatsTestCounterReg03(
void)
1359 result = RegisterCounter(
"t1",
"c1", &pctx);
1368 static int StatsTestCounterReg04(
void)
1375 RegisterCounter(
"t1",
"c1", &pctx);
1376 RegisterCounter(
"t2",
"c2", &pctx);
1377 RegisterCounter(
"t3",
"c3", &pctx);
1379 result = RegisterCounter(
"t1",
"c1", &pctx);
1388 static int StatsTestGetCntArray05(
void)
1403 static int StatsTestGetCntArray06(
void)
1422 static int StatsTestCntArraySize07(
void)
1443 StatsReleasePrivateThreadContext(pca);
1448 static int StatsTestUpdateCounter08(
void)
1467 StatsReleasePrivateThreadContext(pca);
1472 static int StatsTestUpdateCounter09(
void)
1495 StatsReleasePrivateThreadContext(pca);
1500 static int StatsTestUpdateGlobalCounter10(
void)
1506 uint16_t id1, id2, id3;
1530 StatsReleasePrivateThreadContext(pca);
1535 static int StatsTestCounterValues11(
void)
1541 uint16_t id1, id2, id3, id4;
1567 StatsReleasePrivateThreadContext(pca);
1580 UtRegisterTest(
"StatsTestGetCntArray05", StatsTestGetCntArray05);
1581 UtRegisterTest(
"StatsTestGetCntArray06", StatsTestGetCntArray06);
1582 UtRegisterTest(
"StatsTestCntArraySize07", StatsTestCntArraySize07);
1583 UtRegisterTest(
"StatsTestUpdateCounter08", StatsTestUpdateCounter08);
1584 UtRegisterTest(
"StatsTestUpdateCounter09", StatsTestUpdateCounter09);
1586 StatsTestUpdateGlobalCounter10);
1587 UtRegisterTest(
"StatsTestCounterValues11", StatsTestCounterValues11);
#define FROM_TIMEVAL(timev)
initialize a 'struct timespec' from a 'struct timeval'.
void StatsReleaseResources(void)
Releases the resources allotted by the Stats API.
const char * thread_name_counter_wakeup
TmEcode TmThreadSpawn(ThreadVars *tv)
Spawns a thread associated with the ThreadVars instance tv.
TmEcode TmThreadSetupOptions(ThreadVars *tv)
Set the thread options (cpu affinitythread). Priority should be already set by pthread_create.
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
per thread store of counters
StatsPublicThreadContext ** head
Holds the output interface context for the counter api.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
struct StatsRecord_ StatsRecord
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
void StatsSetupPostConfigPreOutput(void)
void TmThreadWaitForFlag(ThreadVars *tv, uint32_t flags)
Waits till the specified flag(s) is(are) set. We don't bother if the kill flag has been set or not on...
uint16_t StatsRegisterGlobalCounter(const char *name, uint64_t(*Func)(void))
Registers a counter, which represents a global value.
struct HtpBodyChunk_ * next
simple fifo queue for packets with mutex and cond Calling the mutex or triggering the cond is respons...
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
struct CountersIdType_ CountersIdType
Container to hold the counter variable.
const char * thread_name_counter_stats
#define SCSetThreadName(n)
void StatsSetUI64(ThreadVars *tv, uint16_t id, uint64_t x)
Sets a value of type double to the local counter.
#define TAILQ_FOREACH(var, head, field)
int StatsSetupPrivate(ThreadVars *tv)
ThreadVars * tv_root[TVT_MAX]
void StatsInit(void)
Initializes the perf counter api. Things are hard coded currently. More work to be done when we imple...
#define SCMUTEX_INITIALIZER
#define JSON_STATS_TOTALS
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
void HashTableFree(HashTable *ht)
StatsPrivateThreadContext perf_private_ctx
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
struct StatsThreadStore_ * next
const char * stats_decoder_events_prefix
void TmThreadsUnsetFlag(ThreadVars *tv, uint32_t flag)
Unset a thread flag.
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
void StatsDecr(ThreadVars *tv, uint16_t id)
Decrements the local counter.
uint16_t StatsRegisterMaxCounter(const char *name, struct ThreadVars_ *tv)
Registers a counter, whose value holds the maximum of all the values assigned to it.
#define PASS
Pass the test.
struct StatsCounter_ * next
void StatsSetupPostConfigPostOutput(void)
#define SCMutexUnlock(mut)
StatsPublicThreadContext perf_public_ctx
HashTable * counters_id_hash
void * HashTableLookup(HashTable *ht, void *data, uint16_t datalen)
Per thread variable structure.
void TmThreadTestThreadUnPaused(ThreadVars *tv)
Tests if the thread represented in the arg has been unpaused or not.
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
#define SCLogWarning(...)
Macro used to log WARNING messages.
int HashTableAdd(HashTable *ht, void *data, uint16_t datalen)
struct ThreadVars_ * next
Stats Context for a ThreadVars instance.
uint64_t StatsGetLocalCounterValue(ThreadVars *tv, uint16_t id)
Get the value of the local copy of the counter that hold this id.
#define SCCtrlMutexLock(mut)
json_t * StatsToJSON(const StatsTable *st, uint8_t flags)
turn StatsTable into a json object
TmModule tmm_modules[TMM_SIZE]
uint8_t thread_setup_flags
used to hold the private version of the counters registered
#define SCCtrlCondTimedwait
ThreadVars * TmThreadCreateMgmtThread(const char *name, void *(fn_p)(void *), int mucond)
Creates and returns the TV instance for a Management thread(MGMT). This function supports only custom...
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
#define SCMutexInit(mut, mutattrs)
StatsPublicThreadContext global_counter_ctx
Storage for local counters, with a link to the public counter used for syncs.
#define SCCtrlMutexUnlock(mut)
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
StatsPublicThreadContext * ctx
void StatsSpawnThreads(void)
Spawns the wakeup, and the management thread used by the stats api.
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
#define JSON_STATS_THREADS
int ConfGetChildValueBool(const ConfNode *base, const char *name, int *val)
int ConfUnixSocketIsEnable(void)
void StatsAddUI64(ThreadVars *tv, uint16_t id, uint64_t x)
Adds a value of type uint64_t to the local counter.
int OutputStatsLoggersRegistered(void)
#define SCLogError(...)
Macro used to log ERROR messages.
int StatsUpdateCounterArray(StatsPrivateThreadContext *pca, StatsPublicThreadContext *pctx)
the private stats store with the public stats store
int ConfValIsFalse(const char *val)
Check if a value is false.
HashTable * HashTableInit(uint32_t size, uint32_t(*Hash)(struct HashTable_ *, void *, uint16_t), char(*Compare)(void *, uint16_t, void *, uint16_t), void(*Free)(void *))
void StatsReleaseCounters(StatsCounter *head)
Releases counters.
const char * GetDocURL(void)
struct StatsGlobalContext_ StatsGlobalContext
Holds the output interface context for the counter api.
uint16_t StatsRegisterAvgCounter(const char *name, struct ThreadVars_ *tv)
Registers a counter, whose value holds the average of all the values assigned to it.
struct StatsThreadStore_ StatsThreadStore
per thread store of counters
bool stats_decoder_events
int TmThreadsCheckFlag(ThreadVars *tv, uint32_t flag)
Check if a thread flag is set.
uint16_t StatsRegisterCounter(const char *name, struct ThreadVars_ *tv)
Registers a normal, unqualified counter.
void StatsThreadCleanup(ThreadVars *tv)
TmEcode OutputStatsLog(ThreadVars *tv, void *thread_data, StatsTable *st)
void StatsRegisterTests(void)
const char * ConfNodeLookupChildValue(const ConfNode *node, const char *name)
Lookup the value of a child configuration node by name.