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