X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Fredis.c;h=77ce5fb615adb52aca056e77e8e19c523d24aa37;hp=36f57b0972749117893661e482561feecd7e9735;hb=54619dc85fd308b21ed09a0271e5c7383c7921b9;hpb=7f07c55bac640c7a50d516248a3152235a14af59 diff --git a/src/redis.c b/src/redis.c index 36f57b09..77ce5fb6 100644 --- a/src/redis.c +++ b/src/redis.c @@ -22,8 +22,8 @@ #include "collectd.h" -#include "common.h" #include "plugin.h" +#include "utils/common/common.h" #include #include @@ -59,11 +59,18 @@ struct redis_query_s { redis_query_t *next; }; +struct prev_s { + derive_t keyspace_hits; + derive_t keyspace_misses; +}; +typedef struct prev_s prev_t; + struct redis_node_s; typedef struct redis_node_s redis_node_t; struct redis_node_s { char *name; char *host; + char *socket; char *passwd; int port; struct timeval timeout; @@ -71,6 +78,7 @@ struct redis_node_s { bool report_cpu_usage; redisContext *redisContext; redis_query_t *queries; + prev_t prev; redis_node_t *next; }; @@ -90,9 +98,11 @@ static void redis_node_free(void *arg) { rq = next; } - redisFree(rn->redisContext); + if (rn->redisContext) + redisFree(rn->redisContext); sfree(rn->name); sfree(rn->host); + sfree(rn->socket); sfree(rn->passwd); sfree(rn); } /* void redis_node_free */ @@ -105,7 +115,7 @@ static int redis_node_add(redis_node_t *rn) /* {{{ */ redis_have_instances = true; char cb_name[sizeof("redis/") + DATA_MAX_NAME_LEN]; - snprintf(cb_name, sizeof(cb_name), "redis/%s", rn->name); + ssnprintf(cb_name, sizeof(cb_name), "redis/%s", rn->name); return plugin_register_complex_read( /* group = */ "redis", @@ -113,7 +123,8 @@ static int redis_node_add(redis_node_t *rn) /* {{{ */ /* callback = */ redis_read, /* interval = */ 0, &(user_data_t){ - .data = rn, .free_func = redis_node_free, + .data = rn, + .free_func = redis_node_free, }); } /* }}} */ @@ -205,6 +216,8 @@ static int redis_config_node(oconfig_item_t *ci) /* {{{ */ rn->port = status; status = 0; } + } else if (strcasecmp("Socket", option->key) == 0) { + status = cf_util_get_string(option, &rn->socket); } else if (strcasecmp("Query", option->key) == 0) { redis_query_t *rq = redis_config_query(option); if (rq == NULL) { @@ -474,7 +487,7 @@ static int redis_db_stats(const char *node, char const *info_line) /* {{{ */ char *str; int i; - snprintf(field_name, sizeof(field_name), "db%d:keys=", db); + ssnprintf(field_name, sizeof(field_name), "db%d:keys=", db); str = strstr(info_line, field_name); if (!str) @@ -490,7 +503,7 @@ static int redis_db_stats(const char *node, char const *info_line) /* {{{ */ return -1; } - snprintf(db_id, sizeof(db_id), "%d", db); + ssnprintf(db_id, sizeof(db_id), "%d", db); redis_submit(node, "records", db_id, val); } return 0; @@ -535,19 +548,71 @@ static void redis_cpu_usage(const char *node, char const *info_line) { } } /* void redis_cpu_usage */ +static gauge_t calculate_ratio_percent(derive_t part1, derive_t part2, + derive_t *prev1, derive_t *prev2) { + if ((*prev1 == 0) || (*prev2 == 0) || (part1 < *prev1) || (part2 < *prev2)) { + *prev1 = part1; + *prev2 = part2; + return NAN; + } + + derive_t num = part1 - *prev1; + derive_t denom = part2 - *prev2 + num; + + *prev1 = part1; + *prev2 = part2; + + if (denom == 0) + return NAN; + + if (num == 0) + return 0; + + return 100.0 * (gauge_t)num / (gauge_t)denom; +} /* gauge_t calculate_ratio_percent */ + +static void redis_keyspace_usage(redis_node_t *rn, char const *info_line) { + value_t hits, misses; + + if (redis_get_info_value(info_line, "keyspace_hits", DS_TYPE_DERIVE, &hits) != + 0) + return; + + if (redis_get_info_value(info_line, "keyspace_misses", DS_TYPE_DERIVE, + &misses) != 0) + return; + + redis_submit(rn->name, "cache_result", "hits", hits); + redis_submit(rn->name, "cache_result", "misses", misses); + + prev_t *prev = &rn->prev; + gauge_t ratio = calculate_ratio_percent( + hits.derive, misses.derive, &prev->keyspace_hits, &prev->keyspace_misses); + redis_submit(rn->name, "percent", "hitratio", (value_t){.gauge = ratio}); + +} /* void redis_keyspace_usage */ + static void redis_check_connection(redis_node_t *rn) { if (rn->redisContext) return; - redisContext *rh = redisConnectWithTimeout(rn->host, rn->port, rn->timeout); + redisContext *rh; + if (rn->socket != NULL) + rh = redisConnectUnixWithTimeout(rn->socket, rn->timeout); + else + rh = redisConnectWithTimeout(rn->host, rn->port, rn->timeout); if (rh == NULL) { ERROR("redis plugin: can't allocate redis context"); return; } if (rh->err) { - ERROR("redis plugin: unable to connect to node `%s' (%s:%d): %s.", rn->name, - rn->host, rn->port, rh->errstr); + if (rn->socket) + ERROR("redis plugin: unable to connect to node `%s' (%s): %s.", rn->name, + rn->socket, rh->errstr); + else + ERROR("redis plugin: unable to connect to node `%s' (%s:%d): %s.", + rn->name, rn->host, rn->port, rh->errstr); redisFree(rh); return; } @@ -603,8 +668,6 @@ static void redis_read_server_info(redis_node_t *rn) { "total_connections_received", DS_TYPE_DERIVE); redis_handle_info(rn->name, rr->str, "total_operations", NULL, "total_commands_processed", DS_TYPE_DERIVE); - redis_handle_info(rn->name, rr->str, "operations_per_second", NULL, - "instantaneous_ops_per_sec", DS_TYPE_GAUGE); redis_handle_info(rn->name, rr->str, "expired_keys", NULL, "expired_keys", DS_TYPE_DERIVE); redis_handle_info(rn->name, rr->str, "evicted_keys", NULL, "evicted_keys", @@ -615,15 +678,13 @@ static void redis_read_server_info(redis_node_t *rn) { DS_TYPE_GAUGE); redis_handle_info(rn->name, rr->str, "current_connections", "slaves", "connected_slaves", DS_TYPE_GAUGE); - redis_handle_info(rn->name, rr->str, "cache_result", "hits", "keyspace_hits", - DS_TYPE_DERIVE); - redis_handle_info(rn->name, rr->str, "cache_result", "misses", - "keyspace_misses", DS_TYPE_DERIVE); redis_handle_info(rn->name, rr->str, "total_bytes", "input", "total_net_input_bytes", DS_TYPE_DERIVE); redis_handle_info(rn->name, rr->str, "total_bytes", "output", "total_net_output_bytes", DS_TYPE_DERIVE); + redis_keyspace_usage(rn, rr->str); + redis_db_stats(rn->name, rr->str); if (rn->report_cpu_usage) @@ -712,8 +773,14 @@ static int redis_read(user_data_t *user_data) /* {{{ */ { redis_node_t *rn = user_data->data; - DEBUG("redis plugin: querying info from node `%s' (%s:%d).", rn->name, - rn->host, rn->port); +#if COLLECT_DEBUG + if (rn->socket) + DEBUG("redis plugin: querying info from node `%s' (%s).", rn->name, + rn->socket); + else + DEBUG("redis plugin: querying info from node `%s' (%s:%d).", rn->name, + rn->host, rn->port); +#endif redis_check_connection(rn);