@ -28,6 +28,7 @@
# include "detect.h"
# include "pkt-var.h"
# include "conf.h"
# include "detect-engine.h"
# include "threads.h"
# include "threadvars.h"
@ -51,6 +52,16 @@
# ifdef HAVE_LIBJANSSON
/**
* specify which engine info will be printed in stats log .
* ALL means both last reload and ruleset stats .
*/
typedef enum OutputEngineInfo_ {
OUTPUT_ENGINE_LAST_RELOAD = 0 ,
OUTPUT_ENGINE_RULESET ,
OUTPUT_ENGINE_ALL ,
} OutputEngineInfo ;
typedef struct OutputStatsCtx_ {
LogFileCtx * file_ctx ;
uint32_t flags ; /** Store mode */
@ -61,6 +72,98 @@ typedef struct JsonStatsLogThread_ {
MemBuffer * buffer ;
} JsonStatsLogThread ;
static json_t * EngineStats2Json ( const DetectEngineCtx * de_ctx ,
const OutputEngineInfo output )
{
struct timeval last_reload ;
char timebuf [ 64 ] ;
const SigFileLoaderStat * sig_stat = NULL ;
json_t * jdata = json_object ( ) ;
if ( jdata = = NULL ) {
return NULL ;
}
if ( output = = OUTPUT_ENGINE_LAST_RELOAD | | output = = OUTPUT_ENGINE_ALL ) {
last_reload = de_ctx - > last_reload ;
CreateIsoTimeString ( & last_reload , timebuf , sizeof ( timebuf ) ) ;
json_object_set_new ( jdata , " last_reload " , json_string ( timebuf ) ) ;
}
sig_stat = & de_ctx - > sig_stat ;
if ( ( output = = OUTPUT_ENGINE_RULESET | | output = = OUTPUT_ENGINE_ALL ) & &
sig_stat ! = NULL )
{
json_object_set_new ( jdata , " rules_loaded " ,
json_integer ( sig_stat - > good_sigs_total ) ) ;
json_object_set_new ( jdata , " rules_failed " ,
json_integer ( sig_stat - > bad_sigs_total ) ) ;
}
return jdata ;
}
static TmEcode OutputEngineStats2Json ( json_t * * jdata , const OutputEngineInfo output )
{
DetectEngineCtx * de_ctx = DetectEngineGetCurrent ( ) ;
if ( de_ctx = = NULL ) {
goto err1 ;
}
/* Since we need to deference de_ctx pointer, we don't want to lost it. */
DetectEngineCtx * list = de_ctx ;
json_t * js_tenant_list = json_array ( ) ;
json_t * js_tenant = NULL ;
if ( js_tenant_list = = NULL ) {
goto err2 ;
}
while ( list ) {
js_tenant = json_object ( ) ;
if ( js_tenant = = NULL ) {
goto err3 ;
}
json_object_set_new ( js_tenant , " id " , json_integer ( list - > tenant_id ) ) ;
json_t * js_stats = EngineStats2Json ( list , output ) ;
if ( js_stats = = NULL ) {
goto err4 ;
}
json_object_update ( js_tenant , js_stats ) ;
json_array_append_new ( js_tenant_list , js_tenant ) ;
json_decref ( js_stats ) ;
list = list - > next ;
}
DetectEngineDeReference ( & de_ctx ) ;
* jdata = js_tenant_list ;
return TM_ECODE_OK ;
err4 :
json_object_clear ( js_tenant ) ;
json_decref ( js_tenant ) ;
err3 :
json_object_clear ( js_tenant_list ) ;
json_decref ( js_tenant_list ) ;
err2 :
DetectEngineDeReference ( & de_ctx ) ;
err1 :
json_object_set_new ( * jdata , " message " , json_string ( " Unable to get info " ) ) ;
return TM_ECODE_FAILED ;
}
TmEcode OutputEngineStatsReloadTime ( json_t * * jdata ) {
return OutputEngineStats2Json ( jdata , OUTPUT_ENGINE_LAST_RELOAD ) ;
}
TmEcode OutputEngineStatsRuleset ( json_t * * jdata ) {
return OutputEngineStats2Json ( jdata , OUTPUT_ENGINE_RULESET ) ;
}
static json_t * OutputStats2Json ( json_t * js , const char * key )
{
void * iter ;
@ -83,6 +186,15 @@ static json_t *OutputStats2Json(json_t *js, const char *key)
json_t * value = json_object_iter_value ( iter ) ;
if ( value = = NULL ) {
value = json_object ( ) ;
if ( ! strncmp ( s , " detect " , 6 ) ) {
json_t * js_engine = NULL ;
TmEcode ret = OutputEngineStats2Json ( & js_engine , OUTPUT_ENGINE_ALL ) ;
if ( ret = = TM_ECODE_OK & & js_engine ) {
json_object_set_new ( value , " engines " , js_engine ) ;
}
}
json_object_set_new ( js , s , value ) ;
}
if ( s2 ! = NULL ) {