suricata
counters.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2025 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
22  * \author Victor Julien <victor@inliniac.net>
23  *
24  * Engine stats API
25  */
26 
27 #include "suricata-common.h"
28 #include "counters.h"
29 
30 #include "suricata.h"
31 #include "threadvars.h"
32 
33 #include "output.h"
34 #include "output-json-stats.h"
35 
36 #include "util-byte.h"
37 #include "util-conf.h"
38 #include "util-hash.h"
39 
40 #include "tm-threads.h"
41 #include "util-privs.h"
42 
43 /* Time interval for syncing the local counters with the global ones */
44 #define STATS_WUT_TTS 3
45 
46 /* Time interval at which the mgmt thread o/p the stats */
47 #define STATS_MGMTT_TTS 8
48 
49 /**
50  * \brief Different kinds of qualifier that can be used to modify the behaviour
51  * of the counter to be registered
52  */
53 enum StatsType {
59 };
60 
61 /**
62  * \brief per thread store of counters
63  */
64 typedef struct StatsThreadStore_ {
65  /** thread name used in output */
66  const char *name;
67 
69 
72 
73 /**
74  * \brief Holds the output interface context for the counter api
75  */
76 typedef struct StatsGlobalContext_ {
77  /** list of thread stores: one per thread plus one global */
80  int sts_cnt;
81 
83 
86 
87 static void *stats_thread_data = NULL;
88 static StatsGlobalContext *stats_ctx = NULL;
89 static time_t stats_start_time;
90 /** refresh interval in seconds */
91 static uint32_t stats_tts = STATS_MGMTT_TTS;
92 /** is the stats counter enabled? */
93 static bool stats_enabled = true;
94 
95 /**< add decoder events as stats? enabled by default */
97 const char *stats_decoder_events_prefix = "decoder.event";
98 /**< add stream events as stats? disabled by default */
99 bool stats_stream_events = false;
100 
101 static int StatsOutput(ThreadVars *tv);
102 static int StatsThreadRegister(const char *thread_name, StatsPublicThreadContext *);
103 static void StatsReleaseCounters(StatsCounter *head);
104 static int StatsUpdateCounterArray(StatsPrivateThreadContext *pca, StatsPublicThreadContext *pctx);
105 
106 /** stats table is filled each interval and passed to the
107  * loggers. Initialized at first use. */
108 static StatsTable stats_table = { NULL, NULL, 0, 0, 0, {0 , 0}};
109 static SCMutex stats_table_mutex = SCMUTEX_INITIALIZER;
110 static int stats_loggers_active = 1;
111 
112 static uint16_t counters_global_id = 0;
113 
114 bool StatsEnabled(void)
115 {
116  return stats_enabled;
117 }
118 
119 static void StatsPublicThreadContextInit(StatsPublicThreadContext *t)
120 {
121  SCSpinInit(&t->lock, 0);
122 }
123 
124 static void StatsPublicThreadContextCleanup(StatsPublicThreadContext *t)
125 {
126  SCSpinLock(&t->lock);
128  SCFree(t->pc_array);
129  StatsReleaseCounters(t->head);
130  t->head = NULL;
131  SC_ATOMIC_SET(t->sync_now, false);
132  t->curr_id = 0;
133  SCSpinUnlock(&t->lock);
134  SCSpinDestroy(&t->lock);
135 }
136 
137 /**
138  * \brief Adds a value of type uint64_t to the local counter.
139  *
140  * \param id ID of the counter as set by the API
141  * \param pca Counter array that holds the local counter for this TM
142  * \param x Value to add to this local counter
143  */
145 {
146  StatsPrivateThreadContext *pca = &stats->priv;
147 #if defined (UNITTESTS) || defined (FUZZ)
148  if (pca->initialized == 0)
149  return;
150 #endif
151 #ifdef DEBUG
152  BUG_ON((id.id < 1) || (id.id > pca->size));
153 #endif
154  pca->head[id.id].v += x;
155 }
156 
157 /**
158  * \brief Increments the local counter
159  *
160  * \param id Index of the counter in the counter array
161  * \param pca Counter array that holds the local counters for this TM
162  */
164 {
165  StatsPrivateThreadContext *pca = &stats->priv;
166 #if defined (UNITTESTS) || defined (FUZZ)
167  if (pca->initialized == 0)
168  return;
169 #endif
170 #ifdef DEBUG
171  BUG_ON((id.id < 1) || (id.id > pca->size));
172 #endif
173  pca->head[id.id].v++;
174 }
175 
176 /**
177  * \brief Decrements the local counter
178  *
179  * \param stats per thread counter structure
180  * \param id Index of the counter in the counter array
181  */
183 {
184  StatsPrivateThreadContext *pca = &stats->priv;
185 #if defined(UNITTESTS) || defined(FUZZ)
186  if (pca->initialized == 0)
187  return;
188 #endif
189 #ifdef DEBUG
190  BUG_ON((id.id < 1) || (id.id > pca->size));
191 #endif
192  pca->head[id.id].v--;
193 }
194 
195 /**
196  * \brief set, so overwrite, the value of the local counter
197  *
198  * \param stats per thread counter structure
199  * \param id Index of the local counter in the counter array
200  * \param x The value to set for the counter
201  */
203 {
204  StatsPrivateThreadContext *pca = &stats->priv;
205 #if defined (UNITTESTS) || defined (FUZZ)
206  if (pca->initialized == 0)
207  return;
208 #endif
209 #ifdef DEBUG
210  BUG_ON((id.id < 1) || (id.id > pca->size));
211 #endif
212  pca->head[id.id].v = x;
213 }
214 
215 /**
216  * \brief update the value of the localmax counter
217  *
218  * \param stats per thread counter structure
219  * \param id Index of the local counter in the counter array
220  * \param x The value to set for the counter
221  */
223 {
224  StatsPrivateThreadContext *pca = &stats->priv;
225 #if defined(UNITTESTS) || defined(FUZZ)
226  if (pca->initialized == 0)
227  return;
228 #endif
229 #ifdef DEBUG
230  BUG_ON((id.id < 1) || (id.id > pca->size));
231 #endif
232 
233  if ((int64_t)x > pca->head[id.id].v) {
234  pca->head[id.id].v = x;
235  }
236 }
237 
239 {
240  StatsPrivateThreadContext *pca = &stats->priv;
241 #if defined(UNITTESTS) || defined(FUZZ)
242  if (pca->initialized == 0)
243  return;
244 #endif
245 #ifdef DEBUG
246  BUG_ON((id.id < 1) || (id.id > pca->size));
247 #endif
248 
249  pca->head[id.id].v += x;
250  pca->head[id.id + 1].v++;
251 }
252 
253 static SCConfNode *GetConfig(void)
254 {
255  SCConfNode *stats = SCConfGetNode("stats");
256  if (stats != NULL)
257  return stats;
258 
259  SCConfNode *root = SCConfGetNode("outputs");
260  SCConfNode *node = NULL;
261  if (root != NULL) {
262  TAILQ_FOREACH(node, &root->head, next) {
263  if (strcmp(node->val, "stats") == 0) {
264  return node->head.tqh_first;
265  }
266  }
267  }
268  return NULL;
269 }
270 
271 /**
272  * \brief Initializes stats context
273  */
274 static void StatsInitCtxPreOutput(void)
275 {
276  SCEnter();
277  SCConfNode *stats = GetConfig();
278  if (stats != NULL) {
279  const char *enabled = SCConfNodeLookupChildValue(stats, "enabled");
280  if (enabled != NULL && SCConfValIsFalse(enabled)) {
281  stats_enabled = false;
282  SCLogDebug("Stats module has been disabled");
283  SCReturn;
284  }
285  /* warn if we are using legacy config to enable stats */
286  SCConfNode *gstats = SCConfGetNode("stats");
287  if (gstats == NULL) {
288  SCLogWarning("global stats config is missing. "
289  "Stats enabled through legacy stats.log. "
290  "See %s/configuration/suricata-yaml.html#stats",
291  GetDocURL());
292  }
293 
294  const char *interval = SCConfNodeLookupChildValue(stats, "interval");
295  if (interval != NULL)
296  if (StringParseUint32(&stats_tts, 10, 0, interval) < 0) {
297  SCLogWarning("Invalid value for "
298  "interval: \"%s\". Resetting to %d.",
299  interval, STATS_MGMTT_TTS);
300  stats_tts = STATS_MGMTT_TTS;
301  }
302 
303  int b;
304  int ret = SCConfGetChildValueBool(stats, "decoder-events", &b);
305  if (ret) {
306  stats_decoder_events = (b == 1);
307  }
308  ret = SCConfGetChildValueBool(stats, "stream-events", &b);
309  if (ret) {
310  stats_stream_events = (b == 1);
311  }
312 
313  const char *prefix = NULL;
314  if (SCConfGetNonNull("stats.decoder-events-prefix", &prefix) != 1) {
315  prefix = "decoder.event";
316  }
318  }
319  SCReturn;
320 }
321 
322 static void StatsInitCtxPostOutput(void)
323 {
324  SCEnter();
325  /* Store the engine start time */
326  time(&stats_start_time);
327 
328  /* init the lock used by StatsThreadStore */
329  if (SCMutexInit(&stats_ctx->sts_lock, NULL) != 0) {
330  FatalError("error initializing sts mutex");
331  }
332 
333  if (stats_enabled && !OutputStatsLoggersRegistered()) {
334  stats_loggers_active = 0;
335 
336  /* if the unix command socket is enabled we do the background
337  * stats sync just in case someone runs 'dump-counters' */
338  if (!ConfUnixSocketIsEnable()) {
339  SCLogWarning("stats are enabled but no loggers are active");
340  stats_enabled = false;
341  SCReturn;
342  }
343  }
344 
345  SCReturn;
346 }
347 
348 /**
349  * \brief Releases the resources allotted to the output context of the
350  * Stats API
351  */
352 static void StatsReleaseCtx(void)
353 {
354  if (stats_ctx == NULL) {
355  SCLogDebug("Counter module has been disabled");
356  return;
357  }
358 
359  StatsThreadStore *sts = NULL;
360  StatsThreadStore *temp = NULL;
361  sts = stats_ctx->sts;
362 
363  while (sts != NULL) {
364  temp = sts->next;
365  SCFree(sts);
366  sts = temp;
367  }
368 
369  if (stats_ctx->counters_id_hash != NULL) {
370  HashTableFree(stats_ctx->counters_id_hash);
371  stats_ctx->counters_id_hash = NULL;
372  counters_global_id = 0;
373  }
374 
375  StatsPublicThreadContextCleanup(&stats_ctx->global_counter_ctx);
376  SCFree(stats_ctx);
377  stats_ctx = NULL;
378 
379  SCMutexLock(&stats_table_mutex);
380  /* free stats table */
381  if (stats_table.tstats != NULL) {
382  SCFree(stats_table.tstats);
383  stats_table.tstats = NULL;
384  }
385 
386  if (stats_table.stats != NULL) {
387  SCFree(stats_table.stats);
388  stats_table.stats = NULL;
389  }
390  memset(&stats_table, 0, sizeof(stats_table));
391  SCMutexUnlock(&stats_table_mutex);
392 }
393 
394 /**
395  * \brief management thread. This thread is responsible for writing the stats
396  *
397  * \param arg thread var
398  *
399  * \retval NULL This is the value that is always returned
400  */
401 static void *StatsMgmtThread(void *arg)
402 {
403  ThreadVars *tv_local = (ThreadVars *)arg;
404 
405  SCSetThreadName(tv_local->name);
406 
407  if (tv_local->thread_setup_flags != 0)
408  TmThreadSetupOptions(tv_local);
409 
410  /* Set the threads capability */
411  tv_local->cap_flags = 0;
412  SCDropCaps(tv_local);
413 
414  if (stats_ctx == NULL) {
415  SCLogError("Stats API not init"
416  "StatsInitCounterApi() has to be called first");
418  return NULL;
419  }
420 
422  BUG_ON(tm->ThreadInit == NULL);
423  int r = tm->ThreadInit(tv_local, NULL, &stats_thread_data);
424  if (r != 0 || stats_thread_data == NULL) {
425  SCLogError("Stats API "
426  "ThreadInit failed");
428  return NULL;
429  }
430  SCLogDebug("stats_thread_data %p", &stats_thread_data);
431 
433  bool run = TmThreadsWaitForUnpause(tv_local);
434  while (run) {
435  struct timeval cur_timev;
436  gettimeofday(&cur_timev, NULL);
437  struct timespec cond_time = FROM_TIMEVAL(cur_timev);
438  cond_time.tv_sec += (stats_tts);
439 
440  /* wait for the set time, or until we are woken up by
441  * the shutdown procedure */
442  SCCtrlMutexLock(tv_local->ctrl_mutex);
443  while (1) {
444  if (TmThreadsCheckFlag(tv_local, THV_KILL)) {
445  break;
446  }
447  int rc = SCCtrlCondTimedwait(tv_local->ctrl_cond, tv_local->ctrl_mutex, &cond_time);
448  if (rc == ETIMEDOUT || rc < 0) {
449  break;
450  }
451  }
452  SCCtrlMutexUnlock(tv_local->ctrl_mutex);
453 
454  SCMutexLock(&stats_table_mutex);
455  StatsOutput(tv_local);
456  SCMutexUnlock(&stats_table_mutex);
457 
458  if (TmThreadsCheckFlag(tv_local, THV_KILL)) {
459  break;
460  }
461  }
462 
464  TmThreadWaitForFlag(tv_local, THV_DEINIT);
465 
466  r = tm->ThreadDeinit(tv_local, stats_thread_data);
467  if (r != TM_ECODE_OK) {
468  SCLogError("Stats Counter API "
469  "ThreadDeinit failed");
470  }
471 
472  TmThreadsSetFlag(tv_local, THV_CLOSED);
473  return NULL;
474 }
475 
477 {
478  StatsUpdateCounterArray(&stats->priv, &stats->pub);
479 }
480 
482 {
483  if (SC_ATOMIC_GET(stats->pub.sync_now)) {
484  StatsUpdateCounterArray(&stats->priv, &stats->pub);
485  }
486 }
487 
488 /**
489  * \brief Wake up thread. This thread wakes up every TTS(time to sleep) seconds
490  * and sets the flag for every ThreadVars' StatsPublicThreadContext
491  *
492  * \param arg is NULL always
493  *
494  * \retval NULL This is the value that is always returned
495  */
496 static void *StatsWakeupThread(void *arg)
497 {
498  ThreadVars *tv_local = (ThreadVars *)arg;
499 
500  SCSetThreadName(tv_local->name);
501 
502  if (tv_local->thread_setup_flags != 0)
503  TmThreadSetupOptions(tv_local);
504 
505  /* Set the threads capability */
506  tv_local->cap_flags = 0;
507  SCDropCaps(tv_local);
508 
509  if (stats_ctx == NULL) {
510  SCLogError("Stats API not init"
511  "StatsInitCounterApi() has to be called first");
513  return NULL;
514  }
515 
517  bool run = TmThreadsWaitForUnpause(tv_local);
518 
519  while (run) {
520  struct timeval cur_timev;
521  gettimeofday(&cur_timev, NULL);
522  struct timespec cond_time = FROM_TIMEVAL(cur_timev);
523  cond_time.tv_sec += STATS_WUT_TTS;
524 
525  /* wait for the set time, or until we are woken up by
526  * the shutdown procedure */
527  SCCtrlMutexLock(tv_local->ctrl_mutex);
528  while (1) {
529  if (TmThreadsCheckFlag(tv_local, THV_KILL)) {
530  break;
531  }
532  int rc = SCCtrlCondTimedwait(tv_local->ctrl_cond, tv_local->ctrl_mutex, &cond_time);
533  if (rc == ETIMEDOUT || rc < 0) {
534  break;
535  }
536  }
537  SCCtrlMutexUnlock(tv_local->ctrl_mutex);
538 
541  while (tv != NULL) {
542  if (tv->stats.pub.head == NULL) {
543  tv = tv->next;
544  continue;
545  }
546 
547  SC_ATOMIC_SET(tv->stats.pub.sync_now, true);
548 
549  if (tv->inq != NULL) {
550  PacketQueue *q = tv->inq->pq;
551  SCMutexLock(&q->mutex_q);
552  SCCondSignal(&q->cond_q);
553  SCMutexUnlock(&q->mutex_q);
554  }
555 
556  tv = tv->next;
557  }
558 
559  /* mgt threads for flow manager */
560  tv = tv_root[TVT_MGMT];
561  while (tv != NULL) {
562  if (tv->stats.pub.head == NULL) {
563  tv = tv->next;
564  continue;
565  }
566 
567  SC_ATOMIC_SET(tv->stats.pub.sync_now, true);
568 
569  tv = tv->next;
570  }
572 
573  if (TmThreadsCheckFlag(tv_local, THV_KILL)) {
574  break;
575  }
576  }
577 
579  TmThreadWaitForFlag(tv_local, THV_DEINIT);
580  TmThreadsSetFlag(tv_local, THV_CLOSED);
581  return NULL;
582 }
583 
584 /**
585  * \brief Releases a counter
586  *
587  * \param pc Pointer to the StatsCounter to be freed
588  */
589 static void StatsReleaseCounter(StatsCounter *pc)
590 {
591  if (pc != NULL) {
592  SCFree(pc);
593  }
594 }
595 
596 /** \internal
597  * \brief Get ID for counters referenced in a derive counter
598  * \retval id (>=1) or 0 on error
599  */
600 static uint16_t GetIdByName(const StatsPublicThreadContext *pctx, const char *name)
601 {
602  for (const StatsCounter *c = pctx->head; c != NULL; c = c->next) {
603  if (strcmp(name, c->name) == 0) {
604  return c->id;
605  }
606  }
607  return 0;
608 }
609 
610 /**
611  * \brief Registers a counter.
612  *
613  * \param name Name of the counter, to be registered
614  * \param pctx StatsPublicThreadContext for this tm-tv instance
615  * \param type_q Qualifier describing the type of counter to be registered
616  *
617  * \retval the counter id for the newly registered counter, or the already
618  * present counter on success
619  * \retval 0 on failure
620  */
621 static uint16_t StatsRegisterQualifiedCounter(const char *name, StatsPublicThreadContext *pctx,
622  enum StatsType type_q, uint64_t (*Func)(void), const char *dname1, const char *dname2)
623 {
624  StatsCounter **head = &pctx->head;
625  StatsCounter *temp = NULL;
626  StatsCounter *prev = NULL;
627  StatsCounter *pc = NULL;
628 
629  if (name == NULL || pctx == NULL) {
630  SCLogDebug("Counter name, StatsPublicThreadContext NULL");
631  return 0;
632  }
633 
634  temp = prev = *head;
635  while (temp != NULL) {
636  prev = temp;
637 
638  if (strcmp(name, temp->name) == 0) {
639  break;
640  }
641 
642  temp = temp->next;
643  }
644 
645  /* We already have a counter registered by this name */
646  if (temp != NULL)
647  return(temp->id);
648 
649  uint16_t did1 = 0;
650  uint16_t did2 = 0;
651  if (type_q == STATS_TYPE_DERIVE_DIV) {
652  did1 = GetIdByName(pctx, dname1);
653  did2 = GetIdByName(pctx, dname2);
654  if (did1 == 0 || did2 == 0) {
655  return 0;
656  }
657  }
658 
659  /* if we reach this point we don't have a counter registered by this name */
660  if ((pc = SCCalloc(1, sizeof(StatsCounter))) == NULL)
661  return 0;
662 
663  /* assign a unique id to this StatsCounter. The id is local to this
664  * thread context. Please note that the id start from 1, and not 0 */
665  if (type_q == STATS_TYPE_DERIVE_DIV) {
666  pc->id = ++pctx->derive_id;
667  } else {
668  pc->id = ++(pctx->curr_id);
669  }
670  /* for AVG counters we use 2 indices into the tables: one for values,
671  * the other to track updates. */
672  if (type_q == STATS_TYPE_AVERAGE)
673  ++(pctx->curr_id);
674  pc->name = name;
675 
676  /* Precalculate the short name */
677  if (strrchr(name, '.') != NULL) {
678  pc->short_name = &name[strrchr(name, '.') - name + 1];
679  }
680 
681  pc->type = type_q;
682  pc->Func = Func;
683  pc->did1 = did1;
684  pc->did2 = did2;
685 
686  /* we now add the counter to the list */
687  if (prev == NULL)
688  *head = pc;
689  else
690  prev->next = pc;
691 
692  return pc->id;
693 }
694 
695 /**
696  * \brief The output interface for the Stats API
697  */
698 static int StatsOutput(ThreadVars *tv)
699 {
700  const StatsThreadStore *sts = NULL;
701  void *td = stats_thread_data;
702 
703  if (counters_global_id == 0)
704  return -1;
705 
706  if (stats_table.nstats == 0) {
707  StatsThreadRegister("Global", &stats_ctx->global_counter_ctx);
708 
709  uint32_t nstats = counters_global_id;
710 
711  stats_table.nstats = nstats;
712  stats_table.stats = SCCalloc(stats_table.nstats, sizeof(StatsRecord));
713  if (stats_table.stats == NULL) {
714  stats_table.nstats = 0;
715  SCLogError("could not alloc memory for stats");
716  return -1;
717  }
718 
719  stats_table.ntstats = stats_ctx->sts_cnt;
720  uint32_t array_size = stats_table.nstats * sizeof(StatsRecord);
721  stats_table.tstats = SCCalloc(stats_table.ntstats, array_size);
722  if (stats_table.tstats == NULL) {
723  stats_table.ntstats = 0;
724  SCLogError("could not alloc memory for stats");
725  return -1;
726  }
727 
728  stats_table.start_time = stats_start_time;
729  }
730 
731  const uint16_t max_id = counters_global_id;
732  if (max_id == 0)
733  return -1;
734 
735  /** temporary local table to merge the per thread counters,
736  * especially needed for the average counters */
737  struct CountersMergeTable {
738  enum StatsType type;
739  int64_t value;
740  uint64_t updates;
741  } merge_table[max_id];
742  memset(&merge_table, 0x00,
743  max_id * sizeof(struct CountersMergeTable));
744 
745  int thread = stats_ctx->sts_cnt - 1;
746  StatsRecord *table = stats_table.stats;
747 
748  /* Loop through the thread counter stores. The global counters
749  * are in a separate store inside this list. */
750  sts = stats_ctx->sts;
751  SCLogDebug("sts %p", sts);
752  while (sts != NULL) {
753  DEBUG_VALIDATE_BUG_ON(thread < 0);
754 
755  SCLogDebug("Thread %d %s ctx %p", thread, sts->name, sts->ctx);
756 
757  /* temporary table for quickly storing the counters for this
758  * thread store, so that we can post process them outside
759  * of the thread store lock */
760  struct CountersMergeTable thread_table[max_id];
761  memset(&thread_table, 0x00,
762  max_id * sizeof(struct CountersMergeTable));
763 
764  StatsLocalCounter thread_table_from_private[max_id];
765  memset(&thread_table_from_private, 0x00, max_id * sizeof(StatsLocalCounter));
766 
767  /* copy private table to a local variable to loop it w/o lock */
768  bool skip = false;
769  SCSpinLock(&sts->ctx->lock);
770  const uint16_t table_size = sts->ctx->curr_id + sts->ctx->derive_id + 1;
771  if (sts->ctx->copy_of_private == NULL) {
772  skip = true;
773  } else {
774  memcpy(&thread_table_from_private, sts->ctx->copy_of_private,
775  table_size * sizeof(StatsLocalCounter));
776  }
777  SCSpinUnlock(&sts->ctx->lock);
778  if (skip)
779  goto next;
780 
781  /* loop counters and handle them. This includes the global counters, which
782  * access the StatsCounters but don't modify them. */
783  for (uint16_t i = 1; i < table_size; i++) {
784  DEBUG_VALIDATE_BUG_ON(i >= max_id); // help scan-build
785  const StatsCounter *pc = sts->ctx->pc_array[i];
786  thread_table[pc->gid].type = pc->type;
787 
788  table[pc->gid].name = pc->name;
789  table[pc->gid].short_name = pc->short_name;
790 
791  switch (pc->type) {
792  case STATS_TYPE_FUNC:
793  if (pc->Func != NULL)
794  thread_table[pc->gid].value = pc->Func();
795  break;
796  case STATS_TYPE_AVERAGE:
797  DEBUG_VALIDATE_BUG_ON(i + 1 >= max_id); // help scan-build
798  thread_table[pc->gid].value = thread_table_from_private[i].v;
799  thread_table[pc->gid].updates = thread_table_from_private[i + 1].v;
800  /* skip updates row */
801  i++;
802  break;
804  SCLogDebug("counter %u/%u is derived from counters %u / %u", pc->id, pc->gid,
805  pc->did1, pc->did2);
806  thread_table[pc->gid].value = thread_table_from_private[pc->did1].v;
807  thread_table[pc->gid].updates = thread_table_from_private[pc->did2].v;
808  break;
809  default:
810  SCLogDebug("Counter %s (%u:%u) value %" PRIu64, pc->name, pc->id, pc->gid,
811  thread_table_from_private[i].v);
812 
813  thread_table[pc->gid].value = thread_table_from_private[i].v;
814  break;
815  }
816  }
817 
818  /* update merge table */
819  for (uint16_t c = 0; c < max_id; c++) {
820  const struct CountersMergeTable *e = &thread_table[c];
821  /* thread only sets type if it has a counter
822  * of this type. */
823  if (e->type == 0)
824  continue;
825 
826  switch (e->type) {
827  case STATS_TYPE_MAXIMUM:
828  if (e->value > merge_table[c].value)
829  merge_table[c].value = e->value;
830  break;
831  case STATS_TYPE_FUNC:
832  merge_table[c].value = e->value;
833  break;
834  case STATS_TYPE_AVERAGE:
835  default:
836  merge_table[c].value += e->value;
837  break;
838  }
839  merge_table[c].updates += e->updates;
840  merge_table[c].type = e->type;
841  }
842 
843  /* update per thread stats table */
844  for (uint16_t c = 0; c < max_id; c++) {
845  const struct CountersMergeTable *e = &thread_table[c];
846  /* thread only sets type if it has a counter
847  * of this type. */
848  if (e->type == 0)
849  continue;
850 
851  uint32_t offset = (thread * stats_table.nstats) + c;
852  StatsRecord *r = &stats_table.tstats[offset];
853  /* xfer previous value to pvalue and reset value */
854  r->pvalue = r->value;
855  r->value = 0;
856  r->name = table[c].name;
857  r->short_name = table[c].short_name;
858  r->tm_name = sts->name;
859 
860  switch (e->type) {
861  case STATS_TYPE_AVERAGE:
863  if (e->value > 0 && e->updates > 0) {
864  r->value = (uint64_t)(e->value / e->updates);
865  }
866  break;
867  default:
868  r->value = e->value;
869  break;
870  }
871  }
872 
873  next:
874  sts = sts->next;
875  thread--;
876  }
877 
878  /* transfer 'merge table' to final stats table */
879  for (uint16_t x = 0; x < max_id; x++) {
880  /* xfer previous value to pvalue and reset value */
881  table[x].pvalue = table[x].value;
882  table[x].value = 0;
883  table[x].tm_name = "Total";
884 
885  const struct CountersMergeTable *m = &merge_table[x];
886  switch (m->type) {
887  case STATS_TYPE_MAXIMUM:
888  if (m->value > table[x].value)
889  table[x].value = m->value;
890  break;
891  case STATS_TYPE_AVERAGE:
893  if (m->value > 0 && m->updates > 0) {
894  table[x].value = (uint64_t)(m->value / m->updates);
895  }
896  break;
897  default:
898  table[x].value += m->value;
899  break;
900  }
901  }
902 
903  /* invoke logger(s) */
904  if (stats_loggers_active) {
905  OutputStatsLog(tv, td, &stats_table);
906  }
907  return 1;
908 }
909 
910 #ifdef BUILD_UNIX_SOCKET
911 /** \brief callback for getting stats into unix socket
912  */
913 TmEcode StatsOutputCounterSocket(json_t *cmd,
914  json_t *answer, void *data)
915 {
916  json_t *message = NULL;
917  TmEcode r = TM_ECODE_OK;
918 
919  if (!stats_enabled) {
920  r = TM_ECODE_FAILED;
921  message = json_string("stats are disabled in the config");
922  } else {
923  SCMutexLock(&stats_table_mutex);
924  if (stats_table.start_time == 0) {
925  r = TM_ECODE_FAILED;
926  message = json_string("stats not yet synchronized");
927  } else {
928  message = StatsToJSON(&stats_table, JSON_STATS_TOTALS|JSON_STATS_THREADS);
929  }
930  SCMutexUnlock(&stats_table_mutex);
931  }
932  json_object_set_new(answer, "message", message);
933  return r;
934 }
935 #endif /* BUILD_UNIX_SOCKET */
936 
937 static void StatsLogSummary(void)
938 {
939  if (!stats_enabled) {
940  return;
941  }
942  uint64_t alerts = 0;
943  SCMutexLock(&stats_table_mutex);
944  if (stats_table.start_time != 0) {
945  const StatsTable *st = &stats_table;
946  for (uint32_t u = 0; u < st->nstats; u++) {
947  const char *name = st->stats[u].name;
948  if (name == NULL || strcmp(name, "detect.alert") != 0)
949  continue;
950  alerts = st->stats[u].value;
951  break;
952  }
953  }
954  SCMutexUnlock(&stats_table_mutex);
955  SCLogInfo("Alerts: %"PRIu64, alerts);
956 }
957 
958 /**
959  * \brief Initializes the perf counter api. Things are hard coded currently.
960  * More work to be done when we implement multiple interfaces
961  */
962 void StatsInit(void)
963 {
964  BUG_ON(stats_ctx != NULL);
965  if ((stats_ctx = SCCalloc(1, sizeof(StatsGlobalContext))) == NULL) {
966  FatalError("Fatal error encountered in StatsInitCtx. Exiting...");
967  }
968 
969  StatsPublicThreadContextInit(&stats_ctx->global_counter_ctx);
970 }
971 
973 {
974  StatsInitCtxPreOutput();
975 }
976 
978 {
979  StatsInitCtxPostOutput();
980 }
981 
982 
983 /**
984  * \brief Spawns the wakeup, and the management thread used by the stats api
985  *
986  * The threads use the condition variable in the thread vars to control
987  * their wait loops to make sure the main thread can quickly kill them.
988  */
990 {
991  SCEnter();
992 
993  if (!stats_enabled) {
994  SCReturn;
995  }
996 
997  ThreadVars *tv_wakeup = NULL;
998  ThreadVars *tv_mgmt = NULL;
999 
1000  /* spawn the stats wakeup thread */
1002  StatsWakeupThread, 1);
1003  if (tv_wakeup == NULL) {
1004  FatalError("TmThreadCreateMgmtThread "
1005  "failed");
1006  }
1007 
1008  if (TmThreadSpawn(tv_wakeup) != 0) {
1009  FatalError("TmThreadSpawn failed for "
1010  "StatsWakeupThread");
1011  }
1012 
1013  /* spawn the stats mgmt thread */
1015  StatsMgmtThread, 1);
1016  if (tv_mgmt == NULL) {
1017  FatalError("TmThreadCreateMgmtThread failed");
1018  }
1019 
1020  if (TmThreadSpawn(tv_mgmt) != 0) {
1021  FatalError("TmThreadSpawn failed for "
1022  "StatsWakeupThread");
1023  }
1024 
1025  SCReturn;
1026 }
1027 
1028 /**
1029  * \brief Registers a normal, unqualified counter
1030  *
1031  * \param name Name of the counter, to be registered
1032  * \param tv Pointer to the ThreadVars instance for which the counter would
1033  * be registered
1034  *
1035  * \retval id Counter id for the newly registered counter, or the already
1036  * present counter
1037  */
1039 {
1040  uint16_t id =
1041  StatsRegisterQualifiedCounter(name, &stats->pub, STATS_TYPE_NORMAL, NULL, NULL, NULL);
1042  StatsCounterId s = { .id = id };
1043  return s;
1044 }
1045 
1046 /**
1047  * \brief Registers a counter, whose value holds the average of all the values
1048  * assigned to it.
1049  *
1050  * \param name Name of the counter, to be registered
1051  * \param tv Pointer to the ThreadVars instance for which the counter would
1052  * be registered
1053  *
1054  * \retval id Counter id for the newly registered counter, or the already
1055  * present counter
1056  */
1058 {
1059  uint16_t id =
1060  StatsRegisterQualifiedCounter(name, &stats->pub, STATS_TYPE_AVERAGE, NULL, NULL, NULL);
1061  StatsCounterAvgId s = { .id = id };
1062  return s;
1063 }
1064 
1065 /**
1066  * \brief Registers a counter, whose value holds the maximum of all the values
1067  * assigned to it.
1068  *
1069  * \param name Name of the counter, to be registered
1070  * \param tv Pointer to the ThreadVars instance for which the counter would
1071  * be registered
1072  *
1073  * \retval the counter id for the newly registered counter, or the already
1074  * present counter
1075  */
1077 {
1078  uint16_t id =
1079  StatsRegisterQualifiedCounter(name, &stats->pub, STATS_TYPE_MAXIMUM, NULL, NULL, NULL);
1080  StatsCounterMaxId s = { .id = id };
1081  return s;
1082 }
1083 
1084 /**
1085  * \brief Registers a counter, which represents a global value
1086  *
1087  * \param name Name of the counter, to be registered
1088  * \param Func Function Pointer returning a uint64_t
1089  *
1090  * \retval id Counter id for the newly registered counter, or the already
1091  * present counter
1092  */
1093 StatsCounterGlobalId StatsRegisterGlobalCounter(const char *name, uint64_t (*Func)(void))
1094 {
1095  StatsCounterGlobalId s = { .id = 0 };
1096 #if defined (UNITTESTS) || defined (FUZZ)
1097  if (stats_ctx == NULL)
1098  return s;
1099 #else
1100  BUG_ON(stats_ctx == NULL);
1101 #endif
1102  uint16_t id = StatsRegisterQualifiedCounter(
1103  name, &(stats_ctx->global_counter_ctx), STATS_TYPE_FUNC, Func, NULL, NULL);
1104  s.id = id;
1105  return s;
1106 }
1107 
1108 /**
1109  * \brief Registers a counter which tracks the result of the calculating the value
1110  * of counter dname1 divided by the value of the counter dname2
1111  *
1112  * \param name Name of the counter, to be registered
1113  * \param dname1 First counter name
1114  * \param dname2 Second counter name
1115  *
1116  * Both counters need to already be registered in this thread.
1117  *
1118  * \retval id Counter id for the newly registered counter, or the already
1119  * present counter
1120  */
1122  const char *name, const char *dname1, const char *dname2, StatsThreadContext *stats)
1123 {
1124  StatsCounterDeriveId s = { .id = 0 };
1125 #if defined(UNITTESTS) || defined(FUZZ)
1126  if (stats_ctx == NULL)
1127  return s;
1128 #else
1129  BUG_ON(stats_ctx == NULL);
1130 #endif
1131  uint16_t id = StatsRegisterQualifiedCounter(
1132  name, &stats->pub, STATS_TYPE_DERIVE_DIV, NULL, dname1, dname2);
1133  s.id = id;
1134  return s;
1135 }
1136 
1137 typedef struct CountersIdType_ {
1138  uint16_t id;
1139  const char *string;
1141 
1142 static uint32_t CountersIdHashFunc(HashTable *ht, void *data, uint16_t datalen)
1143 {
1144  CountersIdType *t = (CountersIdType *)data;
1145  uint32_t hash = 0;
1146  size_t len = strlen(t->string);
1147 
1148  for (size_t i = 0; i < len; i++)
1149  hash += u8_tolower((unsigned char)t->string[i]);
1150 
1151  hash = hash % ht->array_size;
1152  return hash;
1153 }
1154 
1155 static char CountersIdHashCompareFunc(void *data1, uint16_t datalen1,
1156  void *data2, uint16_t datalen2)
1157 {
1158  CountersIdType *t1 = (CountersIdType *)data1;
1159  CountersIdType *t2 = (CountersIdType *)data2;
1160 
1161  if (t1 == NULL || t2 == NULL)
1162  return 0;
1163 
1164  if (t1->string == NULL || t2->string == NULL)
1165  return 0;
1166 
1167  return strcmp(t1->string, t2->string) == 0;
1168 }
1169 
1170 static void CountersIdHashFreeFunc(void *data)
1171 {
1172  SCFree(data);
1173 }
1174 
1175 static int StatsThreadSetupPublic(StatsPublicThreadContext *pctx)
1176 {
1177  size_t array_size = pctx->curr_id + pctx->derive_id + 1;
1178  pctx->pc_array = SCCalloc(array_size, sizeof(StatsCounter *));
1179  if (pctx->pc_array == NULL) {
1180  return -1;
1181  }
1182  /* regular counters that get direct updates by their id as idx */
1183  for (StatsCounter *pc = pctx->head; pc != NULL; pc = pc->next) {
1184  if (pc->type != STATS_TYPE_DERIVE_DIV) {
1185  SCLogDebug("pc %s gid %u id %u", pc->name, pc->gid, pc->id);
1186  BUG_ON(pctx->pc_array[pc->id] != NULL);
1187  pctx->pc_array[pc->id] = pc;
1188  }
1189  }
1190  /* derive counters are not updated by the thread itself and will be put
1191  * at the end of the array */
1192  for (StatsCounter *pc = pctx->head; pc != NULL; pc = pc->next) {
1193  if (pc->type == STATS_TYPE_DERIVE_DIV) {
1194  uint16_t id = pctx->curr_id + pc->id;
1195  SCLogDebug("STATS_TYPE_DERIVE_DIV: pc %s gid %u pc->id %u id %u", pc->name, pc->gid,
1196  pc->id, id);
1197  BUG_ON(pctx->pc_array[id] != NULL);
1198  pctx->pc_array[id] = pc;
1199  }
1200  }
1201 
1202  SCLogDebug("array_size %u memory %" PRIu64, (uint32_t)array_size,
1203  (uint64_t)(array_size * sizeof(StatsLocalCounter)));
1204  pctx->copy_of_private = SCCalloc(array_size, sizeof(StatsLocalCounter));
1205  if (pctx->copy_of_private == NULL) {
1206  return -1;
1207  }
1208  return 0;
1209 }
1210 
1211 /** \internal
1212  * \brief Adds a TM to the clubbed TM table. Multiple instances of the same TM
1213  * are stacked together in a PCTMI container.
1214  *
1215  * \param tm_name Name of the tm to be added to the table
1216  * \param pctx StatsPublicThreadContext associated with the TM tm_name
1217  *
1218  * \retval 1 on success, 0 on failure
1219  */
1220 static int StatsThreadRegister(const char *thread_name, StatsPublicThreadContext *pctx)
1221 {
1222  if (stats_ctx == NULL) {
1223  return 1;
1224  }
1225 
1226  if (thread_name == NULL || pctx == NULL) {
1227  SCLogDebug("supplied argument(s) to StatsThreadRegister NULL");
1228  return 0;
1229  }
1230 
1231  SCMutexLock(&stats_ctx->sts_lock);
1232  SCLogDebug("thread %s", thread_name);
1233  if (stats_ctx->counters_id_hash == NULL) {
1234  stats_ctx->counters_id_hash = HashTableInit(256, CountersIdHashFunc,
1235  CountersIdHashCompareFunc,
1236  CountersIdHashFreeFunc);
1237  if (stats_ctx->counters_id_hash == NULL) {
1238  SCMutexUnlock(&stats_ctx->sts_lock);
1239  return 0;
1240  }
1241  }
1242  StatsCounter *pc = pctx->head;
1243  while (pc != NULL) {
1244  CountersIdType t = { 0, pc->name }, *id = NULL;
1245  id = HashTableLookup(stats_ctx->counters_id_hash, &t, sizeof(t));
1246  if (id == NULL) {
1247  id = SCCalloc(1, sizeof(*id));
1248  BUG_ON(id == NULL);
1249  id->id = counters_global_id++;
1250  id->string = pc->name;
1251  int r = HashTableAdd(stats_ctx->counters_id_hash, id, sizeof(*id));
1252  DEBUG_VALIDATE_BUG_ON(r < 0);
1253  if (r < 0) {
1254  SCMutexUnlock(&stats_ctx->sts_lock);
1255  return 0;
1256  }
1257  }
1258  pc->gid = id->id;
1259  pc = pc->next;
1260  }
1261 
1262  if (StatsThreadSetupPublic(pctx) != 0) {
1263  SCLogDebug("failed to setup StatsThreadSetupPublic");
1264  SCMutexUnlock(&stats_ctx->sts_lock);
1265  return 0;
1266  }
1267 
1268  StatsThreadStore *temp = NULL;
1269  if ((temp = SCCalloc(1, sizeof(StatsThreadStore))) == NULL) {
1270  SCMutexUnlock(&stats_ctx->sts_lock);
1271  return 0;
1272  }
1273 
1274  temp->ctx = pctx;
1275  temp->name = thread_name;
1276 
1277  temp->next = stats_ctx->sts;
1278  stats_ctx->sts = temp;
1279  stats_ctx->sts_cnt++;
1280  SCLogDebug("stats_ctx->sts %p", stats_ctx->sts);
1281 
1282  SCMutexUnlock(&stats_ctx->sts_lock);
1283  return 1;
1284 }
1285 
1286 /** \internal
1287  * \brief Returns a counter array for all counters registered for this tm
1288  * instance
1289  *
1290  * \param pctx Pointer to the tv's StatsPublicThreadContext
1291  *
1292  * \retval pca Pointer to a counter-array for all counter of this tm instance
1293  * on success; NULL on failure
1294  */
1295 static int StatsGetAllCountersArray(
1297 {
1298  if (pctx == NULL || private == NULL)
1299  return -1;
1300 
1301  private->size = pctx->curr_id + 1;
1302 
1303  private->head = SCCalloc(private->size, sizeof(StatsLocalCounter));
1304  if (private->head == NULL) {
1305  return -1;
1306  }
1307 
1308  private->initialized = 1;
1309  return 0;
1310 }
1311 
1312 int StatsSetupPrivate(StatsThreadContext *stats, const char *thread_name)
1313 {
1314  int r = StatsGetAllCountersArray(&stats->pub, &stats->priv);
1315  if (r < 0) {
1316  return -1;
1317  }
1318 
1319  r = StatsThreadRegister(thread_name, &stats->pub);
1320  if (r != 1) {
1321  return -2;
1322  }
1323  return 0;
1324 }
1325 
1326 static void StatsThreadInitPublic(StatsPublicThreadContext *pctx)
1327 {
1328  memset(pctx, 0x00, sizeof(*pctx));
1329  SCSpinInit(&pctx->lock, 0);
1330 }
1331 
1333 {
1334  StatsThreadInitPublic(&stats->pub);
1335 }
1336 
1337 /**
1338  * \brief the private stats store with the public stats store
1339  *
1340  * \param pca Pointer to the StatsPrivateThreadContext
1341  * \param pctx Pointer the tv's StatsPublicThreadContext
1342  *
1343  * \retval 1 on success
1344  * \retval -1 on error
1345  */
1346 static int StatsUpdateCounterArray(StatsPrivateThreadContext *pca, StatsPublicThreadContext *pctx)
1347 {
1348 
1349  if (pca == NULL || pctx == NULL) {
1350  SCLogDebug("pca or pctx is NULL inside StatsUpdateCounterArray");
1351  return -1;
1352  }
1353 
1354  if (pca->size > 0 && pctx->copy_of_private != NULL) {
1355  /* copy the whole table under lock to the public section
1356  * and release the lock. The stats thread will copy it from
1357  * there. */
1358  SCSpinLock(&pctx->lock);
1359  memcpy(pctx->copy_of_private, pca->head, pca->size * sizeof(StatsLocalCounter));
1360  SCSpinUnlock(&pctx->lock);
1361  }
1362  SC_ATOMIC_SET(pctx->sync_now, false);
1363  return 1;
1364 }
1365 
1366 /**
1367  * \brief Get the value of the local copy of the counter that hold this id.
1368  *
1369  * \param tv threadvars
1370  * \param id The counter id.
1371  *
1372  * \retval 0 on success.
1373  * \retval -1 on error.
1374  */
1376 {
1377  StatsPrivateThreadContext *pca = &stats->priv;
1378 #ifdef DEBUG
1379  BUG_ON((id.id < 1) || (id.id > pca->size));
1380 #endif
1381  return pca->head[id.id].v;
1382 }
1383 
1384 /**
1385  * \brief Releases the resources allotted by the Stats API
1386  */
1388 {
1389  StatsLogSummary();
1390  StatsReleaseCtx();
1391 }
1392 
1393 /**
1394  * \brief Releases counters
1395  *
1396  * \param head Pointer to the head of the list of perf counters that have to
1397  * be freed
1398  */
1399 static void StatsReleaseCounters(StatsCounter *head)
1400 {
1401  StatsCounter *pc = NULL;
1402 
1403  while (head != NULL) {
1404  pc = head;
1405  head = head->next;
1406  StatsReleaseCounter(pc);
1407  }
1408 }
1409 
1410 /** \internal
1411  * \brief Releases the StatsPrivateThreadContext allocated by the user,
1412  * for storing and updating local counter values
1413  *
1414  * \param pca Pointer to the StatsPrivateThreadContext
1415  */
1416 static void StatsReleasePrivateThreadContext(StatsPrivateThreadContext *pca)
1417 {
1418  if (pca != NULL) {
1419  if (pca->head != NULL) {
1420  SCFree(pca->head);
1421  pca->head = NULL;
1422  pca->size = 0;
1423  }
1424  pca->initialized = 0;
1425  }
1426 }
1427 
1429 {
1430  StatsPublicThreadContextCleanup(&stats->pub);
1431  StatsReleasePrivateThreadContext(&stats->priv);
1432 }
1433 
1434 /*----------------------------------Unit_Tests--------------------------------*/
1435 
1436 #ifdef UNITTESTS
1437 /** \internal
1438  * \brief Registers a normal, unqualified counter
1439  *
1440  * \param name Name of the counter, to be registered
1441  * \param type Datatype of this counter variable
1442  * \param pctx StatsPublicThreadContext corresponding to the tm_name key under which the
1443  * key has to be registered
1444  *
1445  * \retval id Counter id for the newly registered counter, or the already
1446  * present counter
1447  */
1448 static StatsCounterId RegisterCounter(
1449  const char *name, const char *tm_name, StatsPublicThreadContext *pctx)
1450 {
1451  uint16_t id = StatsRegisterQualifiedCounter(name, pctx, STATS_TYPE_NORMAL, NULL, NULL, NULL);
1452  StatsCounterId s = { .id = id };
1453  return s;
1454 }
1455 
1456 static int StatsTestCounterReg02(void)
1457 {
1459  StatsThreadInitPublic(&pctx);
1460 
1461  StatsCounterId id = RegisterCounter(NULL, NULL, &pctx);
1462  FAIL_IF_NOT(id.id == 0);
1463  PASS;
1464 }
1465 
1466 static int StatsTestCounterReg03(void)
1467 {
1469  StatsThreadInitPublic(&pctx);
1470 
1471  StatsCounterId id = RegisterCounter("t1", "c1", &pctx);
1472  FAIL_IF_NOT(id.id == 1);
1473 
1474  StatsReleaseCounters(pctx.head);
1475  PASS;
1476 }
1477 
1478 static int StatsTestCounterReg04(void)
1479 {
1481  StatsThreadInitPublic(&pctx);
1482 
1483  StatsCounterId c1 = RegisterCounter("t1", "c1", &pctx);
1484  FAIL_IF_NOT(c1.id == 1);
1485  StatsCounterId c2 = RegisterCounter("t2", "c2", &pctx);
1486  FAIL_IF_NOT(c2.id == 2);
1487  StatsCounterId c3 = RegisterCounter("t3", "c3", &pctx);
1488  FAIL_IF_NOT(c3.id == 3);
1489  StatsCounterId id = RegisterCounter("t1", "c1", &pctx);
1490  FAIL_IF_NOT(id.id == 1);
1491 
1492  StatsReleaseCounters(pctx.head);
1493  PASS;
1494 }
1495 
1496 static int StatsTestGetCntArray05(void)
1497 {
1498  ThreadVars tv;
1499  memset(&tv, 0, sizeof(ThreadVars));
1501  StatsCounterId c1 = RegisterCounter("t1", "c1", &tv.stats.pub);
1502  FAIL_IF(c1.id != 1);
1503  int r = StatsGetAllCountersArray(NULL, &tv.stats.priv);
1504  FAIL_IF_NOT(r == -1);
1506  PASS;
1507 }
1508 
1509 static int StatsTestGetCntArray06(void)
1510 {
1511  ThreadVars tv;
1512  memset(&tv, 0, sizeof(ThreadVars));
1514  StatsCounterId c1 = RegisterCounter("t1", "c1", &tv.stats.pub);
1515  FAIL_IF(c1.id != 1);
1516  StatsThreadSetupPublic(&tv.stats.pub);
1517  int r = StatsGetAllCountersArray(&tv.stats.pub, &tv.stats.priv);
1518  FAIL_IF_NOT(r == 0);
1520  PASS;
1521 }
1522 
1523 static int StatsTestCntArraySize07(void)
1524 {
1525  ThreadVars tv;
1526  memset(&tv, 0, sizeof(ThreadVars));
1528  StatsPrivateThreadContext *pca = NULL;
1529 
1530  StatsCounterId id1 = RegisterCounter("t1", "c1", &tv.stats.pub);
1531  StatsCounterId id2 = RegisterCounter("t2", "c2", &tv.stats.pub);
1532 
1533  StatsThreadSetupPublic(&tv.stats.pub);
1534  StatsGetAllCountersArray(&tv.stats.pub, &tv.stats.priv);
1535  pca = &tv.stats.priv;
1536 
1537  StatsCounterIncr(&tv.stats, id1);
1538  StatsCounterIncr(&tv.stats, id2);
1539 
1540  FAIL_IF_NOT(pca->size == 3);
1541 
1543  PASS;
1544 }
1545 
1546 static int StatsTestUpdateCounter08(void)
1547 {
1548  ThreadVars tv;
1549  memset(&tv, 0, sizeof(ThreadVars));
1551  StatsCounterId c1 = RegisterCounter("t1", "c1", &tv.stats.pub);
1552  StatsThreadSetupPublic(&tv.stats.pub);
1553  StatsGetAllCountersArray(&tv.stats.pub, &tv.stats.priv);
1555 
1556  StatsCounterIncr(&tv.stats, c1);
1557  StatsCounterAddI64(&tv.stats, c1, 100);
1558  FAIL_IF_NOT(pca->head[c1.id].v == 101);
1559 
1561  PASS;
1562 }
1563 
1564 static int StatsTestUpdateCounter09(void)
1565 {
1566  ThreadVars tv;
1567  memset(&tv, 0, sizeof(ThreadVars));
1569 
1570  StatsCounterId c1 = RegisterCounter("t1", "c1", &tv.stats.pub);
1571  RegisterCounter("t2", "c2", &tv.stats.pub);
1572  RegisterCounter("t3", "c3", &tv.stats.pub);
1573  RegisterCounter("t4", "c4", &tv.stats.pub);
1574  StatsCounterId c5 = RegisterCounter("t5", "c5", &tv.stats.pub);
1575 
1576  StatsThreadSetupPublic(&tv.stats.pub);
1577  StatsGetAllCountersArray(&tv.stats.pub, &tv.stats.priv);
1579 
1580  StatsCounterIncr(&tv.stats, c5);
1581  StatsCounterAddI64(&tv.stats, c5, 100);
1582 
1583  FAIL_IF_NOT(pca->head[c1.id].v == 0);
1584  FAIL_IF_NOT(pca->head[c5.id].v == 101);
1585 
1587  PASS;
1588 }
1589 
1590 static int StatsTestUpdateGlobalCounter10(void)
1591 {
1592  ThreadVars tv;
1593  memset(&tv, 0, sizeof(ThreadVars));
1595 
1596  StatsCounterId c1 = RegisterCounter("t1", "c1", &tv.stats.pub);
1597  StatsCounterId c2 = RegisterCounter("t2", "c2", &tv.stats.pub);
1598  StatsCounterId c3 = RegisterCounter("t3", "c3", &tv.stats.pub);
1599 
1600  StatsThreadSetupPublic(&tv.stats.pub);
1601  StatsGetAllCountersArray(&tv.stats.pub, &tv.stats.priv);
1603 
1604  StatsCounterIncr(&tv.stats, c1);
1605  StatsCounterAddI64(&tv.stats, c2, 100);
1606  StatsCounterIncr(&tv.stats, c3);
1607  StatsCounterAddI64(&tv.stats, c3, 100);
1608 
1609  StatsUpdateCounterArray(pca, &tv.stats.pub);
1610 
1612  FAIL_IF_NOT(100 == tv.stats.pub.copy_of_private[c2.id].v);
1613  FAIL_IF_NOT(101 == tv.stats.pub.copy_of_private[c3.id].v);
1614 
1616  PASS;
1617 }
1618 
1619 static int StatsTestCounterValues11(void)
1620 {
1621  ThreadVars tv;
1622  memset(&tv, 0, sizeof(ThreadVars));
1624 
1625  StatsCounterId c1 = RegisterCounter("t1", "c1", &tv.stats.pub);
1626  StatsCounterId c2 = RegisterCounter("t2", "c2", &tv.stats.pub);
1627  StatsCounterId c3 = RegisterCounter("t3", "c3", &tv.stats.pub);
1628  StatsCounterId c4 = RegisterCounter("t4", "c4", &tv.stats.pub);
1629 
1630  StatsThreadSetupPublic(&tv.stats.pub);
1631  StatsGetAllCountersArray(&tv.stats.pub, &tv.stats.priv);
1633 
1634  StatsCounterIncr(&tv.stats, c1);
1635  StatsCounterAddI64(&tv.stats, c2, 256);
1636  StatsCounterAddI64(&tv.stats, c3, 257);
1637  StatsCounterAddI64(&tv.stats, c4, 16843024);
1638 
1639  StatsUpdateCounterArray(pca, &tv.stats.pub);
1640 
1642  FAIL_IF_NOT(256 == tv.stats.pub.copy_of_private[c2.id].v);
1643  FAIL_IF_NOT(257 == tv.stats.pub.copy_of_private[c3.id].v);
1644  FAIL_IF_NOT(16843024 == tv.stats.pub.copy_of_private[c4.id].v);
1645 
1647  PASS;
1648 }
1649 
1650 #endif
1651 
1653 {
1654 #ifdef UNITTESTS
1655  UtRegisterTest("StatsTestCounterReg02", StatsTestCounterReg02);
1656  UtRegisterTest("StatsTestCounterReg03", StatsTestCounterReg03);
1657  UtRegisterTest("StatsTestCounterReg04", StatsTestCounterReg04);
1658  UtRegisterTest("StatsTestGetCntArray05", StatsTestGetCntArray05);
1659  UtRegisterTest("StatsTestGetCntArray06", StatsTestGetCntArray06);
1660  UtRegisterTest("StatsTestCntArraySize07", StatsTestCntArraySize07);
1661  UtRegisterTest("StatsTestUpdateCounter08", StatsTestUpdateCounter08);
1662  UtRegisterTest("StatsTestUpdateCounter09", StatsTestUpdateCounter09);
1663  UtRegisterTest("StatsTestUpdateGlobalCounter10",
1664  StatsTestUpdateGlobalCounter10);
1665  UtRegisterTest("StatsTestCounterValues11", StatsTestCounterValues11);
1666 #endif
1667 }
StatsPublicThreadContext_::lock
SCSpinlock lock
Definition: counters.h:115
util-byte.h
tm-threads.h
FROM_TIMEVAL
#define FROM_TIMEVAL(timev)
initialize a 'struct timespec' from a 'struct timeval'.
Definition: util-time.h:124
StatsReleaseResources
void StatsReleaseResources(void)
Releases the resources allotted by the Stats API.
Definition: counters.c:1387
StatsRegisterGlobalCounter
StatsCounterGlobalId StatsRegisterGlobalCounter(const char *name, uint64_t(*Func)(void))
Registers a counter, which represents a global value.
Definition: counters.c:1093
thread_name_counter_wakeup
const char * thread_name_counter_wakeup
Definition: runmodes.c:75
StatsTable_::ntstats
uint32_t ntstats
Definition: output-stats.h:43
len
uint8_t len
Definition: app-layer-dnp3.h:2
StatsCounterMaxUpdateI64
void StatsCounterMaxUpdateI64(StatsThreadContext *stats, StatsCounterMaxId id, int64_t x)
update the value of the localmax counter
Definition: counters.c:222
TmThreadSpawn
TmEcode TmThreadSpawn(ThreadVars *tv)
Spawns a thread associated with the ThreadVars instance tv.
Definition: tm-threads.c:1710
SCSpinDestroy
#define SCSpinDestroy
Definition: threads-debug.h:240
TmThreadSetupOptions
TmEcode TmThreadSetupOptions(ThreadVars *tv)
Set the thread options (cpu affinitythread). Priority should be already set by pthread_create.
Definition: tm-threads.c:873
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
ThreadVars_::name
char name[16]
Definition: threadvars.h:64
StatsSyncCountersIfSignalled
void StatsSyncCountersIfSignalled(StatsThreadContext *stats)
Definition: counters.c:481
StatsThreadStore_
per thread store of counters
Definition: counters.c:64
StatsGlobalContext_
Holds the output interface context for the counter api.
Definition: counters.c:76
SC_ATOMIC_SET
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
Definition: util-atomic.h:386
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:101
StatsRecord
struct StatsRecord_ StatsRecord
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
StatsRegisterCounter
StatsCounterId StatsRegisterCounter(const char *name, StatsThreadContext *stats)
Registers a normal, unqualified counter.
Definition: counters.c:1038
TmThreadsSetFlag
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
Definition: tm-threads.c:102
StatsSetupPostConfigPreOutput
void StatsSetupPostConfigPreOutput(void)
Definition: counters.c:972
TmThreadWaitForFlag
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...
Definition: tm-threads.c:1830
STATS_MGMTT_TTS
#define STATS_MGMTT_TTS
Definition: counters.c:47
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
StatsCounter_::type
int type
Definition: counters.h:56
stats_stream_events
bool stats_stream_events
Definition: counters.c:99
name
const char * name
Definition: detect-engine-proto.c:47
PacketQueue_
simple fifo queue for packets with mutex and cond Calling the mutex or triggering the cond is respons...
Definition: packet-queue.h:49
TMM_STATSLOGGER
@ TMM_STATSLOGGER
Definition: tm-threads-common.h:61
THV_DEINIT
#define THV_DEINIT
Definition: threadvars.h:44
type
uint8_t type
Definition: decode-sctp.h:0
CountersIdType
struct CountersIdType_ CountersIdType
StatsCounter_
Container to hold the counter variable.
Definition: counters.h:55
thread_name_counter_stats
const char * thread_name_counter_stats
Definition: runmodes.c:74
Tmq_::pq
PacketQueue * pq
Definition: tm-queues.h:36
SCSetThreadName
#define SCSetThreadName(n)
Definition: threads.h:305
util-hash.h
StatsRecord_
Definition: output-stats.h:31
StatsPublicThreadContext_::copy_of_private
StatsLocalCounter * copy_of_private
Definition: counters.h:112
THV_RUNNING
#define THV_RUNNING
Definition: threadvars.h:54
StatsCounter_::name
const char * name
Definition: counters.h:74
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
SCConfGetChildValueBool
int SCConfGetChildValueBool(const SCConfNode *base, const char *name, int *val)
Definition: conf.c:541
StatsCounter_::did1
uint16_t did1
Definition: counters.h:66
StatsCounter_::Func
uint64_t(* Func)(void)
Definition: counters.h:71
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
HashTable_
Definition: util-hash.h:35
u8_tolower
#define u8_tolower(c)
Definition: suricata-common.h:458
tv_root
ThreadVars * tv_root[TVT_MAX]
Definition: tm-threads.c:83
SCSpinLock
#define SCSpinLock
Definition: threads-debug.h:236
SCConfValIsFalse
int SCConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:602
StatsInit
void StatsInit(void)
Initializes the perf counter api. Things are hard coded currently. More work to be done when we imple...
Definition: counters.c:962
STATS_TYPE_AVERAGE
@ STATS_TYPE_AVERAGE
Definition: counters.c:55
util-privs.h
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:122
CountersIdType_::string
const char * string
Definition: counters.c:1139
SCDropCaps
#define SCDropCaps(...)
Definition: util-privs.h:89
StatsCounterId
Definition: counters.h:30
m
SCMutex m
Definition: flow-hash.h:6
SCConfNodeLookupChildValue
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:877
JSON_STATS_TOTALS
#define JSON_STATS_TOTALS
Definition: output-json-stats.h:29
StatsRecord_::pvalue
int64_t pvalue
Definition: output-stats.h:36
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
STATS_TYPE_FUNC
@ STATS_TYPE_FUNC
Definition: counters.c:57
StatsRegisterAvgCounter
StatsCounterAvgId StatsRegisterAvgCounter(const char *name, StatsThreadContext *stats)
Registers a counter, whose value holds the average of all the values assigned to it.
Definition: counters.c:1057
StatsCounterDecr
void StatsCounterDecr(StatsThreadContext *stats, StatsCounterId id)
Decrements the local counter.
Definition: counters.c:182
TVT_MGMT
@ TVT_MGMT
Definition: tm-threads-common.h:89
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
HashTableFree
void HashTableFree(HashTable *ht)
Free a HashTable and all its contents.
Definition: util-hash.c:111
ThreadVars_::cap_flags
uint8_t cap_flags
Definition: threadvars.h:79
HashTable_::array_size
uint32_t array_size
Definition: util-hash.h:37
TmModule_::ThreadDeinit
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition: tm-modules.h:53
PacketQueue_::mutex_q
SCMutex mutex_q
Definition: packet-queue.h:56
StatsThreadStore_::next
struct StatsThreadStore_ * next
Definition: counters.c:70
stats_decoder_events_prefix
const char * stats_decoder_events_prefix
Definition: counters.c:97
THV_RUNNING_DONE
#define THV_RUNNING_DONE
Definition: threadvars.h:45
StatsCounterAvgAddI64
void StatsCounterAvgAddI64(StatsThreadContext *stats, StatsCounterAvgId id, int64_t x)
Definition: counters.c:238
STATS_TYPE_MAXIMUM
@ STATS_TYPE_MAXIMUM
Definition: counters.c:56
counters.h
StatsCounter_::short_name
const char * short_name
Definition: counters.h:75
CountersIdType_
Definition: counters.c:1137
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
StatsCounter_::next
struct StatsCounter_ * next
Definition: counters.h:78
StatsCounterMaxId
Definition: counters.h:38
StatsSetupPostConfigPostOutput
void StatsSetupPostConfigPostOutput(void)
Definition: counters.c:977
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:120
StatsGlobalContext_::counters_id_hash
HashTable * counters_id_hash
Definition: counters.c:82
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
HashTableLookup
void * HashTableLookup(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:193
StatsRecord_::name
const char * name
Definition: output-stats.h:32
SCConfGetNonNull
int SCConfGetNonNull(const char *name, const char **vptr)
Retrieve the non-null value of a configuration node.
Definition: conf.c:380
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
StatsThreadStore_::name
const char * name
Definition: counters.c:66
THV_KILL
#define THV_KILL
Definition: threadvars.h:39
StatsThreadContext_::pub
StatsPublicThreadContext pub
Definition: counters.h:132
StatsCounterIncr
void StatsCounterIncr(StatsThreadContext *stats, StatsCounterId id)
Increments the local counter.
Definition: counters.c:163
SCSpinUnlock
#define SCSpinUnlock
Definition: threads-debug.h:238
StringParseUint32
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:268
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:262
HashTableAdd
int HashTableAdd(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:131
ThreadVars_::next
struct ThreadVars_ * next
Definition: threadvars.h:123
StatsPublicThreadContext_
Stats Context for a ThreadVars instance.
Definition: counters.h:92
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:322
StatsTable_
Definition: output-stats.h:39
tv_root_lock
SCMutex tv_root_lock
Definition: tm-threads.c:86
StatsRecord_::value
int64_t value
Definition: output-stats.h:35
SCReturn
#define SCReturn
Definition: util-debug.h:286
SCCtrlMutexLock
#define SCCtrlMutexLock(mut)
Definition: threads-debug.h:377
StatsToJSON
json_t * StatsToJSON(const StatsTable *st, uint8_t flags)
turn StatsTable into a json object
Definition: output-json-stats.c:209
CountersIdType_::id
uint16_t id
Definition: counters.c:1138
tmm_modules
TmModule tmm_modules[TMM_SIZE]
Definition: tm-modules.c:29
ThreadVars_::ctrl_cond
SCCtrlCondT * ctrl_cond
Definition: threadvars.h:128
StatsCounterGlobalId::id
uint16_t id
Definition: counters.h:43
StatsCounter_::id
uint16_t id
Definition: counters.h:59
ThreadVars_::thread_setup_flags
uint8_t thread_setup_flags
Definition: threadvars.h:67
TmEcode
TmEcode
Definition: tm-threads-common.h:80
STATS_TYPE_DERIVE_DIV
@ STATS_TYPE_DERIVE_DIV
Definition: counters.c:58
StatsTable_::start_time
time_t start_time
Definition: output-stats.h:44
StatsPrivateThreadContext_
used to hold the private version of the counters registered
Definition: counters.h:121
SCCtrlCondTimedwait
#define SCCtrlCondTimedwait
Definition: threads-debug.h:386
StatsSetupPrivate
int StatsSetupPrivate(StatsThreadContext *stats, const char *thread_name)
Definition: counters.c:1312
PacketQueue_::cond_q
SCCondT cond_q
Definition: packet-queue.h:57
TmThreadCreateMgmtThread
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...
Definition: tm-threads.c:1103
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:232
SCMutexInit
#define SCMutexInit(mut, mutattrs)
Definition: threads-debug.h:116
STATS_WUT_TTS
#define STATS_WUT_TTS
Definition: counters.c:44
Flow_::next
struct Flow_ * next
Definition: flow.h:406
StatsGlobalContext_::global_counter_ctx
StatsPublicThreadContext global_counter_ctx
Definition: counters.c:84
StatsTable_::stats
StatsRecord * stats
Definition: output-stats.h:40
TmModule_
Definition: tm-modules.h:47
StatsThreadInit
void StatsThreadInit(StatsThreadContext *stats)
Definition: counters.c:1332
TVT_PPT
@ TVT_PPT
Definition: tm-threads-common.h:88
StatsCounterGlobalId
Definition: counters.h:42
StatsGlobalContext_::sts_lock
SCMutex sts_lock
Definition: counters.c:79
THV_INIT_DONE
#define THV_INIT_DONE
Definition: threadvars.h:36
StatsLocalCounter_
counter type for local (private) increments. For AVG counters we use 2 to track values and updates.
Definition: counters.h:85
SCCtrlMutexUnlock
#define SCCtrlMutexUnlock(mut)
Definition: threads-debug.h:379
SCCondSignal
#define SCCondSignal
Definition: threads-debug.h:140
ThreadVars_::inq
Tmq * inq
Definition: threadvars.h:88
util-conf.h
StatsGlobalContext_::sts_cnt
int sts_cnt
Definition: counters.c:80
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
suricata-common.h
output-json-stats.h
TmThreadsWaitForUnpause
bool TmThreadsWaitForUnpause(ThreadVars *tv)
Wait for a thread to become unpaused.
Definition: tm-threads.c:371
StatsCounterMaxId::id
uint16_t id
Definition: counters.h:39
StatsPublicThreadContext_::pc_array
const StatsCounter ** pc_array
Definition: counters.h:110
StatsThreadStore_::ctx
StatsPublicThreadContext * ctx
Definition: counters.c:68
StatsEnabled
bool StatsEnabled(void)
Definition: counters.c:114
StatsSpawnThreads
void StatsSpawnThreads(void)
Spawns the wakeup, and the management thread used by the stats api.
Definition: counters.c:989
StatsRecord_::tm_name
const char * tm_name
Definition: output-stats.h:34
StatsSyncCounters
void StatsSyncCounters(StatsThreadContext *stats)
Definition: counters.c:476
StatsCounterGetLocalValue
int64_t StatsCounterGetLocalValue(StatsThreadContext *stats, StatsCounterId id)
Get the value of the local copy of the counter that hold this id.
Definition: counters.c:1375
TmModule_::ThreadInit
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:51
STATS_TYPE_NORMAL
@ STATS_TYPE_NORMAL
Definition: counters.c:54
JSON_STATS_THREADS
#define JSON_STATS_THREADS
Definition: output-json-stats.h:30
StatsCounterAvgId::id
uint16_t id
Definition: counters.h:35
StatsThreadContext_
Definition: counters.h:131
FatalError
#define FatalError(...)
Definition: util-debug.h:517
StatsTable_::tstats
StatsRecord * tstats
Definition: output-stats.h:41
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:34
threadvars.h
ConfUnixSocketIsEnable
int ConfUnixSocketIsEnable(void)
Definition: util-conf.c:141
SCSpinInit
#define SCSpinInit
Definition: threads-debug.h:239
StatsCounterSetI64
void StatsCounterSetI64(StatsThreadContext *stats, StatsCounterId id, int64_t x)
set, so overwrite, the value of the local counter
Definition: counters.c:202
StatsCounter_::gid
uint16_t gid
Definition: counters.h:62
SCConfGetNode
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition: conf.c:183
OutputStatsLoggersRegistered
int OutputStatsLoggersRegistered(void)
Definition: output-stats.c:177
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
head
Flow * head
Definition: flow-hash.h:1
StatsCounterAvgId
Definition: counters.h:34
SCFree
#define SCFree(p)
Definition: util-mem.h:61
StatsPrivateThreadContext_::initialized
int initialized
Definition: counters.h:128
StatsPrivateThreadContext_::size
uint32_t size
Definition: counters.h:126
StatsCounterId::id
uint16_t id
Definition: counters.h:31
StatsRegisterMaxCounter
StatsCounterMaxId StatsRegisterMaxCounter(const char *name, StatsThreadContext *stats)
Registers a counter, whose value holds the maximum of all the values assigned to it.
Definition: counters.c:1076
StatsRecord_::short_name
const char * short_name
Definition: output-stats.h:33
StatsRegisterDeriveDivCounter
StatsCounterDeriveId StatsRegisterDeriveDivCounter(const char *name, const char *dname1, const char *dname2, StatsThreadContext *stats)
Registers a counter which tracks the result of the calculating the value of counter dname1 divided by...
Definition: counters.c:1121
HashTableInit
HashTable * HashTableInit(uint32_t size, uint32_t(*Hash)(struct HashTable_ *, void *, uint16_t), char(*Compare)(void *, uint16_t, void *, uint16_t), void(*Free)(void *))
Definition: util-hash.c:34
suricata.h
StatsPublicThreadContext_::head
StatsCounter * head
Definition: counters.h:94
GetDocURL
const char * GetDocURL(void)
Definition: suricata.c:1216
StatsGlobalContext_::sts
StatsThreadStore * sts
Definition: counters.c:78
StatsGlobalContext
struct StatsGlobalContext_ StatsGlobalContext
Holds the output interface context for the counter api.
ThreadVars_::ctrl_mutex
SCCtrlMutex * ctrl_mutex
Definition: threadvars.h:127
StatsThreadStore
struct StatsThreadStore_ StatsThreadStore
per thread store of counters
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:375
StatsCounter_::did2
uint16_t did2
Definition: counters.h:67
StatsCounterDeriveId
Definition: counters.h:48
stats_decoder_events
bool stats_decoder_events
Definition: counters.c:96
TmThreadsCheckFlag
int TmThreadsCheckFlag(ThreadVars *tv, uint32_t flag)
Check if a thread flag is set.
Definition: tm-threads.c:94
StatsType
StatsType
Different kinds of qualifier that can be used to modify the behaviour of the counter to be registered...
Definition: counters.c:53
StatsPublicThreadContext_::derive_id
uint16_t derive_id
Definition: counters.h:104
StatsPublicThreadContext_::curr_id
uint16_t curr_id
Definition: counters.h:100
THV_CLOSED
#define THV_CLOSED
Definition: threadvars.h:41
StatsCounterDeriveId::id
uint16_t id
Definition: counters.h:49
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
ThreadVars_::stats
StatsThreadContext stats
Definition: threadvars.h:120
SCConfNode_
Definition: conf.h:37
StatsCounterAddI64
void StatsCounterAddI64(StatsThreadContext *stats, StatsCounterId id, int64_t x)
Adds a value of type uint64_t to the local counter.
Definition: counters.c:144
StatsThreadCleanup
void StatsThreadCleanup(StatsThreadContext *stats)
Definition: counters.c:1428
SCConfNode_::val
char * val
Definition: conf.h:39
StatsTable_::nstats
uint32_t nstats
Definition: output-stats.h:42
SCMutex
#define SCMutex
Definition: threads-debug.h:114
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
StatsPrivateThreadContext_::head
StatsLocalCounter * head
Definition: counters.h:123
OutputStatsLog
TmEcode OutputStatsLog(ThreadVars *tv, void *thread_data, StatsTable *st)
Definition: output-stats.c:77
StatsLocalCounter_::v
int64_t v
Definition: counters.h:86
StatsRegisterTests
void StatsRegisterTests(void)
Definition: counters.c:1652
StatsThreadContext_::priv
StatsPrivateThreadContext priv
Definition: counters.h:133
output.h