diff options
Diffstat (limited to '')
-rw-r--r-- | logsmanagement/rrd_api/rrd_api.h | 312 | ||||
-rw-r--r-- | logsmanagement/rrd_api/rrd_api_docker_ev.c | 137 | ||||
-rw-r--r-- | logsmanagement/rrd_api/rrd_api_docker_ev.h | 39 | ||||
-rw-r--r-- | logsmanagement/rrd_api/rrd_api_generic.c | 28 | ||||
-rw-r--r-- | logsmanagement/rrd_api/rrd_api_generic.h | 34 | ||||
-rw-r--r-- | logsmanagement/rrd_api/rrd_api_kernel.c | 168 | ||||
-rw-r--r-- | logsmanagement/rrd_api/rrd_api_kernel.h | 46 | ||||
-rw-r--r-- | logsmanagement/rrd_api/rrd_api_mqtt.c | 79 | ||||
-rw-r--r-- | logsmanagement/rrd_api/rrd_api_mqtt.h | 37 | ||||
-rw-r--r-- | logsmanagement/rrd_api/rrd_api_stats.c | 298 | ||||
-rw-r--r-- | logsmanagement/rrd_api/rrd_api_stats.h | 19 | ||||
-rw-r--r-- | logsmanagement/rrd_api/rrd_api_systemd.c | 206 | ||||
-rw-r--r-- | logsmanagement/rrd_api/rrd_api_systemd.h | 45 | ||||
-rw-r--r-- | logsmanagement/rrd_api/rrd_api_web_log.c | 716 | ||||
-rw-r--r-- | logsmanagement/rrd_api/rrd_api_web_log.h | 88 |
15 files changed, 2252 insertions, 0 deletions
diff --git a/logsmanagement/rrd_api/rrd_api.h b/logsmanagement/rrd_api/rrd_api.h new file mode 100644 index 00000000..eecaec99 --- /dev/null +++ b/logsmanagement/rrd_api/rrd_api.h @@ -0,0 +1,312 @@ +/** @file rrd_api.h + */ + +#ifndef RRD_API_H_ +#define RRD_API_H_ + +#include "daemon/common.h" +#include "../circular_buffer.h" +#include "../helper.h" + +struct Chart_meta; +struct Chart_str { + const char *type; + const char *id; + const char *title; + const char *units; + const char *family; + const char *context; + const char *chart_type; + long priority; + int update_every; +}; + +#include "rrd_api_generic.h" +#include "rrd_api_web_log.h" +#include "rrd_api_kernel.h" +#include "rrd_api_systemd.h" +#include "rrd_api_docker_ev.h" +#include "rrd_api_mqtt.h" + +#define CHART_TITLE_TOTAL_COLLECTED_LOGS "Total collected log records" +#define CHART_TITLE_RATE_COLLECTED_LOGS "Rate of collected log records" +#define NETDATA_CHART_PRIO_LOGS_INCR 100 /**< PRIO increment step from one log source to another **/ + +typedef struct Chart_data_cus { + char *id; + + struct chart_data_cus_dim { + char *name; + collected_number val; + unsigned long long *p_counter; + } *dims; + + int dims_size; + + struct Chart_data_cus *next; + +} Chart_data_cus_t ; + +struct Chart_meta { + enum log_src_type_t type; + long base_prio; + + union { + chart_data_generic_t *chart_data_generic; + chart_data_web_log_t *chart_data_web_log; + chart_data_kernel_t *chart_data_kernel; + chart_data_systemd_t *chart_data_systemd; + chart_data_docker_ev_t *chart_data_docker_ev; + chart_data_mqtt_t *chart_data_mqtt; + }; + + Chart_data_cus_t *chart_data_cus_arr; + + void (*init)(struct File_info *p_file_info); + void (*update)(struct File_info *p_file_info); + +}; + +static inline struct Chart_str lgs_mng_create_chart(const char *type, + const char *id, + const char *title, + const char *units, + const char *family, + const char *context, + const char *chart_type, + long priority, + int update_every){ + + struct Chart_str cs = { + .type = type, + .id = id, + .title = title, + .units = units, + .family = family ? family : "", + .context = context ? context : "", + .chart_type = chart_type ? chart_type : "", + .priority = priority, + .update_every = update_every + }; + + printf("CHART '%s.%s' '' '%s' '%s' '%s' '%s' '%s' %ld %d '' '" LOGS_MANAGEMENT_PLUGIN_STR "' ''\n", + cs.type, + cs.id, + cs.title, + cs.units, + cs.family, + cs.context, + cs.chart_type, + cs.priority, + cs.update_every + ); + + return cs; +} + +static inline void lgs_mng_add_dim( const char *id, + const char *algorithm, + collected_number multiplier, + collected_number divisor){ + + printf("DIMENSION '%s' '' '%s' %lld %lld\n", id, algorithm, multiplier, divisor); +} + +static inline void lgs_mng_add_dim_post_init( struct Chart_str *cs, + const char *dim_id, + const char *algorithm, + collected_number multiplier, + collected_number divisor){ + + printf("CHART '%s.%s' '' '%s' '%s' '%s' '%s' '%s' %ld %d '' '" LOGS_MANAGEMENT_PLUGIN_STR "' ''\n", + cs->type, + cs->id, + cs->title, + cs->units, + cs->family, + cs->context, + cs->chart_type, + cs->priority, + cs->update_every + ); + lgs_mng_add_dim(dim_id, algorithm, multiplier, divisor); +} + +static inline void lgs_mng_update_chart_begin(const char *type, const char *id){ + + printf("BEGIN '%s.%s'\n", type, id); +} + +static inline void lgs_mng_update_chart_set(const char *id, collected_number val){ + printf("SET '%s' = %lld\n", id, val); +} + +static inline void lgs_mng_update_chart_end(time_t sec){ + printf("END %" PRId64 " 0 1\n", sec); +} + +#define lgs_mng_do_num_of_logs_charts_init(p_file_info, chart_prio){ \ + \ + /* Number of collected logs total - initialise */ \ + if(p_file_info->parser_config->chart_config & CHART_COLLECTED_LOGS_TOTAL){ \ + lgs_mng_create_chart( \ + (char *) p_file_info->chartname /* type */ \ + , "collected_logs_total" /* id */ \ + , CHART_TITLE_TOTAL_COLLECTED_LOGS /* title */ \ + , "log records" /* units */ \ + , "collected_logs" /* family */ \ + , NULL /* context */ \ + , RRDSET_TYPE_AREA_NAME /* chart_type */ \ + , ++chart_prio /* priority */ \ + , p_file_info->update_every /* update_every */ \ + ); \ + lgs_mng_add_dim("total records", RRD_ALGORITHM_ABSOLUTE_NAME, 1, 1); \ + } \ + \ + /* Number of collected logs rate - initialise */ \ + if(p_file_info->parser_config->chart_config & CHART_COLLECTED_LOGS_RATE){ \ + lgs_mng_create_chart( \ + (char *) p_file_info->chartname /* type */ \ + , "collected_logs_rate" /* id */ \ + , CHART_TITLE_RATE_COLLECTED_LOGS /* title */ \ + , "log records" /* units */ \ + , "collected_logs" /* family */ \ + , NULL /* context */ \ + , RRDSET_TYPE_LINE_NAME /* chart_type */ \ + , ++chart_prio /* priority */ \ + , p_file_info->update_every /* update_every */ \ + ); \ + lgs_mng_add_dim("records", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); \ + } \ + \ +} \ + +#define lgs_mng_do_num_of_logs_charts_update(p_file_info, lag_in_sec, chart_data){ \ + \ + /* Number of collected logs total - update previous values */ \ + if(p_file_info->parser_config->chart_config & CHART_COLLECTED_LOGS_TOTAL){ \ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; \ + sec < p_file_info->parser_metrics->last_update; \ + sec++){ \ + lgs_mng_update_chart_begin(p_file_info->chartname, "collected_logs_total"); \ + lgs_mng_update_chart_set("total records", chart_data->num_lines); \ + lgs_mng_update_chart_end(sec); \ + } \ + } \ + \ + /* Number of collected logs rate - update previous values */ \ + if(p_file_info->parser_config->chart_config & CHART_COLLECTED_LOGS_RATE){ \ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; \ + sec < p_file_info->parser_metrics->last_update; \ + sec++){ \ + lgs_mng_update_chart_begin(p_file_info->chartname, "collected_logs_rate"); \ + lgs_mng_update_chart_set("records", chart_data->num_lines); \ + lgs_mng_update_chart_end(sec); \ + } \ + } \ + \ + chart_data->num_lines = p_file_info->parser_metrics->num_lines; \ + \ + /* Number of collected logs total - update */ \ + if(p_file_info->parser_config->chart_config & CHART_COLLECTED_LOGS_TOTAL){ \ + lgs_mng_update_chart_begin( (char *) p_file_info->chartname, "collected_logs_total"); \ + lgs_mng_update_chart_set("total records", chart_data->num_lines); \ + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); \ + } \ + \ + /* Number of collected logs rate - update */ \ + if(p_file_info->parser_config->chart_config & CHART_COLLECTED_LOGS_RATE){ \ + lgs_mng_update_chart_begin( (char *) p_file_info->chartname, "collected_logs_rate"); \ + lgs_mng_update_chart_set("records", chart_data->num_lines); \ + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); \ + } \ +} + +#define lgs_mng_do_custom_charts_init(p_file_info) { \ + \ + for(int cus_off = 0; p_file_info->parser_cus_config[cus_off]; cus_off++){ \ + \ + Chart_data_cus_t *cus; \ + Chart_data_cus_t **p_cus = &p_file_info->chart_meta->chart_data_cus_arr; \ + \ + for(cus = p_file_info->chart_meta->chart_data_cus_arr; \ + cus; \ + cus = cus->next){ \ + \ + if(!strcmp(cus->id, p_file_info->parser_cus_config[cus_off]->chartname)) \ + break; \ + \ + p_cus = &(cus->next); \ + } \ + \ + if(!cus){ \ + cus = callocz(1, sizeof(Chart_data_cus_t)); \ + *p_cus = cus; \ + \ + cus->id = p_file_info->parser_cus_config[cus_off]->chartname; \ + \ + lgs_mng_create_chart( \ + (char *) p_file_info->chartname /* type */ \ + , cus->id /* id */ \ + , cus->id /* title */ \ + , "matches" /* units */ \ + , "custom_charts" /* family */ \ + , NULL /* context */ \ + , RRDSET_TYPE_AREA_NAME /* chart_type */ \ + , p_file_info->chart_meta->base_prio + 1000 + cus_off /* priority */ \ + , p_file_info->update_every /* update_every */ \ + ); \ + } \ + \ + cus->dims = reallocz(cus->dims, ++cus->dims_size * sizeof(struct chart_data_cus_dim)); \ + cus->dims[cus->dims_size - 1].name = \ + p_file_info->parser_cus_config[cus_off]->regex_name; \ + cus->dims[cus->dims_size - 1].val = 0; \ + cus->dims[cus->dims_size - 1].p_counter = \ + &p_file_info->parser_metrics->parser_cus[cus_off]->count; \ + \ + lgs_mng_add_dim(cus->dims[cus->dims_size - 1].name, \ + RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); \ + \ + } \ +} + +#define lgs_mng_do_custom_charts_update(p_file_info, lag_in_sec) { \ + \ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; \ + sec < p_file_info->parser_metrics->last_update; \ + sec++){ \ + \ + for(Chart_data_cus_t *cus = p_file_info->chart_meta->chart_data_cus_arr; \ + cus; \ + cus = cus->next){ \ + \ + lgs_mng_update_chart_begin(p_file_info->chartname, cus->id); \ + \ + for(int d_idx = 0; d_idx < cus->dims_size; d_idx++) \ + lgs_mng_update_chart_set(cus->dims[d_idx].name, cus->dims[d_idx].val); \ + \ + lgs_mng_update_chart_end(sec); \ + } \ + \ + } \ + \ + for(Chart_data_cus_t *cus = p_file_info->chart_meta->chart_data_cus_arr; \ + cus; \ + cus = cus->next){ \ + \ + lgs_mng_update_chart_begin(p_file_info->chartname, cus->id); \ + \ + for(int d_idx = 0; d_idx < cus->dims_size; d_idx++){ \ + \ + cus->dims[d_idx].val += *(cus->dims[d_idx].p_counter); \ + *(cus->dims[d_idx].p_counter) = 0; \ + \ + lgs_mng_update_chart_set(cus->dims[d_idx].name, cus->dims[d_idx].val); \ + } \ + \ + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); \ + } \ +} + +#endif // RRD_API_H_ diff --git a/logsmanagement/rrd_api/rrd_api_docker_ev.c b/logsmanagement/rrd_api/rrd_api_docker_ev.c new file mode 100644 index 00000000..743d256a --- /dev/null +++ b/logsmanagement/rrd_api/rrd_api_docker_ev.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rrd_api_docker_ev.h" + +void docker_ev_chart_init(struct File_info *p_file_info){ + p_file_info->chart_meta->chart_data_docker_ev = callocz(1, sizeof (struct Chart_data_docker_ev)); + p_file_info->chart_meta->chart_data_docker_ev->last_update = now_realtime_sec(); // initial value shouldn't be 0 + long chart_prio = p_file_info->chart_meta->base_prio; + + lgs_mng_do_num_of_logs_charts_init(p_file_info, chart_prio); + + /* Docker events type - initialise */ + if(p_file_info->parser_config->chart_config & CHART_DOCKER_EV_TYPE){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "events_type" // id + , "Events type" // title + , "events types" // units + , "event_type" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + for(int idx = 0; idx < NUM_OF_DOCKER_EV_TYPES; idx++) + lgs_mng_add_dim(docker_ev_type_string[idx], RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + + /* Docker events actions - initialise */ + if(p_file_info->parser_config->chart_config & CHART_DOCKER_EV_ACTION){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "events_action" // id + , "Events action" // title + , "events actions" // units + , "event_action" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + for(int ev_off = 0; ev_off < NUM_OF_DOCKER_EV_TYPES; ev_off++){ + int act_off = -1; + while(docker_ev_action_string[ev_off][++act_off] != NULL){ + + char dim[50]; + snprintfz(dim, 50, "%s %s", + docker_ev_type_string[ev_off], + docker_ev_action_string[ev_off][act_off]); + + lgs_mng_add_dim(dim, RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + } + } + + lgs_mng_do_custom_charts_init(p_file_info); +} + +void docker_ev_chart_update(struct File_info *p_file_info){ + chart_data_docker_ev_t *chart_data = p_file_info->chart_meta->chart_data_docker_ev; + + if(chart_data->last_update != p_file_info->parser_metrics->last_update){ + + time_t lag_in_sec = p_file_info->parser_metrics->last_update - chart_data->last_update - 1; + + lgs_mng_do_num_of_logs_charts_update(p_file_info, lag_in_sec, chart_data); + + /* Docker events type - update */ + if(p_file_info->parser_config->chart_config & CHART_DOCKER_EV_TYPE){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "events_type"); + for(int idx = 0; idx < NUM_OF_DOCKER_EV_TYPES; idx++) + lgs_mng_update_chart_set(docker_ev_type_string[idx], chart_data->num_dock_ev_type[idx]); + lgs_mng_update_chart_end(sec); + } + + lgs_mng_update_chart_begin(p_file_info->chartname, "events_type"); + for(int idx = 0; idx < NUM_OF_DOCKER_EV_TYPES; idx++){ + chart_data->num_dock_ev_type[idx] = p_file_info->parser_metrics->docker_ev->ev_type[idx]; + lgs_mng_update_chart_set(docker_ev_type_string[idx], chart_data->num_dock_ev_type[idx]); + } + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* Docker events action - update */ + if(p_file_info->parser_config->chart_config & CHART_DOCKER_EV_ACTION){ + char dim[50]; + + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "events_action"); + for(int ev_off = 0; ev_off < NUM_OF_DOCKER_EV_TYPES; ev_off++){ + int act_off = -1; + while(docker_ev_action_string[ev_off][++act_off] != NULL){ + if(chart_data->num_dock_ev_action[ev_off][act_off]){ + snprintfz(dim, 50, "%s %s", + docker_ev_type_string[ev_off], + docker_ev_action_string[ev_off][act_off]); + lgs_mng_update_chart_set(dim, chart_data->num_dock_ev_action[ev_off][act_off]); + } + } + } + lgs_mng_update_chart_end(sec); + } + + lgs_mng_update_chart_begin(p_file_info->chartname, "events_action"); + for(int ev_off = 0; ev_off < NUM_OF_DOCKER_EV_TYPES; ev_off++){ + int act_off = -1; + while(docker_ev_action_string[ev_off][++act_off] != NULL){ + chart_data->num_dock_ev_action[ev_off][act_off] = + p_file_info->parser_metrics->docker_ev->ev_action[ev_off][act_off]; + + if(chart_data->num_dock_ev_action[ev_off][act_off]){ + snprintfz(dim, 50, "%s %s", + docker_ev_type_string[ev_off], + docker_ev_action_string[ev_off][act_off]); + lgs_mng_update_chart_set(dim, chart_data->num_dock_ev_action[ev_off][act_off]); + } + } + } + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + + } + + lgs_mng_do_custom_charts_update(p_file_info, lag_in_sec); + + chart_data->last_update = p_file_info->parser_metrics->last_update; + } + +} diff --git a/logsmanagement/rrd_api/rrd_api_docker_ev.h b/logsmanagement/rrd_api/rrd_api_docker_ev.h new file mode 100644 index 00000000..69341326 --- /dev/null +++ b/logsmanagement/rrd_api/rrd_api_docker_ev.h @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +/** @file plugins_logsmanagement_docker_ev.h + * @brief Incudes the structure and function definitions + * for the docker event log charts. + */ + +#ifndef RRD_API_DOCKER_EV_H_ +#define RRD_API_DOCKER_EV_H_ + +#include "daemon/common.h" + +struct File_info; + +typedef struct Chart_data_docker_ev chart_data_docker_ev_t; + +#include "../file_info.h" +#include "../circular_buffer.h" + +#include "rrd_api.h" + +struct Chart_data_docker_ev { + + time_t last_update; + + /* Number of collected log records */ + collected_number num_lines; + + /* Docker events metrics - event type */ + collected_number num_dock_ev_type[NUM_OF_DOCKER_EV_TYPES]; + + /* Docker events metrics - action type */ + collected_number num_dock_ev_action[NUM_OF_DOCKER_EV_TYPES][NUM_OF_CONTAINER_ACTIONS]; +}; + +void docker_ev_chart_init(struct File_info *p_file_info); +void docker_ev_chart_update(struct File_info *p_file_info); + +#endif // RRD_API_DOCKER_EV_H_ diff --git a/logsmanagement/rrd_api/rrd_api_generic.c b/logsmanagement/rrd_api/rrd_api_generic.c new file mode 100644 index 00000000..752f5af7 --- /dev/null +++ b/logsmanagement/rrd_api/rrd_api_generic.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rrd_api_generic.h" + +void generic_chart_init(struct File_info *p_file_info){ + p_file_info->chart_meta->chart_data_generic = callocz(1, sizeof (struct Chart_data_generic)); + p_file_info->chart_meta->chart_data_generic->last_update = now_realtime_sec(); // initial value shouldn't be 0 + long chart_prio = p_file_info->chart_meta->base_prio; + + lgs_mng_do_num_of_logs_charts_init(p_file_info, chart_prio); + + lgs_mng_do_custom_charts_init(p_file_info); +} + +void generic_chart_update(struct File_info *p_file_info){ + chart_data_generic_t *chart_data = p_file_info->chart_meta->chart_data_generic; + + if(chart_data->last_update != p_file_info->parser_metrics->last_update){ + + time_t lag_in_sec = p_file_info->parser_metrics->last_update - chart_data->last_update - 1; + + lgs_mng_do_num_of_logs_charts_update(p_file_info, lag_in_sec, chart_data); + + lgs_mng_do_custom_charts_update(p_file_info, lag_in_sec); + + chart_data->last_update = p_file_info->parser_metrics->last_update; + } +} diff --git a/logsmanagement/rrd_api/rrd_api_generic.h b/logsmanagement/rrd_api/rrd_api_generic.h new file mode 100644 index 00000000..25b801a0 --- /dev/null +++ b/logsmanagement/rrd_api/rrd_api_generic.h @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +/** @file rrd_api_generic.h + * @brief Incudes the structure and function definitions for + * generic log charts. + */ + +#ifndef RRD_API_GENERIC_H_ +#define RRD_API_GENERIC_H_ + +#include "daemon/common.h" + +struct File_info; + +typedef struct Chart_data_generic chart_data_generic_t; + +#include "../file_info.h" +#include "../circular_buffer.h" + +#include "rrd_api.h" + +struct Chart_data_generic { + + time_t last_update; + + /* Number of collected log records */ + collected_number num_lines; + +}; + +void generic_chart_init(struct File_info *p_file_info); +void generic_chart_update(struct File_info *p_file_info); + +#endif // RRD_API_GENERIC_H_ diff --git a/logsmanagement/rrd_api/rrd_api_kernel.c b/logsmanagement/rrd_api/rrd_api_kernel.c new file mode 100644 index 00000000..9372f773 --- /dev/null +++ b/logsmanagement/rrd_api/rrd_api_kernel.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rrd_api_kernel.h" + +void kernel_chart_init(struct File_info *p_file_info){ + p_file_info->chart_meta->chart_data_kernel = callocz(1, sizeof (struct Chart_data_kernel)); + chart_data_kernel_t *chart_data = p_file_info->chart_meta->chart_data_kernel; + chart_data->last_update = now_realtime_sec(); // initial value shouldn't be 0 + long chart_prio = p_file_info->chart_meta->base_prio; + + lgs_mng_do_num_of_logs_charts_init(p_file_info, chart_prio); + + /* Syslog severity level (== Systemd priority) - initialise */ + if(p_file_info->parser_config->chart_config & CHART_SYSLOG_SEVER){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "severity_levels" // id + , "Severity Levels" // title + , "severity levels" // units + , "severity" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + for(int i = 0; i < SYSLOG_SEVER_ARR_SIZE; i++) + lgs_mng_add_dim(dim_sever_str[i], RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + + } + + /* Subsystem - initialise */ + if(p_file_info->parser_config->chart_config & CHART_KMSG_SUBSYSTEM){ + chart_data->cs_subsys = lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "subsystems" // id + , "Subsystems" // title + , "subsystems" // units + , "subsystem" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + } + + /* Device - initialise */ + if(p_file_info->parser_config->chart_config & CHART_KMSG_DEVICE){ + chart_data->cs_device = lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "devices" // id + , "Devices" // title + , "devices" // units + , "device" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + } + + lgs_mng_do_custom_charts_init(p_file_info); +} + +void kernel_chart_update(struct File_info *p_file_info){ + chart_data_kernel_t *chart_data = p_file_info->chart_meta->chart_data_kernel; + + if(chart_data->last_update != p_file_info->parser_metrics->last_update){ + + time_t lag_in_sec = p_file_info->parser_metrics->last_update - chart_data->last_update - 1; + + lgs_mng_do_num_of_logs_charts_update(p_file_info, lag_in_sec, chart_data); + + /* Syslog severity level (== Systemd priority) - update */ + if(p_file_info->parser_config->chart_config & CHART_SYSLOG_SEVER){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "severity_levels"); + for(int idx = 0; idx < SYSLOG_SEVER_ARR_SIZE; idx++) + lgs_mng_update_chart_set(dim_sever_str[idx], chart_data->num_sever[idx]); + lgs_mng_update_chart_end(sec); + } + + lgs_mng_update_chart_begin(p_file_info->chartname, "severity_levels"); + for(int idx = 0; idx < SYSLOG_SEVER_ARR_SIZE; idx++){ + chart_data->num_sever[idx] = p_file_info->parser_metrics->kernel->sever[idx]; + lgs_mng_update_chart_set(dim_sever_str[idx], chart_data->num_sever[idx]); + } + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* Subsystem - update */ + if(p_file_info->parser_config->chart_config & CHART_KMSG_SUBSYSTEM){ + metrics_dict_item_t *it; + + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "subsystems"); + dfe_start_read(p_file_info->parser_metrics->kernel->subsystem, it){ + if(it->dim_initialized) + lgs_mng_update_chart_set(it_dfe.name, (collected_number) it->num); + } + dfe_done(it); + lgs_mng_update_chart_end(sec); + } + + dfe_start_write(p_file_info->parser_metrics->kernel->subsystem, it){ + if(!it->dim_initialized){ + it->dim_initialized = true; + lgs_mng_add_dim_post_init( &chart_data->cs_subsys, it_dfe.name, + RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + } + dfe_done(it); + + lgs_mng_update_chart_begin(p_file_info->chartname, "subsystems"); + dfe_start_write(p_file_info->parser_metrics->kernel->subsystem, it){ + it->num = it->num_new; + lgs_mng_update_chart_set(it_dfe.name, (collected_number) it->num); + } + dfe_done(it); + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* Device - update */ + if(p_file_info->parser_config->chart_config & CHART_KMSG_DEVICE){ + metrics_dict_item_t *it; + + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "devices"); + dfe_start_read(p_file_info->parser_metrics->kernel->device, it){ + if(it->dim_initialized) + lgs_mng_update_chart_set(it_dfe.name, (collected_number) it->num); + } + dfe_done(it); + lgs_mng_update_chart_end(sec); + } + + dfe_start_write(p_file_info->parser_metrics->kernel->device, it){ + if(!it->dim_initialized){ + it->dim_initialized = true; + lgs_mng_add_dim_post_init( &chart_data->cs_device, it_dfe.name, + RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + } + dfe_done(it); + + lgs_mng_update_chart_begin(p_file_info->chartname, "devices"); + dfe_start_write(p_file_info->parser_metrics->kernel->device, it){ + it->num = it->num_new; + lgs_mng_update_chart_set(it_dfe.name, (collected_number) it->num); + } + dfe_done(it); + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + lgs_mng_do_custom_charts_update(p_file_info, lag_in_sec); + + chart_data->last_update = p_file_info->parser_metrics->last_update; + } +} diff --git a/logsmanagement/rrd_api/rrd_api_kernel.h b/logsmanagement/rrd_api/rrd_api_kernel.h new file mode 100644 index 00000000..ccb4a752 --- /dev/null +++ b/logsmanagement/rrd_api/rrd_api_kernel.h @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +/** @file rrd_api_kernel.h + * @brief Incudes the structure and function definitions + * for the kernel log charts. + */ + +#ifndef RRD_API_KERNEL_H_ +#define RRD_API_KERNEL_H_ + +#include "daemon/common.h" + +struct File_info; + +typedef struct Chart_data_kernel chart_data_kernel_t; + +#include "../file_info.h" +#include "../circular_buffer.h" + +#include "rrd_api.h" + +#include "rrd_api_systemd.h" // required for dim_sever_str[] + +struct Chart_data_kernel { + + time_t last_update; + + /* Number of collected log records */ + collected_number num_lines; + + /* Kernel metrics - Syslog Severity value */ + collected_number num_sever[SYSLOG_SEVER_ARR_SIZE]; + + /* Kernel metrics - Subsystem */ + struct Chart_str cs_subsys; + // Special case: Subsystem dimension and number are part of Kernel_metrics_t + + /* Kernel metrics - Device */ + struct Chart_str cs_device; + // Special case: Device dimension and number are part of Kernel_metrics_t +}; + +void kernel_chart_init(struct File_info *p_file_info); +void kernel_chart_update(struct File_info *p_file_info); + +#endif // RRD_API_KERNEL_H_ diff --git a/logsmanagement/rrd_api/rrd_api_mqtt.c b/logsmanagement/rrd_api/rrd_api_mqtt.c new file mode 100644 index 00000000..eb90b2ab --- /dev/null +++ b/logsmanagement/rrd_api/rrd_api_mqtt.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rrd_api_mqtt.h" + +void mqtt_chart_init(struct File_info *p_file_info){ + p_file_info->chart_meta->chart_data_mqtt = callocz(1, sizeof (struct Chart_data_mqtt)); + chart_data_mqtt_t *chart_data = p_file_info->chart_meta->chart_data_mqtt; + chart_data->last_update = now_realtime_sec(); // initial value shouldn't be 0 + long chart_prio = p_file_info->chart_meta->base_prio; + + lgs_mng_do_num_of_logs_charts_init(p_file_info, chart_prio); + + /* Topic - initialise */ + if(p_file_info->parser_config->chart_config & CHART_MQTT_TOPIC){ + chart_data->cs_topic = lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "topics" // id + , "Topics" // title + , "topics" // units + , "topic" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + } + + lgs_mng_do_custom_charts_init(p_file_info); +} + +void mqtt_chart_update(struct File_info *p_file_info){ + chart_data_mqtt_t *chart_data = p_file_info->chart_meta->chart_data_mqtt; + + if(chart_data->last_update != p_file_info->parser_metrics->last_update){ + + time_t lag_in_sec = p_file_info->parser_metrics->last_update - chart_data->last_update - 1; + + lgs_mng_do_num_of_logs_charts_update(p_file_info, lag_in_sec, chart_data); + + /* Topic - update */ + if(p_file_info->parser_config->chart_config & CHART_MQTT_TOPIC){ + metrics_dict_item_t *it; + + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "topics"); + dfe_start_read(p_file_info->parser_metrics->mqtt->topic, it){ + if(it->dim_initialized) + lgs_mng_update_chart_set(it_dfe.name, (collected_number) it->num); + } + dfe_done(it); + lgs_mng_update_chart_end(sec); + } + + dfe_start_write(p_file_info->parser_metrics->mqtt->topic, it){ + if(!it->dim_initialized){ + it->dim_initialized = true; + lgs_mng_add_dim_post_init( &chart_data->cs_topic, it_dfe.name, + RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + } + dfe_done(it); + + lgs_mng_update_chart_begin(p_file_info->chartname, "topics"); + dfe_start_write(p_file_info->parser_metrics->mqtt->topic, it){ + it->num = it->num_new; + lgs_mng_update_chart_set(it_dfe.name, (collected_number) it->num); + } + dfe_done(it); + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + lgs_mng_do_custom_charts_update(p_file_info, lag_in_sec); + + chart_data->last_update = p_file_info->parser_metrics->last_update; + } +} diff --git a/logsmanagement/rrd_api/rrd_api_mqtt.h b/logsmanagement/rrd_api/rrd_api_mqtt.h new file mode 100644 index 00000000..13c5cff3 --- /dev/null +++ b/logsmanagement/rrd_api/rrd_api_mqtt.h @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +/** @file rrd_api_mqtt.h + * @brief Incudes the structure and function definitions + * for the mqtt log charts. + */ + +#ifndef RRD_API_MQTT_H_ +#define RRD_API_MQTT_H_ + +#include "daemon/common.h" + +struct File_info; + +typedef struct Chart_data_mqtt chart_data_mqtt_t; + +#include "../file_info.h" +#include "../circular_buffer.h" + +#include "rrd_api.h" + +struct Chart_data_mqtt { + + time_t last_update; + + /* Number of collected log records */ + collected_number num_lines; + + /* MQTT metrics - Topic */ + struct Chart_str cs_topic; + // Special case: Topic dimension and number are part of Mqtt_metrics_t +}; + +void mqtt_chart_init(struct File_info *p_file_info); +void mqtt_chart_update(struct File_info *p_file_info); + +#endif // RRD_API_MQTT_H_ diff --git a/logsmanagement/rrd_api/rrd_api_stats.c b/logsmanagement/rrd_api/rrd_api_stats.c new file mode 100644 index 00000000..e845d041 --- /dev/null +++ b/logsmanagement/rrd_api/rrd_api_stats.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rrd_api_stats.h" + +static const char *const rrd_type = "netdata"; + +static char **dim_db_timings_write, **dim_db_timings_rotate; + +extern bool logsmanagement_should_exit; + +static void stats_charts_update(void){ + + /* Circular buffer total memory stats - update */ + lgs_mng_update_chart_begin(rrd_type, "circular_buffers_mem_total_cached"); + for(int i = 0; i < p_file_infos_arr->count; i++){ + struct File_info *p_file_info = p_file_infos_arr->data[i]; + if(!p_file_info->parser_config) + continue; + + lgs_mng_update_chart_set(p_file_info->chartname, + __atomic_load_n(&p_file_info->circ_buff->total_cached_mem, __ATOMIC_RELAXED)); + } + lgs_mng_update_chart_end(0); + + /* Circular buffer number of items - update */ + lgs_mng_update_chart_begin(rrd_type, "circular_buffers_num_of_items"); + for(int i = 0; i < p_file_infos_arr->count; i++){ + struct File_info *p_file_info = p_file_infos_arr->data[i]; + if(!p_file_info->parser_config) + continue; + + lgs_mng_update_chart_set(p_file_info->chartname, p_file_info->circ_buff->num_of_items); + } + lgs_mng_update_chart_end(0); + + /* Circular buffer uncompressed buffered items memory stats - update */ + lgs_mng_update_chart_begin(rrd_type, "circular_buffers_mem_uncompressed_used"); + for(int i = 0; i < p_file_infos_arr->count; i++){ + struct File_info *p_file_info = p_file_infos_arr->data[i]; + if(!p_file_info->parser_config) + continue; + + lgs_mng_update_chart_set(p_file_info->chartname, + __atomic_load_n(&p_file_info->circ_buff->text_size_total, __ATOMIC_RELAXED)); + } + lgs_mng_update_chart_end(0); + + /* Circular buffer compressed buffered items memory stats - update */ + lgs_mng_update_chart_begin(rrd_type, "circular_buffers_mem_compressed_used"); + for(int i = 0; i < p_file_infos_arr->count; i++){ + struct File_info *p_file_info = p_file_infos_arr->data[i]; + if(!p_file_info->parser_config) + continue; + + lgs_mng_update_chart_set(p_file_info->chartname, + __atomic_load_n(&p_file_info->circ_buff->text_compressed_size_total, __ATOMIC_RELAXED)); + } + lgs_mng_update_chart_end(0); + + /* Compression stats - update */ + lgs_mng_update_chart_begin(rrd_type, "average_compression_ratio"); + for(int i = 0; i < p_file_infos_arr->count; i++){ + struct File_info *p_file_info = p_file_infos_arr->data[i]; + if(!p_file_info->parser_config) + continue; + + lgs_mng_update_chart_set(p_file_info->chartname, + __atomic_load_n(&p_file_info->circ_buff->compression_ratio, __ATOMIC_RELAXED)); + } + lgs_mng_update_chart_end(0); + + /* DB disk usage stats - update */ + lgs_mng_update_chart_begin(rrd_type, "database_disk_usage"); + for(int i = 0; i < p_file_infos_arr->count; i++){ + struct File_info *p_file_info = p_file_infos_arr->data[i]; + if(!p_file_info->parser_config) + continue; + + lgs_mng_update_chart_set(p_file_info->chartname, + __atomic_load_n(&p_file_info->blob_total_size, __ATOMIC_RELAXED)); + } + lgs_mng_update_chart_end(0); + + /* DB timings - update */ + lgs_mng_update_chart_begin(rrd_type, "database_timings"); + for(int i = 0; i < p_file_infos_arr->count; i++){ + struct File_info *p_file_info = p_file_infos_arr->data[i]; + if(!p_file_info->parser_config) + continue; + + lgs_mng_update_chart_set(dim_db_timings_write[i], + __atomic_exchange_n(&p_file_info->db_write_duration, 0, __ATOMIC_RELAXED)); + + lgs_mng_update_chart_set(dim_db_timings_rotate[i], + __atomic_exchange_n(&p_file_info->db_rotate_duration, 0, __ATOMIC_RELAXED)); + } + lgs_mng_update_chart_end(0); + + /* Query CPU time per byte (user) - update */ + lgs_mng_update_chart_begin(rrd_type, "query_cpu_time_per_MiB_user"); + for(int i = 0; i < p_file_infos_arr->count; i++){ + struct File_info *p_file_info = p_file_infos_arr->data[i]; + if(!p_file_info->parser_config) + continue; + + lgs_mng_update_chart_set(p_file_info->chartname, + __atomic_load_n(&p_file_info->cpu_time_per_mib.user, __ATOMIC_RELAXED)); + } + lgs_mng_update_chart_end(0); + + /* Query CPU time per byte (user) - update */ + lgs_mng_update_chart_begin(rrd_type, "query_cpu_time_per_MiB_sys"); + for(int i = 0; i < p_file_infos_arr->count; i++){ + struct File_info *p_file_info = p_file_infos_arr->data[i]; + if(!p_file_info->parser_config) + continue; + + lgs_mng_update_chart_set(p_file_info->chartname, + __atomic_load_n(&p_file_info->cpu_time_per_mib.sys, __ATOMIC_RELAXED)); + } + lgs_mng_update_chart_end(0); + +} + +void stats_charts_init(void *arg){ + + netdata_mutex_t *p_stdout_mut = (netdata_mutex_t *) arg; + + netdata_mutex_lock(p_stdout_mut); + + int chart_prio = NETDATA_CHART_PRIO_LOGS_STATS_BASE; + + /* Circular buffer total memory stats - initialise */ + lgs_mng_create_chart( + rrd_type // type + , "circular_buffers_mem_total_cached" // id + , "Circular buffers total cached memory" // title + , "bytes" // units + , "logsmanagement" // family + , NULL // context + , RRDSET_TYPE_STACKED_NAME // chart_type + , ++chart_prio // priority + , g_logs_manag_config.update_every // update_every + ); + for(int i = 0; i < p_file_infos_arr->count; i++) + lgs_mng_add_dim(p_file_infos_arr->data[i]->chartname, RRD_ALGORITHM_ABSOLUTE_NAME, 1, 1); + + /* Circular buffer number of items - initialise */ + lgs_mng_create_chart( + rrd_type // type + , "circular_buffers_num_of_items" // id + , "Circular buffers number of items" // title + , "items" // units + , "logsmanagement" // family + , NULL // context + , RRDSET_TYPE_LINE_NAME // chart_type + , ++chart_prio // priority + , g_logs_manag_config.update_every // update_every + ); + for(int i = 0; i < p_file_infos_arr->count; i++) + lgs_mng_add_dim(p_file_infos_arr->data[i]->chartname, RRD_ALGORITHM_ABSOLUTE_NAME, 1, 1); + + /* Circular buffer uncompressed buffered items memory stats - initialise */ + lgs_mng_create_chart( + rrd_type // type + , "circular_buffers_mem_uncompressed_used" // id + , "Circular buffers used memory for uncompressed logs" // title + , "bytes" // units + , "logsmanagement" // family + , NULL // context + , RRDSET_TYPE_STACKED_NAME // chart_type + , ++chart_prio // priority + , g_logs_manag_config.update_every // update_every + ); + for(int i = 0; i < p_file_infos_arr->count; i++) + lgs_mng_add_dim(p_file_infos_arr->data[i]->chartname, RRD_ALGORITHM_ABSOLUTE_NAME, 1, 1); + + /* Circular buffer compressed buffered items memory stats - initialise */ + lgs_mng_create_chart( + rrd_type // type + , "circular_buffers_mem_compressed_used" // id + , "Circular buffers used memory for compressed logs" // title + , "bytes" // units + , "logsmanagement" // family + , NULL // context + , RRDSET_TYPE_STACKED_NAME // chart_type + , ++chart_prio // priority + , g_logs_manag_config.update_every // update_every + ); + for(int i = 0; i < p_file_infos_arr->count; i++) + lgs_mng_add_dim(p_file_infos_arr->data[i]->chartname, RRD_ALGORITHM_ABSOLUTE_NAME, 1, 1); + + /* Compression stats - initialise */ + lgs_mng_create_chart( + rrd_type // type + , "average_compression_ratio" // id + , "Average compression ratio" // title + , "uncompressed / compressed ratio" // units + , "logsmanagement" // family + , NULL // context + , RRDSET_TYPE_LINE_NAME // chart_type + , ++chart_prio // priority + , g_logs_manag_config.update_every // update_every + ); + for(int i = 0; i < p_file_infos_arr->count; i++) + lgs_mng_add_dim(p_file_infos_arr->data[i]->chartname, RRD_ALGORITHM_ABSOLUTE_NAME, 1, 1); + + /* DB disk usage stats - initialise */ + lgs_mng_create_chart( + rrd_type // type + , "database_disk_usage" // id + , "Database disk usage" // title + , "bytes" // units + , "logsmanagement" // family + , NULL // context + , RRDSET_TYPE_STACKED_NAME // chart_type + , ++chart_prio // priority + , g_logs_manag_config.update_every // update_every + ); + for(int i = 0; i < p_file_infos_arr->count; i++) + lgs_mng_add_dim(p_file_infos_arr->data[i]->chartname, RRD_ALGORITHM_ABSOLUTE_NAME, 1, 1); + + /* DB timings - initialise */ + lgs_mng_create_chart( + rrd_type // type + , "database_timings" // id + , "Database timings" // title + , "ns" // units + , "logsmanagement" // family + , NULL // context + , RRDSET_TYPE_STACKED_NAME // chart_type + , ++chart_prio // priority + , g_logs_manag_config.update_every // update_every + ); + for(int i = 0; i < p_file_infos_arr->count; i++){ + struct File_info *p_file_info = p_file_infos_arr->data[i]; + + dim_db_timings_write = reallocz(dim_db_timings_write, (i + 1) * sizeof(char *)); + dim_db_timings_rotate = reallocz(dim_db_timings_rotate, (i + 1) * sizeof(char *)); + + dim_db_timings_write[i] = mallocz(snprintf(NULL, 0, "%s_write", p_file_info->chartname) + 1); + sprintf(dim_db_timings_write[i], "%s_write", p_file_info->chartname); + lgs_mng_add_dim(dim_db_timings_write[i], RRD_ALGORITHM_ABSOLUTE_NAME, 1, 1); + + dim_db_timings_rotate[i] = mallocz(snprintf(NULL, 0, "%s_rotate", p_file_info->chartname) + 1); + sprintf(dim_db_timings_rotate[i], "%s_rotate", p_file_info->chartname); + lgs_mng_add_dim(dim_db_timings_rotate[i], RRD_ALGORITHM_ABSOLUTE_NAME, 1, 1); + } + + /* Query CPU time per byte (user) - initialise */ + lgs_mng_create_chart( + rrd_type // type + , "query_cpu_time_per_MiB_user" // id + , "CPU user time per MiB of query results" // title + , "usec/MiB" // units + , "logsmanagement" // family + , NULL // context + , RRDSET_TYPE_STACKED_NAME // chart_type + , ++chart_prio // priority + , g_logs_manag_config.update_every // update_every + ); + for(int i = 0; i < p_file_infos_arr->count; i++) + lgs_mng_add_dim(p_file_infos_arr->data[i]->chartname, RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + + /* Query CPU time per byte (system) - initialise */ + lgs_mng_create_chart( + rrd_type // type + , "query_cpu_time_per_MiB_sys" // id + , "CPU system time per MiB of query results" // title + , "usec/MiB" // units + , "logsmanagement" // family + , NULL // context + , RRDSET_TYPE_STACKED_NAME // chart_type + , ++chart_prio // priority + , g_logs_manag_config.update_every // update_every + ); + for(int i = 0; i < p_file_infos_arr->count; i++) + lgs_mng_add_dim(p_file_infos_arr->data[i]->chartname, RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + + netdata_mutex_unlock(p_stdout_mut); + + + heartbeat_t hb; + heartbeat_init(&hb); + usec_t step_ut = g_logs_manag_config.update_every * USEC_PER_SEC; + + while (0 == __atomic_load_n(&logsmanagement_should_exit, __ATOMIC_RELAXED)) { + heartbeat_next(&hb, step_ut); + + netdata_mutex_lock(p_stdout_mut); + stats_charts_update(); + fflush(stdout); + netdata_mutex_unlock(p_stdout_mut); + } + + collector_info("[stats charts]: thread exiting..."); +} + diff --git a/logsmanagement/rrd_api/rrd_api_stats.h b/logsmanagement/rrd_api/rrd_api_stats.h new file mode 100644 index 00000000..79a0f15d --- /dev/null +++ b/logsmanagement/rrd_api/rrd_api_stats.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +/** @file rrd_api_stats.h + * @brief Incudes the structure and function definitions + * for logs management stats charts. + */ + +#ifndef RRD_API_STATS_H_ +#define RRD_API_STATS_H_ + +#include "daemon/common.h" + +struct File_info; + +#include "../file_info.h" + +void stats_charts_init(void *arg); + +#endif // RRD_API_STATS_H_
\ No newline at end of file diff --git a/logsmanagement/rrd_api/rrd_api_systemd.c b/logsmanagement/rrd_api/rrd_api_systemd.c new file mode 100644 index 00000000..1d489389 --- /dev/null +++ b/logsmanagement/rrd_api/rrd_api_systemd.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rrd_api_systemd.h" + +const char *dim_sever_str[SYSLOG_SEVER_ARR_SIZE] = { + "0:Emergency", + "1:Alert", + "2:Critical", + "3:Error", + "4:Warning", + "5:Notice", + "6:Informational", + "7:Debug", + "uknown" +}; + +static const char *dim_facil_str[SYSLOG_FACIL_ARR_SIZE] = { + "0:kernel", + "1:user-level", + "2:mail", + "3:system", + "4:sec/auth", + "5:syslog", + "6:lpd/printer", + "7:news/nntp", + "8:uucp", + "9:time", + "10:sec/auth", + "11:ftp", + "12:ntp", + "13:logaudit", + "14:logalert", + "15:clock", + "16:local0", + "17:local1", + "18:local2", + "19:local3", + "20:local4", + "21:local5", + "22:local6", + "23:local7", + "uknown" +}; + +void systemd_chart_init(struct File_info *p_file_info){ + p_file_info->chart_meta->chart_data_systemd = callocz(1, sizeof (struct Chart_data_systemd)); + chart_data_systemd_t *chart_data = p_file_info->chart_meta->chart_data_systemd; + chart_data->last_update = now_realtime_sec(); // initial value shouldn't be 0 + long chart_prio = p_file_info->chart_meta->base_prio; + + lgs_mng_do_num_of_logs_charts_init(p_file_info, chart_prio); + + /* Syslog priority value - initialise */ + if(p_file_info->parser_config->chart_config & CHART_SYSLOG_PRIOR){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "priority_values" // id + , "Priority Values" // title + , "priority values" // units + , "priority" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + for(int i = 0; i < SYSLOG_PRIOR_ARR_SIZE - 1; i++){ + char dim_id[4]; + snprintfz(dim_id, 4, "%d", i); + chart_data->dim_prior[i] = strdupz(dim_id); + lgs_mng_add_dim(chart_data->dim_prior[i], RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + chart_data->dim_prior[SYSLOG_PRIOR_ARR_SIZE - 1] = "uknown"; + lgs_mng_add_dim(chart_data->dim_prior[SYSLOG_PRIOR_ARR_SIZE - 1], + RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + + } + + /* Syslog severity level (== Systemd priority) - initialise */ + if(p_file_info->parser_config->chart_config & CHART_SYSLOG_SEVER){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "severity_levels" // id + , "Severity Levels" // title + , "severity levels" // units + , "priority" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + for(int i = 0; i < SYSLOG_SEVER_ARR_SIZE; i++) + lgs_mng_add_dim(dim_sever_str[i], RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + + /* Syslog facility level - initialise */ + if(p_file_info->parser_config->chart_config & CHART_SYSLOG_FACIL){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "facility_levels" // id + , "Facility Levels" // title + , "facility levels" // units + , "priority" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + for(int i = 0; i < SYSLOG_FACIL_ARR_SIZE; i++) + lgs_mng_add_dim(dim_facil_str[i], RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + + lgs_mng_do_custom_charts_init(p_file_info); +} + +void systemd_chart_update(struct File_info *p_file_info){ + chart_data_systemd_t *chart_data = p_file_info->chart_meta->chart_data_systemd; + + if(chart_data->last_update != p_file_info->parser_metrics->last_update){ + + time_t lag_in_sec = p_file_info->parser_metrics->last_update - chart_data->last_update - 1; + + lgs_mng_do_num_of_logs_charts_update(p_file_info, lag_in_sec, chart_data); + + /* Syslog priority value - update */ + if(p_file_info->parser_config->chart_config & CHART_SYSLOG_PRIOR){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "priority_values"); + for(int idx = 0; idx < SYSLOG_PRIOR_ARR_SIZE; idx++){ + if(chart_data->num_prior[idx]) + lgs_mng_update_chart_set(chart_data->dim_prior[idx], chart_data->num_prior[idx]); + } + lgs_mng_update_chart_end(sec); + } + + lgs_mng_update_chart_begin(p_file_info->chartname, "priority_values"); + for(int idx = 0; idx < SYSLOG_PRIOR_ARR_SIZE; idx++){ + if(p_file_info->parser_metrics->systemd->prior[idx]){ + chart_data->num_prior[idx] = p_file_info->parser_metrics->systemd->prior[idx]; + lgs_mng_update_chart_set(chart_data->dim_prior[idx], chart_data->num_prior[idx]); + } + } + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + + } + + /* Syslog severity level (== Systemd priority) - update chart */ + if(p_file_info->parser_config->chart_config & CHART_SYSLOG_SEVER){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "severity_levels"); + for(int idx = 0; idx < SYSLOG_SEVER_ARR_SIZE; idx++){ + if(chart_data->num_sever[idx]) + lgs_mng_update_chart_set(dim_sever_str[idx], chart_data->num_sever[idx]); + } + lgs_mng_update_chart_end(sec); + } + + lgs_mng_update_chart_begin(p_file_info->chartname, "severity_levels"); + for(int idx = 0; idx < SYSLOG_SEVER_ARR_SIZE; idx++){ + if(p_file_info->parser_metrics->systemd->sever[idx]){ + chart_data->num_sever[idx] = p_file_info->parser_metrics->systemd->sever[idx]; + lgs_mng_update_chart_set(dim_sever_str[idx], chart_data->num_sever[idx]); + } + } + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + + } + + /* Syslog facility value - update chart */ + if(p_file_info->parser_config->chart_config & CHART_SYSLOG_FACIL){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "facility_levels"); + for(int idx = 0; idx < SYSLOG_FACIL_ARR_SIZE; idx++){ + if(chart_data->num_facil[idx]) + lgs_mng_update_chart_set(dim_facil_str[idx], chart_data->num_facil[idx]); + } + lgs_mng_update_chart_end(sec); + } + + lgs_mng_update_chart_begin(p_file_info->chartname, "facility_levels"); + for(int idx = 0; idx < SYSLOG_FACIL_ARR_SIZE; idx++){ + if(p_file_info->parser_metrics->systemd->facil[idx]){ + chart_data->num_facil[idx] = p_file_info->parser_metrics->systemd->facil[idx]; + lgs_mng_update_chart_set(dim_facil_str[idx], chart_data->num_facil[idx]); + } + } + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + + } + + lgs_mng_do_custom_charts_update(p_file_info, lag_in_sec); + + chart_data->last_update = p_file_info->parser_metrics->last_update; + } +} diff --git a/logsmanagement/rrd_api/rrd_api_systemd.h b/logsmanagement/rrd_api/rrd_api_systemd.h new file mode 100644 index 00000000..3497168f --- /dev/null +++ b/logsmanagement/rrd_api/rrd_api_systemd.h @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +/** @file plugins_logsmanagement_systemd.h + * @brief Incudes the structure and function definitions + * for the systemd log charts. + */ + +#ifndef RRD_API_SYSTEMD_H_ +#define RRD_API_SYSTEMD_H_ + +#include "daemon/common.h" + +struct File_info; + +typedef struct Chart_data_systemd chart_data_systemd_t; + +#include "../file_info.h" +#include "../circular_buffer.h" + +#include "rrd_api.h" + +extern const char *dim_sever_str[SYSLOG_SEVER_ARR_SIZE]; + +struct Chart_data_systemd { + + time_t last_update; + + /* Number of collected log records */ + collected_number num_lines; + + /* Systemd metrics - Syslog Priority value */ + char *dim_prior[193]; + collected_number num_prior[193]; + + /* Systemd metrics - Syslog Severity value */ + collected_number num_sever[9]; + + /* Systemd metrics - Syslog Facility value */ + collected_number num_facil[25]; +}; + +void systemd_chart_init(struct File_info *p_file_info); +void systemd_chart_update(struct File_info *p_file_info); + +#endif // RRD_API_SYSTEMD_H_ diff --git a/logsmanagement/rrd_api/rrd_api_web_log.c b/logsmanagement/rrd_api/rrd_api_web_log.c new file mode 100644 index 00000000..5ab60204 --- /dev/null +++ b/logsmanagement/rrd_api/rrd_api_web_log.c @@ -0,0 +1,716 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rrd_api_web_log.h" + +void web_log_chart_init(struct File_info *p_file_info){ + p_file_info->chart_meta->chart_data_web_log = callocz(1, sizeof (struct Chart_data_web_log)); + chart_data_web_log_t *chart_data = p_file_info->chart_meta->chart_data_web_log; + chart_data->last_update = now_realtime_sec(); // initial value shouldn't be 0 + long chart_prio = p_file_info->chart_meta->base_prio; + + lgs_mng_do_num_of_logs_charts_init(p_file_info, chart_prio); + + /* Vhost - initialise */ + if(p_file_info->parser_config->chart_config & CHART_VHOST){ + chart_data->cs_vhosts = lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "vhost" // id + , "Requests by Vhost" // title + , "requests" // units + , "vhost" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + } + + /* Port - initialise */ + if(p_file_info->parser_config->chart_config & CHART_PORT){ + chart_data->cs_ports = lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "port" // id + , "Requests by Port" // title + , "requests" // units + , "port" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + } + + /* IP Version - initialise */ + if(p_file_info->parser_config->chart_config & CHART_IP_VERSION){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "ip_version" // id + , "Requests by IP version" // title + , "requests" // units + , "ip_version" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + lgs_mng_add_dim("ipv4", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("ipv6", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("invalid", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + + /* Request client current poll - initialise */ + if(p_file_info->parser_config->chart_config & CHART_REQ_CLIENT_CURRENT){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "clients" // id + , "Current Poll Unique Client IPs" // title + , "unique ips" // units + , "clients" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + lgs_mng_add_dim("ipv4", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("ipv6", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + + /* Request client all-time - initialise */ + if(p_file_info->parser_config->chart_config & CHART_REQ_CLIENT_ALL_TIME){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "clients_all" // id + , "All Time Unique Client IPs" // title + , "unique ips" // units + , "clients" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + lgs_mng_add_dim("ipv4", RRD_ALGORITHM_ABSOLUTE_NAME, 1, 1); + lgs_mng_add_dim("ipv6", RRD_ALGORITHM_ABSOLUTE_NAME, 1, 1); + } + + /* Request methods - initialise */ + if(p_file_info->parser_config->chart_config & CHART_REQ_METHODS){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "http_methods" // id + , "Requests Per HTTP Method" // title + , "requests" // units + , "http_methods" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + for(int j = 0; j < REQ_METHOD_ARR_SIZE; j++) + lgs_mng_add_dim(req_method_str[j], RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + + /* Request protocol - initialise */ + if(p_file_info->parser_config->chart_config & CHART_REQ_PROTO){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "http_versions" // id + , "Requests Per HTTP Version" // title + , "requests" // units + , "http_versions" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + lgs_mng_add_dim("1.0", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("1.1", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("2.0", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("other", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + + /* Request bandwidth - initialise */ + if(p_file_info->parser_config->chart_config & CHART_BANDWIDTH){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "bandwidth" // id + , "Bandwidth" // title + , "kilobits" // units + , "bandwidth" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + lgs_mng_add_dim("received", RRD_ALGORITHM_INCREMENTAL_NAME, 8, 1000); + lgs_mng_add_dim("sent", RRD_ALGORITHM_INCREMENTAL_NAME, -8, 1000); + } + + /* Request processing time - initialise */ + if(p_file_info->parser_config->chart_config & CHART_REQ_PROC_TIME){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "timings" // id + , "Request Processing Time" // title + , "milliseconds" // units + , "timings" // family + , NULL // context + , RRDSET_TYPE_LINE_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + lgs_mng_add_dim("min", RRD_ALGORITHM_ABSOLUTE_NAME, 1, 1000); + lgs_mng_add_dim("max", RRD_ALGORITHM_ABSOLUTE_NAME, 1, 1000); + lgs_mng_add_dim("avg", RRD_ALGORITHM_ABSOLUTE_NAME, 1, 1000); + } + + /* Response code family - initialise */ + if(p_file_info->parser_config->chart_config & CHART_RESP_CODE_FAMILY){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "responses" // id + , "Response Codes" // title + , "requests" // units + , "responses" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + lgs_mng_add_dim("1xx", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("2xx", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("3xx", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("4xx", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("5xx", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("other", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + + /* Response code - initialise */ + if(p_file_info->parser_config->chart_config & CHART_RESP_CODE){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "detailed_responses" // id + , "Detailed Response Codes" // title + , "requests" // units + , "responses" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + for(int idx = 0; idx < RESP_CODE_ARR_SIZE - 1; idx++){ + char dim_name[4]; + snprintfz(dim_name, 4, "%d", idx + 100); + lgs_mng_add_dim(dim_name, RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + } + + /* Response code type - initialise */ + if(p_file_info->parser_config->chart_config & CHART_RESP_CODE_TYPE){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "response_types" // id + , "Response Statuses" // title + , "requests" // units + , "responses" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + lgs_mng_add_dim("success", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("redirect", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("bad", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("error", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("other", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + + /* SSL protocol - initialise */ + if(p_file_info->parser_config->chart_config & CHART_SSL_PROTO){ + lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "ssl_protocol" // id + , "Requests Per SSL Protocol" // title + , "requests" // units + , "ssl_protocol" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + + lgs_mng_add_dim("TLSV1", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("TLSV1.1", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("TLSV1.2", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("TLSV1.3", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("SSLV2", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("SSLV3", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + lgs_mng_add_dim("other", RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + + /* SSL cipher suite - initialise */ + if(p_file_info->parser_config->chart_config & CHART_SSL_CIPHER){ + chart_data->cs_ssl_ciphers = lgs_mng_create_chart( + (char *) p_file_info->chartname // type + , "ssl_cipher_suite" // id + , "Requests by SSL cipher suite" // title + , "requests" // units + , "ssl_cipher_suite" // family + , NULL // context + , RRDSET_TYPE_AREA_NAME // chart_type + , ++chart_prio // priority + , p_file_info->update_every // update_every + ); + } + + lgs_mng_do_custom_charts_init(p_file_info); +} + + +void web_log_chart_update(struct File_info *p_file_info){ + chart_data_web_log_t *chart_data = p_file_info->chart_meta->chart_data_web_log; + Web_log_metrics_t *wlm = p_file_info->parser_metrics->web_log; + + if(chart_data->last_update != p_file_info->parser_metrics->last_update){ + + time_t lag_in_sec = p_file_info->parser_metrics->last_update - chart_data->last_update - 1; + + lgs_mng_do_num_of_logs_charts_update(p_file_info, lag_in_sec, chart_data); + + /* Vhost - update */ + if(p_file_info->parser_config->chart_config & CHART_VHOST){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "vhost"); + for(int idx = 0; idx < chart_data->vhost_size; idx++) + lgs_mng_update_chart_set(wlm->vhost_arr.vhosts[idx].name, chart_data->num_vhosts[idx]); + lgs_mng_update_chart_end(sec); + } + + if(wlm->vhost_arr.size > chart_data->vhost_size){ + if(wlm->vhost_arr.size >= chart_data->vhost_size_max){ + chart_data->vhost_size_max = wlm->vhost_arr.size * VHOST_BUFFS_SCALE_FACTOR + 1; + chart_data->num_vhosts = reallocz( chart_data->num_vhosts, + chart_data->vhost_size_max * sizeof(collected_number)); + + } + + for(int idx = chart_data->vhost_size; idx < wlm->vhost_arr.size; idx++){ + chart_data->num_vhosts[idx] = 0; + lgs_mng_add_dim_post_init( &chart_data->cs_vhosts, + wlm->vhost_arr.vhosts[idx].name, + RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + + chart_data->vhost_size = wlm->vhost_arr.size; + } + + lgs_mng_update_chart_begin(p_file_info->chartname, "vhost"); + for(int idx = 0; idx < chart_data->vhost_size; idx++){ + chart_data->num_vhosts[idx] += wlm->vhost_arr.vhosts[idx].count; + wlm->vhost_arr.vhosts[idx].count = 0; + lgs_mng_update_chart_set(wlm->vhost_arr.vhosts[idx].name, chart_data->num_vhosts[idx]); + } + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* Port - update */ + if(p_file_info->parser_config->chart_config & CHART_PORT){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "port"); + for(int idx = 0; idx < chart_data->port_size; idx++) + lgs_mng_update_chart_set(wlm->port_arr.ports[idx].name, chart_data->num_ports[idx]); + lgs_mng_update_chart_end(sec); + } + + if(wlm->port_arr.size > chart_data->port_size){ + if(wlm->port_arr.size >= chart_data->port_size_max){ + chart_data->port_size_max = wlm->port_arr.size * PORT_BUFFS_SCALE_FACTOR + 1; + chart_data->num_ports = reallocz( chart_data->num_ports, + chart_data->port_size_max * sizeof(collected_number)); + } + + for(int idx = chart_data->port_size; idx < wlm->port_arr.size; idx++){ + chart_data->num_ports[idx] = 0; + lgs_mng_add_dim_post_init( &chart_data->cs_ports, + wlm->port_arr.ports[idx].name, + RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + + chart_data->port_size = wlm->port_arr.size; + } + + lgs_mng_update_chart_begin(p_file_info->chartname, "port"); + for(int idx = 0; idx < chart_data->port_size; idx++){ + chart_data->num_ports[idx] += wlm->port_arr.ports[idx].count; + wlm->port_arr.ports[idx].count = 0; + lgs_mng_update_chart_set(wlm->port_arr.ports[idx].name, chart_data->num_ports[idx]); + } + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* IP Version - update */ + if(p_file_info->parser_config->chart_config & CHART_IP_VERSION){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "ip_version"); + lgs_mng_update_chart_set("ipv4", chart_data->num_ip_ver_4); + lgs_mng_update_chart_set("ipv6", chart_data->num_ip_ver_6); + lgs_mng_update_chart_set("invalid", chart_data->num_ip_ver_invalid); + lgs_mng_update_chart_end(sec); + } + + chart_data->num_ip_ver_4 += wlm->ip_ver.v4; + chart_data->num_ip_ver_6 += wlm->ip_ver.v6; + chart_data->num_ip_ver_invalid += wlm->ip_ver.invalid; + memset(&wlm->ip_ver, 0, sizeof(wlm->ip_ver)); + + lgs_mng_update_chart_begin(p_file_info->chartname, "ip_version"); + lgs_mng_update_chart_set("ipv4", chart_data->num_ip_ver_4); + lgs_mng_update_chart_set("ipv6", chart_data->num_ip_ver_6); + lgs_mng_update_chart_set("invalid", chart_data->num_ip_ver_invalid); + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* Request client current poll - update */ + if(p_file_info->parser_config->chart_config & CHART_REQ_CLIENT_CURRENT){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "clients"); + lgs_mng_update_chart_set("ipv4", chart_data->num_req_client_current_ipv4); + lgs_mng_update_chart_set("ipv6", chart_data->num_req_client_current_ipv6); + lgs_mng_update_chart_end(sec); + } + + chart_data->num_req_client_current_ipv4 += wlm->req_clients_current_arr.ipv4_size; + wlm->req_clients_current_arr.ipv4_size = 0; + chart_data->num_req_client_current_ipv6 += wlm->req_clients_current_arr.ipv6_size; + wlm->req_clients_current_arr.ipv6_size = 0; + + lgs_mng_update_chart_begin(p_file_info->chartname, "clients"); + lgs_mng_update_chart_set("ipv4", chart_data->num_req_client_current_ipv4); + lgs_mng_update_chart_set("ipv6", chart_data->num_req_client_current_ipv6); + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* Request client all-time - update */ + if(p_file_info->parser_config->chart_config & CHART_REQ_CLIENT_ALL_TIME){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "clients_all"); + lgs_mng_update_chart_set("ipv4", chart_data->num_req_client_all_time_ipv4); + lgs_mng_update_chart_set("ipv6", chart_data->num_req_client_all_time_ipv6); + lgs_mng_update_chart_end(sec); + } + + chart_data->num_req_client_all_time_ipv4 = wlm->req_clients_alltime_arr.ipv4_size; + chart_data->num_req_client_all_time_ipv6 = wlm->req_clients_alltime_arr.ipv6_size; + + lgs_mng_update_chart_begin(p_file_info->chartname, "clients_all"); + lgs_mng_update_chart_set("ipv4", chart_data->num_req_client_all_time_ipv4); + lgs_mng_update_chart_set("ipv6", chart_data->num_req_client_all_time_ipv6); + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* Request methods - update */ + if(p_file_info->parser_config->chart_config & CHART_REQ_METHODS){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "http_methods"); + for(int idx = 0; idx < REQ_METHOD_ARR_SIZE; idx++){ + if(chart_data->num_req_method[idx]) + lgs_mng_update_chart_set(req_method_str[idx], chart_data->num_req_method[idx]); + } + lgs_mng_update_chart_end(sec); + } + + lgs_mng_update_chart_begin(p_file_info->chartname, "http_methods"); + for(int idx = 0; idx < REQ_METHOD_ARR_SIZE; idx++){ + chart_data->num_req_method[idx] += wlm->req_method[idx]; + wlm->req_method[idx] = 0; + if(chart_data->num_req_method[idx]) + lgs_mng_update_chart_set(req_method_str[idx], chart_data->num_req_method[idx]); + } + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* Request protocol - update */ + if(p_file_info->parser_config->chart_config & CHART_REQ_PROTO){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "http_versions"); + lgs_mng_update_chart_set("1.0", chart_data->num_req_proto_http_1); + lgs_mng_update_chart_set("1.1", chart_data->num_req_proto_http_1_1); + lgs_mng_update_chart_set("2.0", chart_data->num_req_proto_http_2); + lgs_mng_update_chart_set("other", chart_data->num_req_proto_other); + lgs_mng_update_chart_end(sec); + } + + chart_data->num_req_proto_http_1 += wlm->req_proto.http_1; + chart_data->num_req_proto_http_1_1 += wlm->req_proto.http_1_1; + chart_data->num_req_proto_http_2 += wlm->req_proto.http_2; + chart_data->num_req_proto_other += wlm->req_proto.other; + memset(&wlm->req_proto, 0, sizeof(wlm->req_proto)); + + lgs_mng_update_chart_begin(p_file_info->chartname, "http_versions"); + lgs_mng_update_chart_set("1.0", chart_data->num_req_proto_http_1); + lgs_mng_update_chart_set("1.1", chart_data->num_req_proto_http_1_1); + lgs_mng_update_chart_set("2.0", chart_data->num_req_proto_http_2); + lgs_mng_update_chart_set("other", chart_data->num_req_proto_other); + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* Request bandwidth - update */ + if(p_file_info->parser_config->chart_config & CHART_BANDWIDTH){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "bandwidth"); + lgs_mng_update_chart_set("received", chart_data->num_bandwidth_req_size); + lgs_mng_update_chart_set("sent", chart_data->num_bandwidth_resp_size); + lgs_mng_update_chart_end(sec); + } + + chart_data->num_bandwidth_req_size += wlm->bandwidth.req_size; + chart_data->num_bandwidth_resp_size += wlm->bandwidth.resp_size; + memset(&wlm->bandwidth, 0, sizeof(wlm->bandwidth)); + + lgs_mng_update_chart_begin(p_file_info->chartname, "bandwidth"); + lgs_mng_update_chart_set("received", chart_data->num_bandwidth_req_size); + lgs_mng_update_chart_set("sent", chart_data->num_bandwidth_resp_size); + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* Request proc time - update */ + if(p_file_info->parser_config->chart_config & CHART_REQ_PROC_TIME){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "timings"); + lgs_mng_update_chart_set("min", chart_data->num_req_proc_time_min); + lgs_mng_update_chart_set("max", chart_data->num_req_proc_time_max); + lgs_mng_update_chart_set("avg", chart_data->num_req_proc_time_avg); + lgs_mng_update_chart_end(sec); + } + + chart_data->num_req_proc_time_min = wlm->req_proc_time.min; + chart_data->num_req_proc_time_max = wlm->req_proc_time.max; + chart_data->num_req_proc_time_avg = wlm->req_proc_time.count ? + wlm->req_proc_time.sum / wlm->req_proc_time.count : 0; + memset(&wlm->req_proc_time, 0, sizeof(wlm->req_proc_time)); + + lgs_mng_update_chart_begin(p_file_info->chartname, "timings"); + lgs_mng_update_chart_set("min", chart_data->num_req_proc_time_min); + lgs_mng_update_chart_set("max", chart_data->num_req_proc_time_max); + lgs_mng_update_chart_set("avg", chart_data->num_req_proc_time_avg); + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* Response code family - update */ + if(p_file_info->parser_config->chart_config & CHART_RESP_CODE_FAMILY){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "responses"); + lgs_mng_update_chart_set("1xx", chart_data->num_resp_code_family_1xx); + lgs_mng_update_chart_set("2xx", chart_data->num_resp_code_family_2xx); + lgs_mng_update_chart_set("3xx", chart_data->num_resp_code_family_3xx); + lgs_mng_update_chart_set("4xx", chart_data->num_resp_code_family_4xx); + lgs_mng_update_chart_set("5xx", chart_data->num_resp_code_family_5xx); + lgs_mng_update_chart_set("other", chart_data->num_resp_code_family_other); + lgs_mng_update_chart_end(sec); + } + + chart_data->num_resp_code_family_1xx += wlm->resp_code_family.resp_1xx; + chart_data->num_resp_code_family_2xx += wlm->resp_code_family.resp_2xx; + chart_data->num_resp_code_family_3xx += wlm->resp_code_family.resp_3xx; + chart_data->num_resp_code_family_4xx += wlm->resp_code_family.resp_4xx; + chart_data->num_resp_code_family_5xx += wlm->resp_code_family.resp_5xx; + chart_data->num_resp_code_family_other += wlm->resp_code_family.other; + memset(&wlm->resp_code_family, 0, sizeof(wlm->resp_code_family)); + + lgs_mng_update_chart_begin(p_file_info->chartname, "responses"); + lgs_mng_update_chart_set("1xx", chart_data->num_resp_code_family_1xx); + lgs_mng_update_chart_set("2xx", chart_data->num_resp_code_family_2xx); + lgs_mng_update_chart_set("3xx", chart_data->num_resp_code_family_3xx); + lgs_mng_update_chart_set("4xx", chart_data->num_resp_code_family_4xx); + lgs_mng_update_chart_set("5xx", chart_data->num_resp_code_family_5xx); + lgs_mng_update_chart_set("other", chart_data->num_resp_code_family_other); + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* Response code - update */ + if(p_file_info->parser_config->chart_config & CHART_RESP_CODE){ + char dim_name[4]; + + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "detailed_responses"); + for(int idx = 0; idx < RESP_CODE_ARR_SIZE - 1; idx++){ + if(chart_data->num_resp_code[idx]){ + snprintfz(dim_name, 4, "%d", idx + 100); + lgs_mng_update_chart_set(dim_name, chart_data->num_resp_code[idx]); + } + } + if(chart_data->num_resp_code[RESP_CODE_ARR_SIZE - 1]) + lgs_mng_update_chart_set("other", chart_data->num_resp_code[RESP_CODE_ARR_SIZE - 1]); + lgs_mng_update_chart_end(sec); + } + + lgs_mng_update_chart_begin(p_file_info->chartname, "detailed_responses"); + for(int idx = 0; idx < RESP_CODE_ARR_SIZE - 1; idx++){ + chart_data->num_resp_code[idx] += wlm->resp_code[idx]; + wlm->resp_code[idx] = 0; + if(chart_data->num_resp_code[idx]){ + snprintfz(dim_name, 4, "%d", idx + 100); + lgs_mng_update_chart_set(dim_name, chart_data->num_resp_code[idx]); + } + } + chart_data->num_resp_code[RESP_CODE_ARR_SIZE - 1] += wlm->resp_code[RESP_CODE_ARR_SIZE - 1]; + wlm->resp_code[RESP_CODE_ARR_SIZE - 1] = 0; + if(chart_data->num_resp_code[RESP_CODE_ARR_SIZE - 1]) + lgs_mng_update_chart_set("other", chart_data->num_resp_code[RESP_CODE_ARR_SIZE - 1]); + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* Response code type - update */ + if(p_file_info->parser_config->chart_config & CHART_RESP_CODE_TYPE){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "response_types"); + lgs_mng_update_chart_set("success", chart_data->num_resp_code_type_success); + lgs_mng_update_chart_set("redirect", chart_data->num_resp_code_type_redirect); + lgs_mng_update_chart_set("bad", chart_data->num_resp_code_type_bad); + lgs_mng_update_chart_set("error", chart_data->num_resp_code_type_error); + lgs_mng_update_chart_set("other", chart_data->num_resp_code_type_other); + lgs_mng_update_chart_end(sec); + } + + chart_data->num_resp_code_type_success += wlm->resp_code_type.resp_success; + chart_data->num_resp_code_type_redirect += wlm->resp_code_type.resp_redirect; + chart_data->num_resp_code_type_bad += wlm->resp_code_type.resp_bad; + chart_data->num_resp_code_type_error += wlm->resp_code_type.resp_error; + chart_data->num_resp_code_type_other += wlm->resp_code_type.other; + memset(&wlm->resp_code_type, 0, sizeof(wlm->resp_code_type)); + + lgs_mng_update_chart_begin(p_file_info->chartname, "response_types"); + lgs_mng_update_chart_set("success", chart_data->num_resp_code_type_success); + lgs_mng_update_chart_set("redirect", chart_data->num_resp_code_type_redirect); + lgs_mng_update_chart_set("bad", chart_data->num_resp_code_type_bad); + lgs_mng_update_chart_set("error", chart_data->num_resp_code_type_error); + lgs_mng_update_chart_set("other", chart_data->num_resp_code_type_other); + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* SSL protocol - update */ + if(p_file_info->parser_config->chart_config & CHART_SSL_PROTO){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "ssl_protocol"); + lgs_mng_update_chart_set("TLSV1", chart_data->num_ssl_proto_tlsv1); + lgs_mng_update_chart_set("TLSV1.1", chart_data->num_ssl_proto_tlsv1_1); + lgs_mng_update_chart_set("TLSV1.2", chart_data->num_ssl_proto_tlsv1_2); + lgs_mng_update_chart_set("TLSV1.3", chart_data->num_ssl_proto_tlsv1_3); + lgs_mng_update_chart_set("SSLV2", chart_data->num_ssl_proto_sslv2); + lgs_mng_update_chart_set("SSLV3", chart_data->num_ssl_proto_sslv3); + lgs_mng_update_chart_set("other", chart_data->num_ssl_proto_other); + lgs_mng_update_chart_end(sec); + } + + chart_data->num_ssl_proto_tlsv1 += wlm->ssl_proto.tlsv1; + chart_data->num_ssl_proto_tlsv1_1 += wlm->ssl_proto.tlsv1_1; + chart_data->num_ssl_proto_tlsv1_2 += wlm->ssl_proto.tlsv1_2; + chart_data->num_ssl_proto_tlsv1_3 += wlm->ssl_proto.tlsv1_3; + chart_data->num_ssl_proto_sslv2 += wlm->ssl_proto.sslv2; + chart_data->num_ssl_proto_sslv3 += wlm->ssl_proto.sslv3; + chart_data->num_ssl_proto_other += wlm->ssl_proto.other; + memset(&wlm->ssl_proto, 0, sizeof(wlm->ssl_proto)); + + lgs_mng_update_chart_begin(p_file_info->chartname, "ssl_protocol"); + lgs_mng_update_chart_set("TLSV1", chart_data->num_ssl_proto_tlsv1); + lgs_mng_update_chart_set("TLSV1.1", chart_data->num_ssl_proto_tlsv1_1); + lgs_mng_update_chart_set("TLSV1.2", chart_data->num_ssl_proto_tlsv1_2); + lgs_mng_update_chart_set("TLSV1.3", chart_data->num_ssl_proto_tlsv1_3); + lgs_mng_update_chart_set("SSLV2", chart_data->num_ssl_proto_sslv2); + lgs_mng_update_chart_set("SSLV3", chart_data->num_ssl_proto_sslv3); + lgs_mng_update_chart_set("other", chart_data->num_ssl_proto_other); + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + /* SSL cipher suite - update */ + if(p_file_info->parser_config->chart_config & CHART_SSL_CIPHER){ + for(time_t sec = p_file_info->parser_metrics->last_update - lag_in_sec; + sec < p_file_info->parser_metrics->last_update; + sec++){ + + lgs_mng_update_chart_begin(p_file_info->chartname, "ssl_cipher_suite"); + for(int idx = 0; idx < chart_data->ssl_cipher_size; idx++){ + lgs_mng_update_chart_set( wlm->ssl_cipher_arr.ssl_ciphers[idx].name, + chart_data->num_ssl_ciphers[idx]); + } + lgs_mng_update_chart_end(sec); + } + + if(wlm->ssl_cipher_arr.size > chart_data->ssl_cipher_size){ + chart_data->ssl_cipher_size = wlm->ssl_cipher_arr.size; + chart_data->num_ssl_ciphers = reallocz( chart_data->num_ssl_ciphers, + chart_data->ssl_cipher_size * sizeof(collected_number)); + + for(int idx = chart_data->ssl_cipher_size; idx < wlm->ssl_cipher_arr.size; idx++){ + chart_data->num_ssl_ciphers[idx] = 0; + lgs_mng_add_dim_post_init( &chart_data->cs_ssl_ciphers, + wlm->ssl_cipher_arr.ssl_ciphers[idx].name, + RRD_ALGORITHM_INCREMENTAL_NAME, 1, 1); + } + + chart_data->ssl_cipher_size = wlm->ssl_cipher_arr.size; + } + + lgs_mng_update_chart_begin(p_file_info->chartname, "ssl_cipher_suite"); + for(int idx = 0; idx < chart_data->ssl_cipher_size; idx++){ + chart_data->num_ssl_ciphers[idx] += wlm->ssl_cipher_arr.ssl_ciphers[idx].count; + wlm->ssl_cipher_arr.ssl_ciphers[idx].count = 0; + lgs_mng_update_chart_set( wlm->ssl_cipher_arr.ssl_ciphers[idx].name, + chart_data->num_ssl_ciphers[idx]); + } + lgs_mng_update_chart_end(p_file_info->parser_metrics->last_update); + } + + lgs_mng_do_custom_charts_update(p_file_info, lag_in_sec); + + chart_data->last_update = p_file_info->parser_metrics->last_update; + } +} diff --git a/logsmanagement/rrd_api/rrd_api_web_log.h b/logsmanagement/rrd_api/rrd_api_web_log.h new file mode 100644 index 00000000..de0c88e3 --- /dev/null +++ b/logsmanagement/rrd_api/rrd_api_web_log.h @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +/** @file rrd_api_web_log.h + * @brief Incudes the structure and function definitions for + * the web log charts. + */ + +#ifndef RRD_API_WEB_LOG_H_ +#define RRD_API_WEB_LOG_H_ + +#include "daemon/common.h" + +struct File_info; + +typedef struct Chart_data_web_log chart_data_web_log_t; + +#include "../file_info.h" +#include "../circular_buffer.h" + +#include "rrd_api.h" + +struct Chart_data_web_log { + + time_t last_update; + + /* Number of collected log records */ + collected_number num_lines; + + /* Vhosts */ + struct Chart_str cs_vhosts; + collected_number *num_vhosts; + int vhost_size, vhost_size_max; /**< Actual size and maximum allocated size of dim_vhosts, num_vhosts arrays **/ + + /* Ports */ + struct Chart_str cs_ports; + collected_number *num_ports; + int port_size, port_size_max; /**< Actual size and maximum allocated size of dim_ports, num_ports and ports arrays **/ + + /* IP Version */ + collected_number num_ip_ver_4, num_ip_ver_6, num_ip_ver_invalid; + + /* Request client current poll */ + collected_number num_req_client_current_ipv4, num_req_client_current_ipv6; + + /* Request client all-time */ + collected_number num_req_client_all_time_ipv4, num_req_client_all_time_ipv6; + + /* Request methods */ + collected_number num_req_method[REQ_METHOD_ARR_SIZE]; + + /* Request protocol */ + collected_number num_req_proto_http_1, num_req_proto_http_1_1, + num_req_proto_http_2, num_req_proto_other; + + /* Request bandwidth */ + collected_number num_bandwidth_req_size, num_bandwidth_resp_size; + + /* Request processing time */ + collected_number num_req_proc_time_min, num_req_proc_time_max, num_req_proc_time_avg; + + /* Response code family */ + collected_number num_resp_code_family_1xx, num_resp_code_family_2xx, + num_resp_code_family_3xx, num_resp_code_family_4xx, + num_resp_code_family_5xx, num_resp_code_family_other; + + /* Response code */ + collected_number num_resp_code[RESP_CODE_ARR_SIZE]; + + /* Response code type */ + collected_number num_resp_code_type_success, num_resp_code_type_redirect, + num_resp_code_type_bad, num_resp_code_type_error, num_resp_code_type_other; + + /* SSL protocol */ + collected_number num_ssl_proto_tlsv1, num_ssl_proto_tlsv1_1, + num_ssl_proto_tlsv1_2, num_ssl_proto_tlsv1_3, + num_ssl_proto_sslv2, num_ssl_proto_sslv3, num_ssl_proto_other; + + /* SSL cipher suite */ + struct Chart_str cs_ssl_ciphers; + collected_number *num_ssl_ciphers; + int ssl_cipher_size; + +}; + +void web_log_chart_init(struct File_info *p_file_info); +void web_log_chart_update(struct File_info *p_file_info); + +#endif // RRD_API_WEB_LOG_H_ |