123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410 |
- // SPDX-License-Identifier: GPL-3.0-or-later
- /** @file logsmanag_config.c
- * @brief This file includes functions to manage
- * the logs management configuration.
- */
- #include "logsmanag_config.h"
- #include "db_api.h"
- #include "rrd_api/rrd_api.h"
- #include "helper.h"
- g_logs_manag_config_t g_logs_manag_config = {
- .update_every = UPDATE_EVERY,
- .update_timeout = UPDATE_TIMEOUT_DEFAULT,
- .use_log_timestamp = CONFIG_BOOLEAN_AUTO,
- .circ_buff_max_size_in_mib = CIRCULAR_BUFF_DEFAULT_MAX_SIZE / (1 MiB),
- .circ_buff_drop_logs = CIRCULAR_BUFF_DEFAULT_DROP_LOGS,
- .compression_acceleration = COMPRESSION_ACCELERATION_DEFAULT,
- .db_mode = GLOBAL_DB_MODE_DEFAULT,
- .disk_space_limit_in_mib = DISK_SPACE_LIMIT_DEFAULT,
- .buff_flush_to_db_interval = SAVE_BLOB_TO_DB_DEFAULT,
- .enable_collected_logs_total = ENABLE_COLLECTED_LOGS_TOTAL_DEFAULT,
- .enable_collected_logs_rate = ENABLE_COLLECTED_LOGS_RATE_DEFAULT,
- .sd_journal_field_prefix = SD_JOURNAL_FIELD_PREFIX,
- .do_sd_journal_send = SD_JOURNAL_SEND_DEFAULT
- };
- static logs_manag_db_mode_t db_mode_str_to_db_mode(const char *const db_mode_str){
- if(!db_mode_str || !*db_mode_str) return g_logs_manag_config.db_mode;
- else if(!strcasecmp(db_mode_str, "full")) return LOGS_MANAG_DB_MODE_FULL;
- else if(!strcasecmp(db_mode_str, "none")) return LOGS_MANAG_DB_MODE_NONE;
- else return g_logs_manag_config.db_mode;
- }
- static struct config log_management_config = {
- .first_section = NULL,
- .last_section = NULL,
- .mutex = NETDATA_MUTEX_INITIALIZER,
- .index = {
- .avl_tree = {
- .root = NULL,
- .compar = appconfig_section_compare
- },
- .rwlock = AVL_LOCK_INITIALIZER
- }
- };
- static struct Chart_meta chart_types[] = {
- {.type = FLB_TAIL, .init = generic_chart_init, .update = generic_chart_update},
- {.type = FLB_WEB_LOG, .init = web_log_chart_init, .update = web_log_chart_update},
- {.type = FLB_KMSG, .init = kernel_chart_init, .update = kernel_chart_update},
- {.type = FLB_SYSTEMD, .init = systemd_chart_init, .update = systemd_chart_update},
- {.type = FLB_DOCKER_EV, .init = docker_ev_chart_init, .update = docker_ev_chart_update},
- {.type = FLB_SYSLOG, .init = generic_chart_init, .update = generic_chart_update},
- {.type = FLB_SERIAL, .init = generic_chart_init, .update = generic_chart_update},
- {.type = FLB_MQTT, .init = mqtt_chart_init, .update = mqtt_chart_update}
- };
- char *get_user_config_dir(void){
- char *dir = getenv("NETDATA_USER_CONFIG_DIR");
- return dir ? dir : CONFIG_DIR;
- }
- char *get_stock_config_dir(void){
- char *dir = getenv("NETDATA_STOCK_CONFIG_DIR");
- return dir ? dir : LIBCONFIG_DIR;
- }
- char *get_log_dir(void){
- char *dir = getenv("NETDATA_LOG_DIR");
- return dir ? dir : LOG_DIR;
- }
- char *get_cache_dir(void){
- char *dir = getenv("NETDATA_CACHE_DIR");
- return dir ? dir : CACHE_DIR;
- }
- /**
- * @brief Cleanup p_file_info struct
- * @param p_file_info The struct of File_info type to be cleaned up.
- * @todo Pass p_file_info by reference, so that it can be set to NULL. */
- static void p_file_info_destroy(void *arg){
- struct File_info *p_file_info = (struct File_info *) arg;
- // TODO: Clean up rrd / chart stuff.
- // p_file_info->chart_meta
- if(unlikely(!p_file_info)){
- collector_info("p_file_info_destroy() called but p_file_info == NULL - already destroyed?");
- return;
- }
- char chartname[100];
- snprintfz(chartname, 100, "%s", p_file_info->chartname ? p_file_info->chartname : "Unknown");
- collector_info("[%s]: p_file_info_destroy() cleanup...", chartname);
- __atomic_store_n(&p_file_info->state, LOG_SRC_EXITING, __ATOMIC_RELAXED);
- if(uv_is_active((uv_handle_t *) &p_file_info->flb_tmp_buff_cpy_timer)){
- uv_timer_stop(&p_file_info->flb_tmp_buff_cpy_timer);
- if (!uv_is_closing((uv_handle_t *) &p_file_info->flb_tmp_buff_cpy_timer))
- uv_close((uv_handle_t *) &p_file_info->flb_tmp_buff_cpy_timer, NULL);
- }
- // TODO: Need to do proper termination of DB threads and allocated memory.
- if(p_file_info->db_writer_thread){
- uv_thread_join(p_file_info->db_writer_thread);
- sqlite3_finalize(p_file_info->stmt_get_log_msg_metadata_asc);
- sqlite3_finalize(p_file_info->stmt_get_log_msg_metadata_desc);
- if(sqlite3_close(p_file_info->db) != SQLITE_OK)
- collector_error("[%s]: Failed to close database", chartname);
- freez(p_file_info->db_mut);
- freez((void *) p_file_info->db_metadata);
- freez((void *) p_file_info->db_dir);
- freez(p_file_info->db_writer_thread);
- }
- freez((void *) p_file_info->chartname);
- freez(p_file_info->filename);
- freez((void *) p_file_info->file_basename);
- freez((void *) p_file_info->stream_guid);
- for(int i = 1; i <= BLOB_MAX_FILES; i++){
- if(p_file_info->blob_handles[i]){
- uv_fs_close(NULL, NULL, p_file_info->blob_handles[i], NULL);
- p_file_info->blob_handles[i] = 0;
- }
- }
- if(p_file_info->circ_buff)
- circ_buff_destroy(p_file_info->circ_buff);
-
- if(p_file_info->parser_metrics){
- switch(p_file_info->log_type){
- case FLB_WEB_LOG: {
- if(p_file_info->parser_metrics->web_log)
- freez(p_file_info->parser_metrics->web_log);
- break;
- }
- case FLB_KMSG: {
- if(p_file_info->parser_metrics->kernel){
- dictionary_destroy(p_file_info->parser_metrics->kernel->subsystem);
- dictionary_destroy(p_file_info->parser_metrics->kernel->device);
- freez(p_file_info->parser_metrics->kernel);
- }
- break;
- }
- case FLB_SYSTEMD:
- case FLB_SYSLOG: {
- if(p_file_info->parser_metrics->systemd)
- freez(p_file_info->parser_metrics->systemd);
- break;
- }
- case FLB_DOCKER_EV: {
- if(p_file_info->parser_metrics->docker_ev)
- freez(p_file_info->parser_metrics->docker_ev);
- break;
- }
- case FLB_MQTT: {
- if(p_file_info->parser_metrics->mqtt){
- dictionary_destroy(p_file_info->parser_metrics->mqtt->topic);
- freez(p_file_info->parser_metrics->mqtt);
- }
- break;
- }
- default:
- break;
- }
- for(int i = 0; p_file_info->parser_cus_config &&
- p_file_info->parser_metrics->parser_cus &&
- p_file_info->parser_cus_config[i]; i++){
- freez(p_file_info->parser_cus_config[i]->chartname);
- freez(p_file_info->parser_cus_config[i]->regex_str);
- freez(p_file_info->parser_cus_config[i]->regex_name);
- regfree(&p_file_info->parser_cus_config[i]->regex);
- freez(p_file_info->parser_cus_config[i]);
- freez(p_file_info->parser_metrics->parser_cus[i]);
- }
- freez(p_file_info->parser_cus_config);
- freez(p_file_info->parser_metrics->parser_cus);
- freez(p_file_info->parser_metrics);
- }
- if(p_file_info->parser_config){
- freez(p_file_info->parser_config->gen_config);
- freez(p_file_info->parser_config);
- }
- Flb_output_config_t *output_next = p_file_info->flb_outputs;
- while(output_next){
- Flb_output_config_t *output = output_next;
- output_next = output_next->next;
- struct flb_output_config_param *param_next = output->param;
- while(param_next){
- struct flb_output_config_param *param = param_next;
- param_next = param->next;
- freez(param->key);
- freez(param->val);
- freez(param);
- }
- freez(output->plugin);
- freez(output);
- }
- freez(p_file_info->flb_config);
-
- freez(p_file_info);
- collector_info("[%s]: p_file_info_destroy() cleanup done", chartname);
- }
- void p_file_info_destroy_all(void){
- if(p_file_infos_arr){
- uv_thread_t thread_id[p_file_infos_arr->count];
- for(int i = 0; i < p_file_infos_arr->count; i++){
- fatal_assert(0 == uv_thread_create(&thread_id[i], p_file_info_destroy, p_file_infos_arr->data[i]));
- }
- for(int i = 0; i < p_file_infos_arr->count; i++){
- uv_thread_join(&thread_id[i]);
- }
- freez(p_file_infos_arr);
- p_file_infos_arr = NULL;
- }
- }
- /**
- * @brief Load logs management configuration.
- * @returns 0 if success,
- * -1 if config file not found
- * -2 if p_flb_srvc_config if is NULL (no flb_srvc_config_t provided)
- */
- int logs_manag_config_load( flb_srvc_config_t *p_flb_srvc_config,
- Flb_socket_config_t **forward_in_config_p,
- int g_update_every){
- int rc = LOGS_MANAG_CONFIG_LOAD_ERROR_OK;
- char section[100];
- char temp_path[FILENAME_MAX + 1];
- struct config logsmanagement_d_conf = {
- .first_section = NULL,
- .last_section = NULL,
- .mutex = NETDATA_MUTEX_INITIALIZER,
- .index = {
- .avl_tree = {
- .root = NULL,
- .compar = appconfig_section_compare
- },
- .rwlock = AVL_LOCK_INITIALIZER
- }
- };
- char *filename = strdupz_path_subpath(get_user_config_dir(), "logsmanagement.d.conf");
- if(!appconfig_load(&logsmanagement_d_conf, filename, 0, NULL)) {
- collector_info("CONFIG: cannot load user config '%s'. Will try stock config.", filename);
- freez(filename);
- filename = strdupz_path_subpath(get_stock_config_dir(), "logsmanagement.d.conf");
- if(!appconfig_load(&logsmanagement_d_conf, filename, 0, NULL)){
- collector_error("CONFIG: cannot load stock config '%s'. Logs management will be disabled.", filename);
- rc = LOGS_MANAG_CONFIG_LOAD_ERROR_NO_STOCK_CONFIG;
- }
- }
- freez(filename);
-
- /* [global] section */
- snprintfz(section, 100, "global");
- g_logs_manag_config.update_every = appconfig_get_number(
- &logsmanagement_d_conf,
- section,
- "update every",
- g_logs_manag_config.update_every);
-
- g_logs_manag_config.update_every =
- g_update_every && g_update_every > g_logs_manag_config.update_every ?
- g_update_every : g_logs_manag_config.update_every;
- g_logs_manag_config.update_timeout = appconfig_get_number(
- &logsmanagement_d_conf,
- section,
- "update timeout",
- UPDATE_TIMEOUT_DEFAULT);
- if(g_logs_manag_config.update_timeout < g_logs_manag_config.update_every)
- g_logs_manag_config.update_timeout = g_logs_manag_config.update_every;
- g_logs_manag_config.use_log_timestamp = appconfig_get_boolean_ondemand(
- &logsmanagement_d_conf,
- section,
- "use log timestamp",
- g_logs_manag_config.use_log_timestamp);
-
- g_logs_manag_config.circ_buff_max_size_in_mib = appconfig_get_number(
- &logsmanagement_d_conf,
- section,
- "circular buffer max size MiB",
- g_logs_manag_config.circ_buff_max_size_in_mib);
-
- g_logs_manag_config.circ_buff_drop_logs = appconfig_get_boolean(
- &logsmanagement_d_conf,
- section,
- "circular buffer drop logs if full",
- g_logs_manag_config.circ_buff_drop_logs);
- g_logs_manag_config.compression_acceleration = appconfig_get_number(
- &logsmanagement_d_conf,
- section,
- "compression acceleration",
- g_logs_manag_config.compression_acceleration);
- g_logs_manag_config.enable_collected_logs_total = appconfig_get_boolean(
- &logsmanagement_d_conf,
- section,
- "collected logs total chart enable",
- g_logs_manag_config.enable_collected_logs_total);
- g_logs_manag_config.enable_collected_logs_rate = appconfig_get_boolean(
- &logsmanagement_d_conf,
- section,
- "collected logs rate chart enable",
- g_logs_manag_config.enable_collected_logs_rate);
- g_logs_manag_config.do_sd_journal_send = appconfig_get_boolean(
- &logsmanagement_d_conf,
- section,
- "submit logs to system journal",
- g_logs_manag_config.do_sd_journal_send);
- g_logs_manag_config.sd_journal_field_prefix = appconfig_get(
- &logsmanagement_d_conf,
- section,
- "systemd journal fields prefix",
- g_logs_manag_config.sd_journal_field_prefix);
-
- if(!rc){
- collector_info("CONFIG: [%s] update every: %d", section, g_logs_manag_config.update_every);
- collector_info("CONFIG: [%s] update timeout: %d", section, g_logs_manag_config.update_timeout);
- collector_info("CONFIG: [%s] use log timestamp: %d", section, g_logs_manag_config.use_log_timestamp);
- collector_info("CONFIG: [%s] circular buffer max size MiB: %d", section, g_logs_manag_config.circ_buff_max_size_in_mib);
- collector_info("CONFIG: [%s] circular buffer drop logs if full: %d", section, g_logs_manag_config.circ_buff_drop_logs);
- collector_info("CONFIG: [%s] compression acceleration: %d", section, g_logs_manag_config.compression_acceleration);
- collector_info("CONFIG: [%s] collected logs total chart enable: %d", section, g_logs_manag_config.enable_collected_logs_total);
- collector_info("CONFIG: [%s] collected logs rate chart enable: %d", section, g_logs_manag_config.enable_collected_logs_rate);
- collector_info("CONFIG: [%s] submit logs to system journal: %d", section, g_logs_manag_config.do_sd_journal_send);
- collector_info("CONFIG: [%s] systemd journal fields prefix: %s", section, g_logs_manag_config.sd_journal_field_prefix);
- }
- /* [db] section */
- snprintfz(section, 100, "db");
- const char *const db_mode_str = appconfig_get(
- &logsmanagement_d_conf,
- section,
- "db mode",
- GLOBAL_DB_MODE_DEFAULT_STR);
- g_logs_manag_config.db_mode = db_mode_str_to_db_mode(db_mode_str);
- snprintfz(temp_path, FILENAME_MAX, "%s" LOGS_MANAG_DB_SUBPATH, get_cache_dir());
- db_set_main_dir(appconfig_get(&logsmanagement_d_conf, section, "db dir", temp_path));
- g_logs_manag_config.buff_flush_to_db_interval = appconfig_get_number(
- &logsmanagement_d_conf,
- section,
- "circular buffer flush to db",
- g_logs_manag_config.buff_flush_to_db_interval);
-
- g_logs_manag_config.disk_space_limit_in_mib = appconfig_get_number(
- &logsmanagement_d_conf,
- section,
- "disk space limit MiB",
- g_logs_manag_config.disk_space_limit_in_mib);
- if(!rc){
- collector_info("CONFIG: [%s] db mode: %s [%d]", section, db_mode_str, (int) g_logs_manag_config.db_mode);
- collector_info("CONFIG: [%s] db dir: %s", section, temp_path);
- collector_info("CONFIG: [%s] circular buffer flush to db: %d", section, g_logs_manag_config.buff_flush_to_db_interval);
- collector_info("CONFIG: [%s] disk space limit MiB: %d", section, g_logs_manag_config.disk_space_limit_in_mib);
- }
- /* [forward input] section */
- snprintfz(section, 100, "forward input");
- const int fwd_enable = appconfig_get_boolean(
- &logsmanagement_d_conf,
- section,
- "enabled",
- CONFIG_BOOLEAN_NO);
-
- *forward_in_config_p = (Flb_socket_config_t *) callocz(1, sizeof(Flb_socket_config_t));
- (*forward_in_config_p)->unix_path = appconfig_get(
- &logsmanagement_d_conf,
- section,
- "unix path",
- FLB_FORWARD_UNIX_PATH_DEFAULT);
-
- (*forward_in_config_p)->unix_perm = appconfig_get(
- &logsmanagement_d_conf,
- section,
- "unix perm",
- FLB_FORWARD_UNIX_PERM_DEFAULT);
-
- // TODO: Check if listen is in valid format
- (*forward_in_config_p)->listen = appconfig_get(
- &logsmanagement_d_conf,
- section,
- "listen",
- FLB_FORWARD_ADDR_DEFAULT);
-
- (*forward_in_config_p)->port = appconfig_get(
- &logsmanagement_d_conf,
- section,
- "port",
- FLB_FORWARD_PORT_DEFAULT);
- if(!rc){
- collector_info("CONFIG: [%s] enabled: %s", section, fwd_enable ? "yes" : "no");
- collector_info("CONFIG: [%s] unix path: %s", section, (*forward_in_config_p)->unix_path);
- collector_info("CONFIG: [%s] unix perm: %s", section, (*forward_in_config_p)->unix_perm);
- collector_info("CONFIG: [%s] listen: %s", section, (*forward_in_config_p)->listen);
- collector_info("CONFIG: [%s] port: %s", section, (*forward_in_config_p)->port);
- }
- if(!fwd_enable) {
- freez(*forward_in_config_p);
- *forward_in_config_p = NULL;
- }
- /* [fluent bit] section */
- snprintfz(section, 100, "fluent bit");
- snprintfz(temp_path, FILENAME_MAX, "%s/%s", get_log_dir(), FLB_LOG_FILENAME_DEFAULT);
-
- if(p_flb_srvc_config){
- p_flb_srvc_config->flush = appconfig_get(
- &logsmanagement_d_conf,
- section,
- "flush",
- p_flb_srvc_config->flush);
-
- p_flb_srvc_config->http_listen = appconfig_get(
- &logsmanagement_d_conf,
- section,
- "http listen",
- p_flb_srvc_config->http_listen);
- p_flb_srvc_config->http_port = appconfig_get(
- &logsmanagement_d_conf,
- section,
- "http port",
- p_flb_srvc_config->http_port);
-
- p_flb_srvc_config->http_server = appconfig_get(
- &logsmanagement_d_conf,
- section,
- "http server",
- p_flb_srvc_config->http_server);
-
- p_flb_srvc_config->log_path = appconfig_get(
- &logsmanagement_d_conf,
- section,
- "log file",
- temp_path);
-
- p_flb_srvc_config->log_level = appconfig_get(
- &logsmanagement_d_conf,
- section,
- "log level",
- p_flb_srvc_config->log_level);
-
- p_flb_srvc_config->coro_stack_size = appconfig_get(
- &logsmanagement_d_conf,
- section,
- "coro stack size",
- p_flb_srvc_config->coro_stack_size);
- }
- else
- rc = LOGS_MANAG_CONFIG_LOAD_ERROR_P_FLB_SRVC_NULL;
- if(!rc){
- collector_info("CONFIG: [%s] flush: %s", section, p_flb_srvc_config->flush);
- collector_info("CONFIG: [%s] http listen: %s", section, p_flb_srvc_config->http_listen);
- collector_info("CONFIG: [%s] http port: %s", section, p_flb_srvc_config->http_port);
- collector_info("CONFIG: [%s] http server: %s", section, p_flb_srvc_config->http_server);
- collector_info("CONFIG: [%s] log file: %s", section, p_flb_srvc_config->log_path);
- collector_info("CONFIG: [%s] log level: %s", section, p_flb_srvc_config->log_level);
- collector_info("CONFIG: [%s] coro stack size: %s", section, p_flb_srvc_config->coro_stack_size);
- }
- return rc;
- }
- static bool metrics_dict_conflict_cb(const DICTIONARY_ITEM *item __maybe_unused, void *old_value, void *new_value, void *data __maybe_unused){
- ((metrics_dict_item_t *)old_value)->num_new += ((metrics_dict_item_t *)new_value)->num_new;
- return true;
- }
- #define FLB_OUTPUT_PLUGIN_NAME_KEY "name"
- static int flb_output_param_get_cb(void *entry, void *data){
- struct config_option *option = (struct config_option *) entry;
- Flb_output_config_t *flb_output = (Flb_output_config_t *) data;
-
- char *param_prefix = callocz(1, snprintf(NULL, 0, "output %d", MAX_OUTPUTS_PER_SOURCE) + 1);
- sprintf(param_prefix, "output %d", flb_output->id);
- size_t param_prefix_len = strlen(param_prefix);
-
- if(!strncasecmp(option->name, param_prefix, param_prefix_len)){ // param->name looks like "output 1 host"
- char *param_key = &option->name[param_prefix_len]; // param_key should look like " host"
- while(*param_key == ' ') param_key++; // remove whitespace so it looks like "host"
-
- if(*param_key && strcasecmp(param_key, FLB_OUTPUT_PLUGIN_NAME_KEY)){ // ignore param_key "name"
- // debug_log( "config_option: name[%s], value[%s]", option->name, option->value);
- // debug_log( "config option kv:[%s][%s]", param_key, option->value);
- struct flb_output_config_param **p = &flb_output->param;
- while((*p) != NULL) p = &((*p)->next); // Go to last param of linked list
- (*p) = callocz(1, sizeof(struct flb_output_config_param));
- (*p)->key = strdupz(param_key);
- (*p)->val = strdupz(option->value);
- }
- }
- freez(param_prefix);
- return 0;
- }
- /**
- * @brief Initialize logs management based on a section configuration.
- * @note On error, calls p_file_info_destroy() to clean up before returning.
- * @param config_section Section to read configuration from.
- * @todo How to handle duplicate entries?
- */
- static void config_section_init(uv_loop_t *main_loop,
- struct section *config_section,
- Flb_socket_config_t *forward_in_config,
- flb_srvc_config_t *p_flb_srvc_config,
- netdata_mutex_t *stdout_mut){
- struct File_info *p_file_info = callocz(1, sizeof(struct File_info));
- /* -------------------------------------------------------------------------
- * Check if config_section->name is valid and if so, use it as chartname.
- * ------------------------------------------------------------------------- */
- if(config_section->name && *config_section->name){
- char tmp[LOGS_MANAG_CHARTNAME_SIZE] = {0};
- snprintfz(tmp, sizeof(tmp), "%s%s", LOGS_MANAG_CHARTNAME_PREFIX, config_section->name);
- netdata_fix_chart_id(tmp);
- for(char *ch = (char *) tmp; *ch; ch++)
- *ch = *ch == '.' ? '_' : *ch; // Convert dots to underscores
- p_file_info->chartname = strdupz(tmp);
- collector_info("[%s]: Initializing config loading", p_file_info->chartname);
- } else {
- collector_error("Invalid logs management config section.");
- return p_file_info_destroy(p_file_info);
- }
-
- /* -------------------------------------------------------------------------
- * Check if this log source is enabled.
- * ------------------------------------------------------------------------- */
- if(appconfig_get_boolean(&log_management_config, config_section->name, "enabled", CONFIG_BOOLEAN_NO)){
- collector_info("[%s]: enabled = yes", p_file_info->chartname);
- } else {
- collector_info("[%s]: enabled = no", p_file_info->chartname);
- return p_file_info_destroy(p_file_info);
- }
- /* -------------------------------------------------------------------------
- * Check log type.
- * ------------------------------------------------------------------------- */
- char *type = appconfig_get(&log_management_config, config_section->name, "log type", "flb_tail");
- if(!type || !*type) p_file_info->log_type = FLB_TAIL; // Default
- else{
- if(!strcasecmp(type, "flb_tail")) p_file_info->log_type = FLB_TAIL;
- else if (!strcasecmp(type, "flb_web_log")) p_file_info->log_type = FLB_WEB_LOG;
- else if (!strcasecmp(type, "flb_kmsg")) p_file_info->log_type = FLB_KMSG;
- else if (!strcasecmp(type, "flb_systemd")) p_file_info->log_type = FLB_SYSTEMD;
- else if (!strcasecmp(type, "flb_docker_events")) p_file_info->log_type = FLB_DOCKER_EV;
- else if (!strcasecmp(type, "flb_syslog")) p_file_info->log_type = FLB_SYSLOG;
- else if (!strcasecmp(type, "flb_serial")) p_file_info->log_type = FLB_SERIAL;
- else if (!strcasecmp(type, "flb_mqtt")) p_file_info->log_type = FLB_MQTT;
- else p_file_info->log_type = FLB_TAIL;
- }
- freez(type);
- collector_info("[%s]: log type = %s", p_file_info->chartname, log_src_type_t_str[p_file_info->log_type]);
- /* -------------------------------------------------------------------------
- * Read log source.
- * ------------------------------------------------------------------------- */
- char *source = appconfig_get(&log_management_config, config_section->name, "log source", "local");
- if(!source || !*source) p_file_info->log_source = LOG_SOURCE_LOCAL; // Default
- else if(!strcasecmp(source, "forward")) p_file_info->log_source = LOG_SOURCE_FORWARD;
- else p_file_info->log_source = LOG_SOURCE_LOCAL;
- freez(source);
- collector_info("[%s]: log source = %s", p_file_info->chartname, log_src_t_str[p_file_info->log_source]);
- if(p_file_info->log_source == LOG_SOURCE_FORWARD && !forward_in_config){
- collector_info("[%s]: forward_in_config == NULL - this log source will be disabled", p_file_info->chartname);
- return p_file_info_destroy(p_file_info);
- }
- /* -------------------------------------------------------------------------
- * Read stream uuid.
- * ------------------------------------------------------------------------- */
- p_file_info->stream_guid = appconfig_get(&log_management_config, config_section->name, "stream guid", "");
- collector_info("[%s]: stream guid = %s", p_file_info->chartname, p_file_info->stream_guid);
- /* -------------------------------------------------------------------------
- * Read log path configuration and check if it is valid.
- * ------------------------------------------------------------------------- */
- p_file_info->filename = appconfig_get(&log_management_config, config_section->name, "log path", LOG_PATH_AUTO);
- if( /* path doesn't matter when log source is not local */
- (p_file_info->log_source == LOG_SOURCE_LOCAL) &&
-
- /* FLB_SYSLOG is special case, may or may not require a path */
- (p_file_info->log_type != FLB_SYSLOG) &&
- /* FLB_MQTT is special case, does not require a path */
- (p_file_info->log_type != FLB_MQTT) &&
-
- (!p_file_info->filename /* Sanity check */ ||
- !*p_file_info->filename ||
- !strcmp(p_file_info->filename, LOG_PATH_AUTO) ||
- access(p_file_info->filename, R_OK)
- )){
- freez(p_file_info->filename);
- p_file_info->filename = NULL;
-
- switch(p_file_info->log_type){
- case FLB_TAIL:
- if(!strcasecmp(p_file_info->chartname, LOGS_MANAG_CHARTNAME_PREFIX "netdata_daemon_log")){
- char path[FILENAME_MAX + 1];
- snprintfz(path, FILENAME_MAX, "%s/daemon.log", get_log_dir());
- if(access(path, R_OK)) {
- collector_error("[%s]: 'Netdata daemon.log' path (%s) invalid, unknown or needs permissions",
- p_file_info->chartname, path);
- return p_file_info_destroy(p_file_info);
- } else p_file_info->filename = strdupz(path);
- } else if(!strcasecmp(p_file_info->chartname, LOGS_MANAG_CHARTNAME_PREFIX "fluentbit_log")){
- if(access(p_flb_srvc_config->log_path, R_OK)){
- collector_error("[%s]: Netdata fluentbit.log path (%s) invalid, unknown or needs permissions",
- p_file_info->chartname, p_flb_srvc_config->log_path);
- return p_file_info_destroy(p_file_info);
- } else p_file_info->filename = strdupz(p_flb_srvc_config->log_path);
- } else if(!strcasecmp(p_file_info->chartname, LOGS_MANAG_CHARTNAME_PREFIX "auth_log_tail")){
- const char * const auth_path_default[] = {
- "/var/log/auth.log",
- NULL
- };
- int i = 0;
- while(auth_path_default[i] && access(auth_path_default[i], R_OK)){i++;};
- if(!auth_path_default[i]){
- collector_error("[%s]: auth.log path invalid, unknown or needs permissions", p_file_info->chartname);
- return p_file_info_destroy(p_file_info);
- } else p_file_info->filename = strdupz(auth_path_default[i]);
- } else if(!strcasecmp(p_file_info->chartname, "syslog_tail")){
- const char * const syslog_path_default[] = {
- "/var/log/syslog", /* Debian, Ubuntu */
- "/var/log/messages", /* RHEL, Red Hat, CentOS, Fedora */
- NULL
- };
- int i = 0;
- while(syslog_path_default[i] && access(syslog_path_default[i], R_OK)){i++;};
- if(!syslog_path_default[i]){
- collector_error("[%s]: syslog path invalid, unknown or needs permissions", p_file_info->chartname);
- return p_file_info_destroy(p_file_info);
- } else p_file_info->filename = strdupz(syslog_path_default[i]);
- }
- break;
- case FLB_WEB_LOG:
- if(!strcasecmp(p_file_info->chartname, LOGS_MANAG_CHARTNAME_PREFIX "apache_access_log")){
- const char * const apache_access_path_default[] = {
- "/var/log/apache/access.log",
- "/var/log/apache2/access.log",
- "/var/log/apache2/access_log",
- "/var/log/httpd/access_log",
- "/var/log/httpd-access.log",
- NULL
- };
- int i = 0;
- while(apache_access_path_default[i] && access(apache_access_path_default[i], R_OK)){i++;};
- if(!apache_access_path_default[i]){
- collector_error("[%s]: Apache access.log path invalid, unknown or needs permissions", p_file_info->chartname);
- return p_file_info_destroy(p_file_info);
- } else p_file_info->filename = strdupz(apache_access_path_default[i]);
- } else if(!strcasecmp(p_file_info->chartname, LOGS_MANAG_CHARTNAME_PREFIX "nginx_access_log")){
- const char * const nginx_access_path_default[] = {
- "/var/log/nginx/access.log",
- NULL
- };
- int i = 0;
- while(nginx_access_path_default[i] && access(nginx_access_path_default[i], R_OK)){i++;};
- if(!nginx_access_path_default[i]){
- collector_error("[%s]: Nginx access.log path invalid, unknown or needs permissions", p_file_info->chartname);
- return p_file_info_destroy(p_file_info);
- } else p_file_info->filename = strdupz(nginx_access_path_default[i]);
- }
- break;
- case FLB_KMSG:
- if(access(KMSG_DEFAULT_PATH, R_OK)){
- collector_error("[%s]: kmsg default path invalid, unknown or needs permissions", p_file_info->chartname);
- return p_file_info_destroy(p_file_info);
- } else p_file_info->filename = strdupz(KMSG_DEFAULT_PATH);
- break;
- case FLB_SYSTEMD:
- p_file_info->filename = strdupz(SYSTEMD_DEFAULT_PATH);
- break;
- case FLB_DOCKER_EV:
- if(access(DOCKER_EV_DEFAULT_PATH, R_OK)){
- collector_error("[%s]: Docker socket default Unix path invalid, unknown or needs permissions", p_file_info->chartname);
- return p_file_info_destroy(p_file_info);
- } else p_file_info->filename = strdupz(DOCKER_EV_DEFAULT_PATH);
- break;
- default:
- collector_error("[%s]: log path invalid or unknown", p_file_info->chartname);
- return p_file_info_destroy(p_file_info);
- }
- }
- p_file_info->file_basename = get_basename(p_file_info->filename);
- collector_info("[%s]: p_file_info->filename: %s", p_file_info->chartname,
- p_file_info->filename ? p_file_info->filename : "NULL");
- collector_info("[%s]: p_file_info->file_basename: %s", p_file_info->chartname,
- p_file_info->file_basename ? p_file_info->file_basename : "NULL");
- if(unlikely(!p_file_info->filename)) return p_file_info_destroy(p_file_info);
- /* -------------------------------------------------------------------------
- * Read "update every" and "update timeout" configuration.
- * ------------------------------------------------------------------------- */
- p_file_info->update_every = appconfig_get_number( &log_management_config, config_section->name,
- "update every", g_logs_manag_config.update_every);
- collector_info("[%s]: update every = %d", p_file_info->chartname, p_file_info->update_every);
- p_file_info->update_timeout = appconfig_get_number( &log_management_config, config_section->name,
- "update timeout", g_logs_manag_config.update_timeout);
- if(p_file_info->update_timeout < p_file_info->update_every) p_file_info->update_timeout = p_file_info->update_every;
- collector_info("[%s]: update timeout = %d", p_file_info->chartname, p_file_info->update_timeout);
- /* -------------------------------------------------------------------------
- * Read "use log timestamp" configuration.
- * ------------------------------------------------------------------------- */
- p_file_info->use_log_timestamp = appconfig_get_boolean_ondemand(&log_management_config, config_section->name,
- "use log timestamp",
- g_logs_manag_config.use_log_timestamp);
- collector_info("[%s]: use log timestamp = %s", p_file_info->chartname,
- p_file_info->use_log_timestamp ? "auto or yes" : "no");
- /* -------------------------------------------------------------------------
- * Read compression acceleration configuration.
- * ------------------------------------------------------------------------- */
- p_file_info->compression_accel = appconfig_get_number( &log_management_config, config_section->name,
- "compression acceleration",
- g_logs_manag_config.compression_acceleration);
- collector_info("[%s]: compression acceleration = %d", p_file_info->chartname, p_file_info->compression_accel);
- /* -------------------------------------------------------------------------
- * Read DB mode.
- * ------------------------------------------------------------------------- */
- const char *const db_mode_str = appconfig_get(&log_management_config, config_section->name, "db mode", NULL);
- collector_info("[%s]: db mode = %s", p_file_info->chartname, db_mode_str ? db_mode_str : "NULL");
- p_file_info->db_mode = db_mode_str_to_db_mode(db_mode_str);
- freez((void *)db_mode_str);
- /* -------------------------------------------------------------------------
- * Read save logs from buffers to DB interval configuration.
- * ------------------------------------------------------------------------- */
- p_file_info->buff_flush_to_db_interval = appconfig_get_number( &log_management_config, config_section->name,
- "circular buffer flush to db",
- g_logs_manag_config.buff_flush_to_db_interval);
- if(p_file_info->buff_flush_to_db_interval > SAVE_BLOB_TO_DB_MAX) {
- p_file_info->buff_flush_to_db_interval = SAVE_BLOB_TO_DB_MAX;
- collector_info("[%s]: circular buffer flush to db out of range. Using maximum permitted value: %d",
- p_file_info->chartname, p_file_info->buff_flush_to_db_interval);
- } else if(p_file_info->buff_flush_to_db_interval < SAVE_BLOB_TO_DB_MIN) {
- p_file_info->buff_flush_to_db_interval = SAVE_BLOB_TO_DB_MIN;
- collector_info("[%s]: circular buffer flush to db out of range. Using minimum permitted value: %d",
- p_file_info->chartname, p_file_info->buff_flush_to_db_interval);
- }
- collector_info("[%s]: circular buffer flush to db = %d", p_file_info->chartname, p_file_info->buff_flush_to_db_interval);
- /* -------------------------------------------------------------------------
- * Read BLOB max size configuration.
- * ------------------------------------------------------------------------- */
- p_file_info->blob_max_size = appconfig_get_number( &log_management_config, config_section->name,
- "disk space limit MiB",
- g_logs_manag_config.disk_space_limit_in_mib) MiB / BLOB_MAX_FILES;
- collector_info("[%s]: BLOB max size = %lld", p_file_info->chartname, (long long)p_file_info->blob_max_size);
- /* -------------------------------------------------------------------------
- * Read configuration about sending logs to system journal.
- * ------------------------------------------------------------------------- */
- p_file_info->do_sd_journal_send = appconfig_get_boolean(&log_management_config, config_section->name,
- "submit logs to system journal",
- g_logs_manag_config.do_sd_journal_send);
- /* -------------------------------------------------------------------------
- * Read collected logs chart configuration.
- * ------------------------------------------------------------------------- */
- p_file_info->parser_config = callocz(1, sizeof(Log_parser_config_t));
- if(appconfig_get_boolean(&log_management_config, config_section->name,
- "collected logs total chart enable",
- g_logs_manag_config.enable_collected_logs_total)){
- p_file_info->parser_config->chart_config |= CHART_COLLECTED_LOGS_TOTAL;
- }
- collector_info( "[%s]: collected logs total chart enable = %s", p_file_info->chartname,
- (p_file_info->parser_config->chart_config & CHART_COLLECTED_LOGS_TOTAL) ? "yes" : "no");
- if(appconfig_get_boolean(&log_management_config, config_section->name,
- "collected logs rate chart enable",
- g_logs_manag_config.enable_collected_logs_rate)){
- p_file_info->parser_config->chart_config |= CHART_COLLECTED_LOGS_RATE;
- }
- collector_info( "[%s]: collected logs rate chart enable = %s", p_file_info->chartname,
- (p_file_info->parser_config->chart_config & CHART_COLLECTED_LOGS_RATE) ? "yes" : "no");
- /* -------------------------------------------------------------------------
- * Deal with log-type-specific configuration options.
- * ------------------------------------------------------------------------- */
-
- if(p_file_info->log_type == FLB_TAIL || p_file_info->log_type == FLB_WEB_LOG){
- Flb_tail_config_t *tail_config = callocz(1, sizeof(Flb_tail_config_t));
- if(appconfig_get_boolean(&log_management_config, config_section->name, "use inotify", CONFIG_BOOLEAN_YES))
- tail_config->use_inotify = 1;
- collector_info( "[%s]: use inotify = %s", p_file_info->chartname, tail_config->use_inotify? "yes" : "no");
- p_file_info->flb_config = tail_config;
- }
-
- if(p_file_info->log_type == FLB_WEB_LOG){
- /* Check if a valid web log format configuration is detected */
- char *log_format = appconfig_get(&log_management_config, config_section->name, "log format", LOG_PATH_AUTO);
- const char delimiter = ' '; // TODO!!: TO READ FROM CONFIG
- collector_info("[%s]: log format = %s", p_file_info->chartname, log_format ? log_format : "NULL!");
- /* If "log format = auto" or no "log format" config is detected,
- * try log format autodetection based on last log file line.
- * TODO 1: Add another case in OR where log_format is compared with a valid reg exp.
- * TODO 2: Set default log format and delimiter if not found in config? Or auto-detect? */
- if(!log_format || !*log_format || !strcmp(log_format, LOG_PATH_AUTO)){
- collector_info("[%s]: Attempting auto-detection of log format", p_file_info->chartname);
- char *line = read_last_line(p_file_info->filename, 0);
- if(!line){
- collector_error("[%s]: read_last_line() returned NULL", p_file_info->chartname);
- return p_file_info_destroy(p_file_info);
- }
- p_file_info->parser_config->gen_config = auto_detect_web_log_parser_config(line, delimiter);
- freez(line);
- }
- else{
- p_file_info->parser_config->gen_config = read_web_log_parser_config(log_format, delimiter);
- collector_info( "[%s]: Read web log parser config: %s", p_file_info->chartname,
- p_file_info->parser_config->gen_config ? "success!" : "failed!");
- }
- freez(log_format);
- if(!p_file_info->parser_config->gen_config){
- collector_error("[%s]: No valid web log parser config found", p_file_info->chartname);
- return p_file_info_destroy(p_file_info);
- }
- /* Check whether metrics verification during parsing is required */
- Web_log_parser_config_t *wblp_config = (Web_log_parser_config_t *) p_file_info->parser_config->gen_config;
- wblp_config->verify_parsed_logs = appconfig_get_boolean( &log_management_config, config_section->name,
- "verify parsed logs", CONFIG_BOOLEAN_NO);
- collector_info("[%s]: verify parsed logs = %d", p_file_info->chartname, wblp_config->verify_parsed_logs);
- wblp_config->skip_timestamp_parsing = p_file_info->use_log_timestamp ? 0 : 1;
- collector_info("[%s]: skip_timestamp_parsing = %d", p_file_info->chartname, wblp_config->skip_timestamp_parsing);
-
- for(int j = 0; j < wblp_config->num_fields; j++){
- if((wblp_config->fields[j] == VHOST_WITH_PORT || wblp_config->fields[j] == VHOST)
- && appconfig_get_boolean(&log_management_config, config_section->name, "vhosts chart", CONFIG_BOOLEAN_NO)){
- p_file_info->parser_config->chart_config |= CHART_VHOST;
- }
- if((wblp_config->fields[j] == VHOST_WITH_PORT || wblp_config->fields[j] == PORT)
- && appconfig_get_boolean(&log_management_config, config_section->name, "ports chart", CONFIG_BOOLEAN_NO)){
- p_file_info->parser_config->chart_config |= CHART_PORT;
- }
- if((wblp_config->fields[j] == REQ_CLIENT)
- && appconfig_get_boolean(&log_management_config, config_section->name, "IP versions chart", CONFIG_BOOLEAN_NO)){
- p_file_info->parser_config->chart_config |= CHART_IP_VERSION;
- }
- if((wblp_config->fields[j] == REQ_CLIENT)
- && appconfig_get_boolean(&log_management_config, config_section->name, "unique client IPs - current poll chart", CONFIG_BOOLEAN_NO)){
- p_file_info->parser_config->chart_config |= CHART_REQ_CLIENT_CURRENT;
- }
- if((wblp_config->fields[j] == REQ_CLIENT)
- && appconfig_get_boolean(&log_management_config, config_section->name, "unique client IPs - all-time chart", CONFIG_BOOLEAN_NO)){
- p_file_info->parser_config->chart_config |= CHART_REQ_CLIENT_ALL_TIME;
- }
- if((wblp_config->fields[j] == REQ || wblp_config->fields[j] == REQ_METHOD)
- && appconfig_get_boolean(&log_management_config, config_section->name, "http request methods chart", CONFIG_BOOLEAN_NO)){
- p_file_info->parser_config->chart_config |= CHART_REQ_METHODS;
- }
- if((wblp_config->fields[j] == REQ || wblp_config->fields[j] == REQ_PROTO)
- && appconfig_get_boolean(&log_management_config, config_section->name, "http protocol versions chart", CONFIG_BOOLEAN_NO)){
- p_file_info->parser_config->chart_config |= CHART_REQ_PROTO;
- }
- if((wblp_config->fields[j] == REQ_SIZE || wblp_config->fields[j] == RESP_SIZE)
- && appconfig_get_boolean(&log_management_config, config_section->name, "bandwidth chart", CONFIG_BOOLEAN_NO)){
- p_file_info->parser_config->chart_config |= CHART_BANDWIDTH;
- }
- if((wblp_config->fields[j] == REQ_PROC_TIME)
- && appconfig_get_boolean(&log_management_config, config_section->name, "timings chart", CONFIG_BOOLEAN_NO)){
- p_file_info->parser_config->chart_config |= CHART_REQ_PROC_TIME;
- }
- if((wblp_config->fields[j] == RESP_CODE)
- && appconfig_get_boolean(&log_management_config, config_section->name, "response code families chart", CONFIG_BOOLEAN_NO)){
- p_file_info->parser_config->chart_config |= CHART_RESP_CODE_FAMILY;
- }
- if((wblp_config->fields[j] == RESP_CODE)
- && appconfig_get_boolean(&log_management_config, config_section->name, "response codes chart", CONFIG_BOOLEAN_NO)){
- p_file_info->parser_config->chart_config |= CHART_RESP_CODE;
- }
- if((wblp_config->fields[j] == RESP_CODE)
- && appconfig_get_boolean(&log_management_config, config_section->name, "response code types chart", CONFIG_BOOLEAN_NO)){
- p_file_info->parser_config->chart_config |= CHART_RESP_CODE_TYPE;
- }
- if((wblp_config->fields[j] == SSL_PROTO)
- && appconfig_get_boolean(&log_management_config, config_section->name, "SSL protocols chart", CONFIG_BOOLEAN_NO)){
- p_file_info->parser_config->chart_config |= CHART_SSL_PROTO;
- }
- if((wblp_config->fields[j] == SSL_CIPHER_SUITE)
- && appconfig_get_boolean(&log_management_config, config_section->name, "SSL chipher suites chart", CONFIG_BOOLEAN_NO)){
- p_file_info->parser_config->chart_config |= CHART_SSL_CIPHER;
- }
- }
- }
- else if(p_file_info->log_type == FLB_KMSG){
- Flb_kmsg_config_t *kmsg_config = callocz(1, sizeof(Flb_kmsg_config_t));
- kmsg_config->prio_level = appconfig_get(&log_management_config, config_section->name, "prio level", "8");
- p_file_info->flb_config = kmsg_config;
- if(appconfig_get_boolean(&log_management_config, config_section->name, "severity chart", CONFIG_BOOLEAN_NO)) {
- p_file_info->parser_config->chart_config |= CHART_SYSLOG_SEVER;
- }
- if(appconfig_get_boolean(&log_management_config, config_section->name, "subsystem chart", CONFIG_BOOLEAN_NO)) {
- p_file_info->parser_config->chart_config |= CHART_KMSG_SUBSYSTEM;
- }
- if(appconfig_get_boolean(&log_management_config, config_section->name, "device chart", CONFIG_BOOLEAN_NO)) {
- p_file_info->parser_config->chart_config |= CHART_KMSG_DEVICE;
- }
- }
- else if(p_file_info->log_type == FLB_SYSTEMD || p_file_info->log_type == FLB_SYSLOG){
- if(p_file_info->log_type == FLB_SYSLOG){
- Syslog_parser_config_t *syslog_config = callocz(1, sizeof(Syslog_parser_config_t));
- /* Read syslog format */
- syslog_config->log_format = appconfig_get( &log_management_config,
- config_section->name,
- "log format", NULL);
- collector_info("[%s]: log format = %s", p_file_info->chartname,
- syslog_config->log_format ? syslog_config->log_format : "NULL!");
- if(!syslog_config->log_format || !*syslog_config->log_format || !strcasecmp(syslog_config->log_format, "auto")){
- freez(syslog_config->log_format);
- freez(syslog_config);
- return p_file_info_destroy(p_file_info);
- }
- syslog_config->socket_config = callocz(1, sizeof(Flb_socket_config_t));
- /* Read syslog socket mode
- * see also https://docs.fluentbit.io/manual/pipeline/inputs/syslog#configuration-parameters */
- syslog_config->socket_config->mode = appconfig_get( &log_management_config,
- config_section->name,
- "mode", "unix_udp");
- collector_info("[%s]: mode = %s", p_file_info->chartname, syslog_config->socket_config->mode);
- /* Check for valid socket path if (mode == unix_udp) or
- * (mode == unix_tcp), else read syslog network interface to bind,
- * if (mode == udp) or (mode == tcp). */
- if( !strcasecmp(syslog_config->socket_config->mode, "unix_udp") ||
- !strcasecmp(syslog_config->socket_config->mode, "unix_tcp")){
- if(!p_file_info->filename || !*p_file_info->filename || !strcasecmp(p_file_info->filename, LOG_PATH_AUTO)){
- // freez(syslog_config->socket_config->mode);
- freez(syslog_config->socket_config);
- freez(syslog_config->log_format);
- freez(syslog_config);
- return p_file_info_destroy(p_file_info);
- }
- syslog_config->socket_config->unix_perm = appconfig_get(&log_management_config,
- config_section->name,
- "unix_perm", "0644");
- collector_info("[%s]: unix_perm = %s", p_file_info->chartname, syslog_config->socket_config->unix_perm);
- } else if( !strcasecmp(syslog_config->socket_config->mode, "udp") ||
- !strcasecmp(syslog_config->socket_config->mode, "tcp")){
- // TODO: Check if listen is in valid format
- syslog_config->socket_config->listen = appconfig_get( &log_management_config,
- config_section->name,
- "listen", "0.0.0.0");
- collector_info("[%s]: listen = %s", p_file_info->chartname, syslog_config->socket_config->listen);
- syslog_config->socket_config->port = appconfig_get( &log_management_config,
- config_section->name,
- "port", "5140");
- collector_info("[%s]: port = %s", p_file_info->chartname, syslog_config->socket_config->port);
- } else {
- /* Any other modes are invalid */
- // freez(syslog_config->socket_config->mode);
- freez(syslog_config->socket_config);
- freez(syslog_config->log_format);
- freez(syslog_config);
- return p_file_info_destroy(p_file_info);
- }
- p_file_info->parser_config->gen_config = syslog_config;
- }
- if(appconfig_get_boolean(&log_management_config, config_section->name, "priority value chart", CONFIG_BOOLEAN_NO)) {
- p_file_info->parser_config->chart_config |= CHART_SYSLOG_PRIOR;
- }
- if(appconfig_get_boolean(&log_management_config, config_section->name, "severity chart", CONFIG_BOOLEAN_NO)) {
- p_file_info->parser_config->chart_config |= CHART_SYSLOG_SEVER;
- }
- if(appconfig_get_boolean(&log_management_config, config_section->name, "facility chart", CONFIG_BOOLEAN_NO)) {
- p_file_info->parser_config->chart_config |= CHART_SYSLOG_FACIL;
- }
- }
- else if(p_file_info->log_type == FLB_DOCKER_EV){
- if(appconfig_get_boolean(&log_management_config, config_section->name, "event type chart", CONFIG_BOOLEAN_NO)) {
- p_file_info->parser_config->chart_config |= CHART_DOCKER_EV_TYPE;
- }
- if(appconfig_get_boolean(&log_management_config, config_section->name, "event action chart", CONFIG_BOOLEAN_NO)) {
- p_file_info->parser_config->chart_config |= CHART_DOCKER_EV_ACTION;
- }
- }
- else if(p_file_info->log_type == FLB_SERIAL){
- Flb_serial_config_t *serial_config = callocz(1, sizeof(Flb_serial_config_t));
- serial_config->bitrate = appconfig_get(&log_management_config, config_section->name, "bitrate", "115200");
- serial_config->min_bytes = appconfig_get(&log_management_config, config_section->name, "min bytes", "1");
- serial_config->separator = appconfig_get(&log_management_config, config_section->name, "separator", "");
- serial_config->format = appconfig_get(&log_management_config, config_section->name, "format", "");
- p_file_info->flb_config = serial_config;
- }
- else if(p_file_info->log_type == FLB_MQTT){
- Flb_socket_config_t *socket_config = callocz(1, sizeof(Flb_socket_config_t));
- socket_config->listen = appconfig_get(&log_management_config, config_section->name, "listen", "0.0.0.0");
- socket_config->port = appconfig_get(&log_management_config, config_section->name, "port", "1883");
- p_file_info->flb_config = socket_config;
- if(appconfig_get_boolean(&log_management_config, config_section->name, "topic chart", CONFIG_BOOLEAN_NO)) {
- p_file_info->parser_config->chart_config |= CHART_MQTT_TOPIC;
- }
- }
- /* -------------------------------------------------------------------------
- * Allocate p_file_info->parser_metrics memory.
- * ------------------------------------------------------------------------- */
- p_file_info->parser_metrics = callocz(1, sizeof(Log_parser_metrics_t));
- switch(p_file_info->log_type){
- case FLB_WEB_LOG:{
- p_file_info->parser_metrics->web_log = callocz(1, sizeof(Web_log_metrics_t));
- break;
- }
- case FLB_KMSG: {
- p_file_info->parser_metrics->kernel = callocz(1, sizeof(Kernel_metrics_t));
- p_file_info->parser_metrics->kernel->subsystem = dictionary_create( DICT_OPTION_SINGLE_THREADED |
- DICT_OPTION_NAME_LINK_DONT_CLONE |
- DICT_OPTION_DONT_OVERWRITE_VALUE);
- dictionary_register_conflict_callback(p_file_info->parser_metrics->kernel->subsystem, metrics_dict_conflict_cb, NULL);
- p_file_info->parser_metrics->kernel->device = dictionary_create(DICT_OPTION_SINGLE_THREADED |
- DICT_OPTION_NAME_LINK_DONT_CLONE |
- DICT_OPTION_DONT_OVERWRITE_VALUE);
- dictionary_register_conflict_callback(p_file_info->parser_metrics->kernel->device, metrics_dict_conflict_cb, NULL);
- break;
- }
- case FLB_SYSTEMD:
- case FLB_SYSLOG: {
- p_file_info->parser_metrics->systemd = callocz(1, sizeof(Systemd_metrics_t));
- break;
- }
- case FLB_DOCKER_EV: {
- p_file_info->parser_metrics->docker_ev = callocz(1, sizeof(Docker_ev_metrics_t));
- break;
- }
- case FLB_MQTT: {
- p_file_info->parser_metrics->mqtt = callocz(1, sizeof(Mqtt_metrics_t));
- p_file_info->parser_metrics->mqtt->topic = dictionary_create( DICT_OPTION_SINGLE_THREADED |
- DICT_OPTION_NAME_LINK_DONT_CLONE |
- DICT_OPTION_DONT_OVERWRITE_VALUE);
- dictionary_register_conflict_callback(p_file_info->parser_metrics->mqtt->topic, metrics_dict_conflict_cb, NULL);
- break;
- }
- default:
- break;
- }
- /* -------------------------------------------------------------------------
- * Configure (optional) custom charts.
- * ------------------------------------------------------------------------- */
- p_file_info->parser_cus_config = callocz(1, sizeof(Log_parser_cus_config_t *));
- p_file_info->parser_metrics->parser_cus = callocz(1, sizeof(Log_parser_cus_metrics_t *));
- for(int cus_off = 1; cus_off <= MAX_CUS_CHARTS_PER_SOURCE; cus_off++){
- /* Read chart name config */
- char *cus_chart_k = mallocz(snprintf(NULL, 0, "custom %d chart", MAX_CUS_CHARTS_PER_SOURCE) + 1);
- sprintf(cus_chart_k, "custom %d chart", cus_off);
- char *cus_chart_v = appconfig_get(&log_management_config, config_section->name, cus_chart_k, NULL);
- debug_log( "cus chart: (%s:%s)", cus_chart_k, cus_chart_v ? cus_chart_v : "NULL");
- freez(cus_chart_k);
- if(unlikely(!cus_chart_v)){
- collector_error("[%s]: custom %d chart = NULL, custom charts for this log source will be disabled.",
- p_file_info->chartname, cus_off);
- break;
- }
- netdata_fix_chart_id(cus_chart_v);
- /* Read regex config */
- char *cus_regex_k = mallocz(snprintf(NULL, 0, "custom %d regex", MAX_CUS_CHARTS_PER_SOURCE) + 1);
- sprintf(cus_regex_k, "custom %d regex", cus_off);
- char *cus_regex_v = appconfig_get(&log_management_config, config_section->name, cus_regex_k, NULL);
- debug_log( "cus regex: (%s:%s)", cus_regex_k, cus_regex_v ? cus_regex_v : "NULL");
- freez(cus_regex_k);
- if(unlikely(!cus_regex_v)) {
- collector_error("[%s]: custom %d regex = NULL, custom charts for this log source will be disabled.",
- p_file_info->chartname, cus_off);
- freez(cus_chart_v);
- break;
- }
- /* Read regex name config */
- char *cus_regex_name_k = mallocz(snprintf(NULL, 0, "custom %d regex name", MAX_CUS_CHARTS_PER_SOURCE) + 1);
- sprintf(cus_regex_name_k, "custom %d regex name", cus_off);
- char *cus_regex_name_v = appconfig_get( &log_management_config, config_section->name,
- cus_regex_name_k, cus_regex_v);
- debug_log( "cus regex name: (%s:%s)", cus_regex_name_k, cus_regex_name_v ? cus_regex_name_v : "NULL");
- freez(cus_regex_name_k);
- m_assert(cus_regex_name_v, "cus_regex_name_v cannot be NULL, should be cus_regex_v");
-
-
- /* Escape any backslashes in the regex name, to ensure dimension is displayed correctly in charts */
- int regex_name_bslashes = 0;
- char **p_regex_name = &cus_regex_name_v;
- for(char *p = *p_regex_name; *p; p++) if(unlikely(*p == '\\')) regex_name_bslashes++;
- if(regex_name_bslashes) {
- *p_regex_name = reallocz(*p_regex_name, strlen(*p_regex_name) + 1 + regex_name_bslashes);
- for(char *p = *p_regex_name; *p; p++){
- if(unlikely(*p == '\\')){
- memmove(p + 1, p, strlen(p) + 1);
- *p++ = '\\';
- }
- }
- }
- /* Read ignore case config */
- char *cus_ignore_case_k = mallocz(snprintf(NULL, 0, "custom %d ignore case", MAX_CUS_CHARTS_PER_SOURCE) + 1);
- sprintf(cus_ignore_case_k, "custom %d ignore case", cus_off);
- int cus_ignore_case_v = appconfig_get_boolean( &log_management_config,
- config_section->name, cus_ignore_case_k, CONFIG_BOOLEAN_YES);
- debug_log( "cus case: (%s:%s)", cus_ignore_case_k, cus_ignore_case_v ? "yes" : "no");
- freez(cus_ignore_case_k);
- int regex_flags = cus_ignore_case_v ? REG_EXTENDED | REG_NEWLINE | REG_ICASE : REG_EXTENDED | REG_NEWLINE;
-
- int rc;
- regex_t regex;
- if (unlikely((rc = regcomp(®ex, cus_regex_v, regex_flags)))){
- size_t regcomp_err_str_size = regerror(rc, ®ex, 0, 0);
- char *regcomp_err_str = mallocz(regcomp_err_str_size);
- regerror(rc, ®ex, regcomp_err_str, regcomp_err_str_size);
- collector_error("[%s]: could not compile regex for custom %d chart: %s due to error: %s. "
- "Custom charts for this log source will be disabled.",
- p_file_info->chartname, cus_off, cus_chart_v, regcomp_err_str);
- freez(regcomp_err_str);
- freez(cus_chart_v);
- freez(cus_regex_v);
- freez(cus_regex_name_v);
- break;
- };
- /* Allocate memory and copy config to p_file_info->parser_cus_config struct */
- p_file_info->parser_cus_config = reallocz( p_file_info->parser_cus_config,
- (cus_off + 1) * sizeof(Log_parser_cus_config_t *));
- p_file_info->parser_cus_config[cus_off - 1] = callocz(1, sizeof(Log_parser_cus_config_t));
- p_file_info->parser_cus_config[cus_off - 1]->chartname = cus_chart_v;
- p_file_info->parser_cus_config[cus_off - 1]->regex_str = cus_regex_v;
- p_file_info->parser_cus_config[cus_off - 1]->regex_name = cus_regex_name_v;
- p_file_info->parser_cus_config[cus_off - 1]->regex = regex;
- /* Initialise custom log parser metrics struct array */
- p_file_info->parser_metrics->parser_cus = reallocz( p_file_info->parser_metrics->parser_cus,
- (cus_off + 1) * sizeof(Log_parser_cus_metrics_t *));
- p_file_info->parser_metrics->parser_cus[cus_off - 1] = callocz(1, sizeof(Log_parser_cus_metrics_t));
- p_file_info->parser_cus_config[cus_off] = NULL;
- p_file_info->parser_metrics->parser_cus[cus_off] = NULL;
- }
- /* -------------------------------------------------------------------------
- * Configure (optional) Fluent Bit outputs.
- * ------------------------------------------------------------------------- */
-
- Flb_output_config_t **output_next_p = &p_file_info->flb_outputs;
- for(int out_off = 1; out_off <= MAX_OUTPUTS_PER_SOURCE; out_off++){
- /* Read output plugin */
- char *out_plugin_k = callocz(1, snprintf(NULL, 0, "output %d " FLB_OUTPUT_PLUGIN_NAME_KEY, MAX_OUTPUTS_PER_SOURCE) + 1);
- sprintf(out_plugin_k, "output %d " FLB_OUTPUT_PLUGIN_NAME_KEY, out_off);
- char *out_plugin_v = appconfig_get(&log_management_config, config_section->name, out_plugin_k, NULL);
- debug_log( "output %d "FLB_OUTPUT_PLUGIN_NAME_KEY": %s", out_off, out_plugin_v ? out_plugin_v : "NULL");
- freez(out_plugin_k);
- if(unlikely(!out_plugin_v)){
- collector_error("[%s]: output %d "FLB_OUTPUT_PLUGIN_NAME_KEY" = NULL, outputs for this log source will be disabled.",
- p_file_info->chartname, out_off);
- break;
- }
- Flb_output_config_t *output = callocz(1, sizeof(Flb_output_config_t));
- output->id = out_off;
- output->plugin = out_plugin_v;
- /* Read parameters for this output */
- avl_traverse_lock(&config_section->values_index, flb_output_param_get_cb, output);
- *output_next_p = output;
- output_next_p = &output->next;
- }
-
-
- /* -------------------------------------------------------------------------
- * Read circular buffer configuration and initialize the buffer.
- * ------------------------------------------------------------------------- */
- size_t circular_buffer_max_size = ((size_t)appconfig_get_number(&log_management_config,
- config_section->name,
- "circular buffer max size MiB",
- g_logs_manag_config.circ_buff_max_size_in_mib)) MiB;
- if(circular_buffer_max_size > CIRCULAR_BUFF_MAX_SIZE_RANGE_MAX) {
- circular_buffer_max_size = CIRCULAR_BUFF_MAX_SIZE_RANGE_MAX;
- collector_info( "[%s]: circular buffer max size out of range. Using maximum permitted value (MiB): %zu",
- p_file_info->chartname, (size_t) (circular_buffer_max_size / (1 MiB)));
- } else if(circular_buffer_max_size < CIRCULAR_BUFF_MAX_SIZE_RANGE_MIN) {
- circular_buffer_max_size = CIRCULAR_BUFF_MAX_SIZE_RANGE_MIN;
- collector_info( "[%s]: circular buffer max size out of range. Using minimum permitted value (MiB): %zu",
- p_file_info->chartname, (size_t) (circular_buffer_max_size / (1 MiB)));
- }
- collector_info("[%s]: circular buffer max size MiB = %zu", p_file_info->chartname, (size_t) (circular_buffer_max_size / (1 MiB)));
- int circular_buffer_allow_dropped_logs = appconfig_get_boolean( &log_management_config,
- config_section->name,
- "circular buffer drop logs if full",
- g_logs_manag_config.circ_buff_drop_logs);
- collector_info("[%s]: circular buffer drop logs if full = %s", p_file_info->chartname,
- circular_buffer_allow_dropped_logs ? "yes" : "no");
- p_file_info->circ_buff = circ_buff_init(p_file_info->buff_flush_to_db_interval,
- circular_buffer_max_size,
- circular_buffer_allow_dropped_logs);
- /* -------------------------------------------------------------------------
- * Initialize rrd related structures.
- * ------------------------------------------------------------------------- */
- p_file_info->chart_meta = callocz(1, sizeof(struct Chart_meta));
- memcpy(p_file_info->chart_meta, &chart_types[p_file_info->log_type], sizeof(struct Chart_meta));
- p_file_info->chart_meta->base_prio = NETDATA_CHART_PRIO_LOGS_BASE + p_file_infos_arr->count * NETDATA_CHART_PRIO_LOGS_INCR;
- netdata_mutex_lock(stdout_mut);
- p_file_info->chart_meta->init(p_file_info);
- fflush(stdout);
- netdata_mutex_unlock(stdout_mut);
- /* -------------------------------------------------------------------------
- * Initialize input plugin for local log sources.
- * ------------------------------------------------------------------------- */
- if(p_file_info->log_source == LOG_SOURCE_LOCAL){
- int rc = flb_add_input(p_file_info);
- if(unlikely(rc)){
- collector_error("[%s]: flb_add_input() error: %d", p_file_info->chartname, rc);
- return p_file_info_destroy(p_file_info);
- }
- }
- /* flb_complete_item_timer_timeout_cb() is needed for both local and
- * non-local sources. */
- p_file_info->flb_tmp_buff_cpy_timer.data = p_file_info;
- if(unlikely(0 != uv_mutex_init(&p_file_info->flb_tmp_buff_mut)))
- fatal("uv_mutex_init(&p_file_info->flb_tmp_buff_mut) failed");
- fatal_assert(0 == uv_timer_init( main_loop,
- &p_file_info->flb_tmp_buff_cpy_timer));
- fatal_assert(0 == uv_timer_start( &p_file_info->flb_tmp_buff_cpy_timer,
- flb_complete_item_timer_timeout_cb, 0,
- p_file_info->update_timeout * MSEC_PER_SEC));
-
- /* -------------------------------------------------------------------------
- * All set up successfully - add p_file_info to list of all p_file_info structs.
- * ------------------------------------------------------------------------- */
- p_file_infos_arr->data = reallocz(p_file_infos_arr->data, (++p_file_infos_arr->count) * (sizeof p_file_info));
- p_file_infos_arr->data[p_file_infos_arr->count - 1] = p_file_info;
- __atomic_store_n(&p_file_info->state, LOG_SRC_READY, __ATOMIC_RELAXED);
- collector_info("[%s]: initialization completed", p_file_info->chartname);
- }
- void config_file_load( uv_loop_t *main_loop,
- Flb_socket_config_t *p_forward_in_config,
- flb_srvc_config_t *p_flb_srvc_config,
- netdata_mutex_t *stdout_mut){
-
- int user_default_conf_found = 0;
- struct section *config_section;
- char tmp_name[FILENAME_MAX + 1];
- snprintfz(tmp_name, FILENAME_MAX, "%s/logsmanagement.d", get_user_config_dir());
- DIR *dir = opendir(tmp_name);
- if(dir){
- struct dirent *de = NULL;
- while ((de = readdir(dir))) {
- size_t d_name_len = strlen(de->d_name);
- if (de->d_type == DT_DIR || d_name_len < 6 || strncmp(&de->d_name[d_name_len - 5], ".conf", sizeof(".conf")))
- continue;
- if(!user_default_conf_found && !strncmp(de->d_name, "default.conf", sizeof("default.conf")))
- user_default_conf_found = 1;
- snprintfz(tmp_name, FILENAME_MAX, "%s/logsmanagement.d/%s", get_user_config_dir(), de->d_name);
- collector_info("loading config:%s", tmp_name);
- log_management_config = (struct config){
- .first_section = NULL,
- .last_section = NULL,
- .mutex = NETDATA_MUTEX_INITIALIZER,
- .index = {
- .avl_tree = {
- .root = NULL,
- .compar = appconfig_section_compare
- },
- .rwlock = AVL_LOCK_INITIALIZER
- }
- };
- if(!appconfig_load(&log_management_config, tmp_name, 0, NULL))
- continue;
- config_section = log_management_config.first_section;
- do {
- config_section_init(main_loop, config_section, p_forward_in_config, p_flb_srvc_config, stdout_mut);
- config_section = config_section->next;
- } while(config_section);
- }
- closedir(dir);
- }
- if(!user_default_conf_found){
- collector_info("CONFIG: cannot load user config '%s/logsmanagement.d/default.conf'. Will try stock config.", get_user_config_dir());
- snprintfz(tmp_name, FILENAME_MAX, "%s/logsmanagement.d/default.conf", get_stock_config_dir());
- if(!appconfig_load(&log_management_config, tmp_name, 0, NULL)){
- collector_error("CONFIG: cannot load stock config '%s/logsmanagement.d/default.conf'. Logs management will be disabled.", get_stock_config_dir());
- exit(1);
- }
- config_section = log_management_config.first_section;
- do {
- config_section_init(main_loop, config_section, p_forward_in_config, p_flb_srvc_config, stdout_mut);
- config_section = config_section->next;
- } while(config_section);
- }
- }
|