static int camqp_config_connection (oconfig_item_t *ci, /* {{{ */ _Bool publish) { camqp_config_t *conf; int status; int i; conf = malloc (sizeof (*conf)); if (conf == NULL) { ERROR ("amqp plugin: malloc failed."); return (ENOMEM); } /* Initialize "conf" {{{ */ memset (conf, 0, sizeof (*conf)); conf->publish = publish; conf->name = NULL; conf->format = CAMQP_FORMAT_COMMAND; conf->host = NULL; conf->port = 5672; conf->vhost = NULL; conf->user = NULL; conf->password = NULL; conf->exchange = NULL; conf->routing_key = NULL; conf->connection_retry_delay = 0; /* publish only */ conf->delivery_mode = CAMQP_DM_VOLATILE; conf->store_rates = 0; conf->graphite_flags = 0; /* publish & graphite only */ conf->prefix = NULL; conf->postfix = NULL; conf->escape_char = '_'; /* subscribe only */ conf->exchange_type = NULL; conf->queue = NULL; conf->queue_durable = 0; conf->queue_auto_delete = 1; /* general */ conf->connection = NULL; pthread_mutex_init (&conf->lock, /* attr = */ NULL); /* }}} */ status = cf_util_get_string (ci, &conf->name); if (status != 0) { sfree (conf); return (status); } for (i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; if (strcasecmp ("Host", child->key) == 0) status = cf_util_get_string (child, &conf->host); else if (strcasecmp ("Port", child->key) == 0) { status = cf_util_get_port_number (child); if (status > 0) { conf->port = status; status = 0; } } else if (strcasecmp ("VHost", child->key) == 0) status = cf_util_get_string (child, &conf->vhost); else if (strcasecmp ("User", child->key) == 0) status = cf_util_get_string (child, &conf->user); else if (strcasecmp ("Password", child->key) == 0) status = cf_util_get_string (child, &conf->password); else if (strcasecmp ("Exchange", child->key) == 0) status = cf_util_get_string (child, &conf->exchange); else if ((strcasecmp ("ExchangeType", child->key) == 0) && !publish) status = cf_util_get_string (child, &conf->exchange_type); else if ((strcasecmp ("Queue", child->key) == 0) && !publish) status = cf_util_get_string (child, &conf->queue); else if ((strcasecmp ("QueueDurable", child->key) == 0) && !publish) status = cf_util_get_boolean (child, &conf->queue_durable); else if ((strcasecmp ("QueueAutoDelete", child->key) == 0) && !publish) status = cf_util_get_boolean (child, &conf->queue_auto_delete); else if (strcasecmp ("RoutingKey", child->key) == 0) status = cf_util_get_string (child, &conf->routing_key); else if ((strcasecmp ("Persistent", child->key) == 0) && publish) { _Bool tmp = 0; status = cf_util_get_boolean (child, &tmp); if (tmp) conf->delivery_mode = CAMQP_DM_PERSISTENT; else conf->delivery_mode = CAMQP_DM_VOLATILE; } else if ((strcasecmp ("StoreRates", child->key) == 0) && publish) { status = cf_util_get_boolean (child, &conf->store_rates); (void) cf_util_get_flag (child, &conf->graphite_flags, GRAPHITE_STORE_RATES); } else if ((strcasecmp ("Format", child->key) == 0) && publish) status = camqp_config_set_format (child, conf); else if ((strcasecmp ("GraphiteSeparateInstances", child->key) == 0) && publish) status = cf_util_get_flag (child, &conf->graphite_flags, GRAPHITE_SEPARATE_INSTANCES); else if ((strcasecmp ("GraphiteAlwaysAppendDS", child->key) == 0) && publish) status = cf_util_get_flag (child, &conf->graphite_flags, GRAPHITE_ALWAYS_APPEND_DS); else if ((strcasecmp ("GraphitePrefix", child->key) == 0) && publish) status = cf_util_get_string (child, &conf->prefix); else if ((strcasecmp ("GraphitePostfix", child->key) == 0) && publish) status = cf_util_get_string (child, &conf->postfix); else if ((strcasecmp ("GraphiteEscapeChar", child->key) == 0) && publish) { char *tmp_buff = NULL; status = cf_util_get_string (child, &tmp_buff); if (strlen (tmp_buff) > 1) WARNING ("amqp plugin: The option \"GraphiteEscapeChar\" handles " "only one character. Others will be ignored."); conf->escape_char = tmp_buff[0]; sfree (tmp_buff); } else if (strcasecmp ("ConnectionRetryDelay", child->key) == 0) status = cf_util_get_int (child, &conf->connection_retry_delay); else WARNING ("amqp plugin: Ignoring unknown " "configuration option \"%s\".", child->key); if (status != 0) break; } /* for (i = 0; i < ci->children_num; i++) */ if ((status == 0) && (conf->exchange == NULL)) { if (conf->exchange_type != NULL) WARNING ("amqp plugin: The option \"ExchangeType\" was given " "without the \"Exchange\" option. It will be ignored."); if (!publish && (conf->routing_key != NULL)) WARNING ("amqp plugin: The option \"RoutingKey\" was given " "without the \"Exchange\" option. It will be ignored."); } if (status != 0) { camqp_config_free (conf); return (status); } if (conf->exchange != NULL) { DEBUG ("amqp plugin: camqp_config_connection: exchange = %s;", conf->exchange); } if (publish) { char cbname[128]; user_data_t ud = { conf, camqp_config_free }; ssnprintf (cbname, sizeof (cbname), "amqp/%s", conf->name); status = plugin_register_write (cbname, camqp_write, &ud); if (status != 0) { camqp_config_free (conf); return (status); } } else { status = camqp_subscribe_init (conf); if (status != 0) { camqp_config_free (conf); return (status); } } return (0); } /* }}} int camqp_config_connection */
/* * Configuration * ============= * The following approximately two hundred functions are used to handle the * configuration and fill the threshold list. * {{{ */ static int ut_config_type(const threshold_t *th_orig, oconfig_item_t *ci) { threshold_t th; int status = 0; if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { WARNING("threshold values: The `Type' block needs exactly one string " "argument."); return -1; } if (ci->children_num < 1) { WARNING("threshold values: The `Type' block needs at least one option."); return -1; } memcpy(&th, th_orig, sizeof(th)); sstrncpy(th.type, ci->values[0].value.string, sizeof(th.type)); th.warning_min = NAN; th.warning_max = NAN; th.failure_min = NAN; th.failure_max = NAN; th.hits = 0; th.hysteresis = 0; th.flags = UT_FLAG_INTERESTING; /* interesting by default */ for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i; if (strcasecmp("Instance", option->key) == 0) status = cf_util_get_string_buffer(option, th.type_instance, sizeof(th.type_instance)); else if (strcasecmp("DataSource", option->key) == 0) status = cf_util_get_string_buffer(option, th.data_source, sizeof(th.data_source)); else if (strcasecmp("WarningMax", option->key) == 0) status = cf_util_get_double(option, &th.warning_max); else if (strcasecmp("FailureMax", option->key) == 0) status = cf_util_get_double(option, &th.failure_max); else if (strcasecmp("WarningMin", option->key) == 0) status = cf_util_get_double(option, &th.warning_min); else if (strcasecmp("FailureMin", option->key) == 0) status = cf_util_get_double(option, &th.failure_min); else if (strcasecmp("Interesting", option->key) == 0) status = cf_util_get_flag(option, &th.flags, UT_FLAG_INTERESTING); else if (strcasecmp("Invert", option->key) == 0) status = cf_util_get_flag(option, &th.flags, UT_FLAG_INVERT); else if (strcasecmp("Persist", option->key) == 0) status = cf_util_get_flag(option, &th.flags, UT_FLAG_PERSIST); else if (strcasecmp("PersistOK", option->key) == 0) status = cf_util_get_flag(option, &th.flags, UT_FLAG_PERSIST_OK); else if (strcasecmp("Percentage", option->key) == 0) status = cf_util_get_flag(option, &th.flags, UT_FLAG_PERCENTAGE); else if (strcasecmp("Hits", option->key) == 0) status = cf_util_get_int(option, &th.hits); else if (strcasecmp("Hysteresis", option->key) == 0) status = cf_util_get_double(option, &th.hysteresis); else { WARNING("threshold values: Option `%s' not allowed inside a `Type' " "block.", option->key); status = -1; } if (status != 0) break; } if (status == 0) { status = ut_threshold_add(&th); } return status; } /* int ut_config_type */
static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{ */ { int status; int i; struct kafka_topic_context *tctx; char *key; char *val; char callback_name[DATA_MAX_NAME_LEN]; char errbuf[1024]; user_data_t ud; oconfig_item_t *child; rd_kafka_conf_res_t ret; if ((tctx = calloc(1, sizeof (*tctx))) == NULL) { ERROR ("write_kafka plugin: calloc failed."); return; } tctx->escape_char = '.'; tctx->store_rates = 1; rd_kafka_conf_set_log_cb(conf, kafka_log); if ((tctx->kafka = rd_kafka_new(RD_KAFKA_PRODUCER, conf, errbuf, sizeof(errbuf))) == NULL) { sfree(tctx); ERROR("write_kafka plugin: cannot create kafka handle."); return; } conf = NULL; if ((tctx->conf = rd_kafka_topic_conf_new()) == NULL) { rd_kafka_destroy(tctx->kafka); sfree(tctx); ERROR ("write_kafka plugin: cannot create topic configuration."); return; } if (ci->values_num != 1) { WARNING("kafka topic name needed."); goto errout; } if (ci->values[0].type != OCONFIG_TYPE_STRING) { WARNING("kafka topic needs a string argument."); goto errout; } if ((tctx->topic_name = strdup(ci->values[0].value.string)) == NULL) { ERROR("write_kafka plugin: cannot copy topic name."); goto errout; } for (i = 0; i < ci->children_num; i++) { /* * The code here could be simplified but makes room * for easy adding of new options later on. */ child = &ci->children[i]; status = 0; if (strcasecmp ("Property", child->key) == 0) { if (child->values_num != 2) { WARNING("kafka properties need both a key and a value."); goto errout; } if (child->values[0].type != OCONFIG_TYPE_STRING || child->values[1].type != OCONFIG_TYPE_STRING) { WARNING("kafka properties needs string arguments."); goto errout; } key = child->values[0].value.string; val = child->values[0].value.string; ret = rd_kafka_topic_conf_set(tctx->conf,key, val, errbuf, sizeof(errbuf)); if (ret != RD_KAFKA_CONF_OK) { WARNING("cannot set kafka topic property %s to %s: %s.", key, val, errbuf); goto errout; } } else if (strcasecmp ("Key", child->key) == 0) { char *tmp_buf = NULL; status = cf_util_get_string(child, &tmp_buf); if (status != 0) { WARNING("write_kafka plugin: invalid key supplied"); break; } if (strcasecmp(tmp_buf, "Random") != 0) { tctx->has_key = 1; tctx->key = crc32_buffer((u_char *)tmp_buf, strlen(tmp_buf)); } sfree(tmp_buf); } else if (strcasecmp ("Format", child->key) == 0) { status = cf_util_get_string(child, &key); if (status != 0) goto errout; assert(key != NULL); if (strcasecmp(key, "Command") == 0) { tctx->format = KAFKA_FORMAT_COMMAND; } else if (strcasecmp(key, "Graphite") == 0) { tctx->format = KAFKA_FORMAT_GRAPHITE; } else if (strcasecmp(key, "Json") == 0) { tctx->format = KAFKA_FORMAT_JSON; } else { WARNING ("write_kafka plugin: Invalid format string: %s", key); } sfree(key); } else if (strcasecmp ("StoreRates", child->key) == 0) { status = cf_util_get_boolean (child, &tctx->store_rates); (void) cf_util_get_flag (child, &tctx->graphite_flags, GRAPHITE_STORE_RATES); } else if (strcasecmp ("GraphiteSeparateInstances", child->key) == 0) { status = cf_util_get_flag (child, &tctx->graphite_flags, GRAPHITE_SEPARATE_INSTANCES); } else if (strcasecmp ("GraphiteAlwaysAppendDS", child->key) == 0) { status = cf_util_get_flag (child, &tctx->graphite_flags, GRAPHITE_ALWAYS_APPEND_DS); } else if (strcasecmp ("GraphitePrefix", child->key) == 0) { status = cf_util_get_string (child, &tctx->prefix); } else if (strcasecmp ("GraphitePostfix", child->key) == 0) { status = cf_util_get_string (child, &tctx->postfix); } else if (strcasecmp ("GraphiteEscapeChar", child->key) == 0) { char *tmp_buff = NULL; status = cf_util_get_string (child, &tmp_buff); if (strlen (tmp_buff) > 1) WARNING ("write_kafka plugin: The option \"GraphiteEscapeChar\" handles " "only one character. Others will be ignored."); tctx->escape_char = tmp_buff[0]; sfree (tmp_buff); } else { WARNING ("write_kafka plugin: Invalid directive: %s.", child->key); } if (status != 0) break; } rd_kafka_topic_conf_set_partitioner_cb(tctx->conf, kafka_partition); rd_kafka_topic_conf_set_opaque(tctx->conf, tctx); if ((tctx->topic = rd_kafka_topic_new(tctx->kafka, tctx->topic_name, tctx->conf)) == NULL) { ERROR("write_kafka plugin: cannot create topic."); goto errout; } tctx->conf = NULL; ssnprintf(callback_name, sizeof(callback_name), "write_kafka/%s", tctx->topic_name); ud.data = tctx; ud.free_func = kafka_topic_context_free; status = plugin_register_write (callback_name, kafka_write, &ud); if (status != 0) { WARNING ("write_kafka plugin: plugin_register_write (\"%s\") " "failed with status %i.", callback_name, status); goto errout; } return; errout: if (conf != NULL) rd_kafka_conf_destroy(conf); if (tctx->kafka != NULL) rd_kafka_destroy(tctx->kafka); if (tctx->topic != NULL) rd_kafka_topic_destroy(tctx->topic); if (tctx->topic_name != NULL) free(tctx->topic_name); if (tctx->conf != NULL) rd_kafka_topic_conf_destroy(tctx->conf); sfree(tctx); } /* }}} int kafka_config_topic */