From: Florian Forster Date: Wed, 3 Nov 2010 13:15:37 +0000 (+0100) Subject: mongodb plugin: Rename the "mongo" plugin. X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=5488370b9951ffc4a609d252cecf0b545178bc26;p=collectd.git mongodb plugin: Rename the "mongo" plugin. --- diff --git a/configure.in b/configure.in index 156b3769..e52159cd 100644 --- a/configure.in +++ b/configure.in @@ -4685,7 +4685,7 @@ AC_PLUGIN([mbmon], [yes], [Query mbmond]) AC_PLUGIN([memcachec], [$with_libmemcached], [memcachec statistics]) AC_PLUGIN([memcached], [yes], [memcached statistics]) AC_PLUGIN([memory], [$plugin_memory], [Memory usage]) -AC_PLUGIN([mongo], [$with_libmongoc], [MongoDB statistics]) +AC_PLUGIN([mongodb], [$with_libmongoc], [MongoDB statistics]) AC_PLUGIN([modbus], [$with_libmodbus], [Modbus plugin]) AC_PLUGIN([multimeter], [$plugin_multimeter], [Read multimeter values]) AC_PLUGIN([mysql], [$with_libmysql], [MySQL statistics]) @@ -5010,7 +5010,7 @@ Configuration: memcached . . . . . . $enable_memcached memory . . . . . . . $enable_memory modbus . . . . . . . $enable_modbus - mongo . . . . . . . $enable_mongo + mongodb . . . . . . $enable_mongodb multimeter . . . . . $enable_multimeter mysql . . . . . . . . $enable_mysql netapp . . . . . . . $enable_netapp diff --git a/src/mongo.c b/src/mongo.c deleted file mode 100644 index 7d720635..00000000 --- a/src/mongo.c +++ /dev/null @@ -1,473 +0,0 @@ -/** - * collectd - src/mongo.c - * Copyright (C) 2010 Ryan Cox - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; only version 2 of the License is applicable. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Ryan Cox - **/ - -#include -#include -#include -#include -#include -#include "collectd.h" -#include "common.h" -#include "plugin.h" - -#define MC_PLUGIN_NAME "mongo" -#define MC_MONGO_DEF_HOST "127.0.0.1" -#define MC_MONGO_DEF_PORT 27017 -#define MC_MONGO_DEF_DB "admin" -#define MC_MIN_PORT 1 -#define MC_MAX_PORT 65535 -#define SUCCESS 0 -#define FAILURE -1 - -static char *mc_user = NULL; -static char *mc_password = NULL; -static char *mc_db = NULL; -static char *mc_host = NULL; -static int mc_port = MC_MONGO_DEF_PORT; - -static mongo_connection conn[1]; - -static const char *config_keys[] = { - "User", - "Password", - "Database", - "Host", - "Port" -}; - -static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); - -static void submit(const char *type, const char *instance, value_t *values, size_t values_len) { - INFO("Submiting [%d] for type [%s]",values_len,type); - value_list_t v = VALUE_LIST_INIT; - - v.values = values; - v.values_len = values_len; - - if( instance != NULL ) { - sstrncpy(v.type_instance,instance,sizeof(v.type_instance)); - } - - sstrncpy(v.host, hostname_g, sizeof(v.host)); - sstrncpy(v.plugin, MC_PLUGIN_NAME, sizeof(v.plugin)); - char port[12]; - sprintf(port, "%d",mc_port); - sstrncpy(v.plugin_instance, port, sizeof(v.plugin_instance)); - sstrncpy(v.type, type, sizeof(v.type)); - - plugin_dispatch_values(&v); -} - -static void submit_counter(const char *type, const char *instance, int64_t counter ) { - value_t v[1]; - v[0].counter = counter; - submit(type, instance, v, STATIC_ARRAY_SIZE (v)); -} - -static void submit_gauge(const char *type, const char *instance, gauge_t gauge ) { - value_t v[1]; - v[0].gauge = gauge; - submit(type, instance, v, STATIC_ARRAY_SIZE (v)); -} - - -static void handle_opcounters(bson* obj) { - INFO("handle op counters"); - bson_iterator it; - if(bson_find(&it, obj, "opcounters")) { - bson subobj; - bson_iterator_subobject(&it, &subobj); - bson_iterator it2; - bson_iterator_init(&it2, subobj.data); - - int64_t insert = 0; - int64_t query = 0; - int64_t delete = 0; - int64_t getmore = 0; - int64_t command = 0; - - while(bson_iterator_next(&it2)){ - if(strcmp(bson_iterator_key(&it2),"insert") == 0) { - insert = bson_iterator_long(&it2); - } - if(strcmp(bson_iterator_key(&it2),"query") == 0) { - query = bson_iterator_long(&it2); - } - if(strcmp(bson_iterator_key(&it2),"delete") == 0) { - delete = bson_iterator_long(&it2); - } - if(strcmp(bson_iterator_key(&it2),"getmore") == 0) { - getmore = bson_iterator_long(&it2); - } - if(strcmp(bson_iterator_key(&it2),"command") == 0) { - command = bson_iterator_long(&it2); - } - } - - bson_destroy(&subobj); - - submit_gauge("mongo_counter", "indert", insert ); - submit_gauge("mongo_counter", "query", query ); - submit_gauge("mongo_counter", "delete", delete ); - submit_gauge("mongo_counter", "getmore", getmore ); - submit_gauge("mongo_counter", "command", command ); - submit_gauge("mongo_counter", "insert", insert ); - } -} - -static void handle_mem(bson* obj) { - INFO("handle mem"); - bson_iterator it; - if(bson_find(&it, obj, "mem")) { - bson subobj; - bson_iterator_subobject(&it, &subobj); - bson_iterator it2; - bson_iterator_init(&it2, subobj.data); - int64_t resident = 0; - int64_t virtual = 0; - int64_t mapped = 0; - while(bson_iterator_next(&it2)) { - if(strcmp(bson_iterator_key(&it2),"resident") == 0) { - resident = bson_iterator_long(&it2); - } - if(strcmp(bson_iterator_key(&it2),"virtual") == 0) { - virtual = bson_iterator_long(&it2); - } - if(strcmp(bson_iterator_key(&it2),"mapped") == 0) { - mapped = bson_iterator_long(&it2); - } - } - value_t values[3]; - values[0].gauge = resident; - values[1].gauge = virtual; - values[2].gauge = mapped; - submit_gauge("memory", "resident", resident ); - submit_gauge("memory", "virtual", virtual ); - submit_gauge("memory", "mapped", mapped ); - bson_destroy(&subobj); - } -} - -static void handle_connections(bson* obj) { - INFO("handle connections"); - bson_iterator it; - if(bson_find(&it, obj, "connections")) { - bson subobj; - bson_iterator_subobject(&it, &subobj); - bson_iterator it2; - bson_iterator_init(&it2, subobj.data); - while(bson_iterator_next(&it2)) { - if(strcmp(bson_iterator_key(&it2),"current") == 0) { - submit_gauge("connections", "connections", bson_iterator_int(&it2)); - break; - } - } - bson_destroy(&subobj); - } -} - -static void handle_lock(bson* obj) { - INFO("handle lock"); - bson_iterator it; - if(bson_find(&it, obj, "globalLock")) { - bson subobj; - bson_iterator_subobject(&it, &subobj); - bson_iterator it2; - bson_iterator_init(&it2, subobj.data); - while(bson_iterator_next(&it2)) { - if(strcmp(bson_iterator_key(&it2),"ratio") == 0) { - submit_gauge("percent", "lock_ratio", bson_iterator_double(&it2)); - } - } - bson_destroy(&subobj); - } -} - -static void handle_index_counters(bson* obj) { - INFO("handle index counters"); - bson_iterator icit; - if(bson_find(&icit, obj, "indexCounters")) { - bson oic; - bson_iterator_subobject(&icit, &oic); - bson_iterator bit; - if(bson_find(&icit, &oic, "btree")) { - bson obt; - bson_iterator_subobject(&icit, &obt); - bson_iterator bit; - bson_iterator_init(&bit, oic.data); - int accesses; - int misses; - while(bson_iterator_next(&bit)) { - if(strcmp(bson_iterator_key(&bit),"accesses") == 0) { - accesses = bson_iterator_int(&bit); - } - if(strcmp(bson_iterator_key(&bit),"misses") == 0) { - misses = bson_iterator_int(&bit); - } - } - - double ratio = 0; - if( misses > 0 ) { - double ratio = accesses/misses; - } - submit_gauge("cache_ratio", "cache_misses", ratio ); - bson_destroy(&obt); - } - bson_destroy(&oic); - } -} - -static void handle_stats_counts(bson* obj) { - - INFO("handle stats counts"); - bson_iterator it; - bson_iterator_init(&it, obj->data); - int64_t collections = 0; - int64_t objects = 0; - int64_t numExtents = 0; - int64_t indexes = 0; - - while(bson_iterator_next(&it)) { - if(strcmp(bson_iterator_key(&it),"collections") == 0) { - collections = bson_iterator_long(&it); - } - if(strcmp(bson_iterator_key(&it),"objects") == 0) { - objects = bson_iterator_long(&it); - } - if(strcmp(bson_iterator_key(&it),"numExtents") == 0) { - numExtents = bson_iterator_long(&it); - } - if(strcmp(bson_iterator_key(&it),"indexes") == 0) { - indexes = bson_iterator_long(&it); - } - } - - submit_gauge("counter","object_count",objects); - - submit_gauge("counter", "collections",collections); - submit_gauge("counter", "num_extents",numExtents); - submit_gauge("counter", "indexes",indexes); -} - -static void handle_stats_sizes(bson* obj) { - bson_iterator it; - bson_iterator_init(&it, obj->data); - int64_t storageSize = 0; - int64_t dataSize = 0; - int64_t indexSize = 0; - while(bson_iterator_next(&it)) { - if(strcmp(bson_iterator_key(&it),"storageSize") == 0) { - storageSize = bson_iterator_long(&it); - } - if(strcmp(bson_iterator_key(&it),"dataSize") == 0) { - dataSize = bson_iterator_long(&it); - } - if(strcmp(bson_iterator_key(&it),"indexSize") == 0) { - indexSize = bson_iterator_long(&it); - } - } - - value_t values[3]; - submit_gauge("file_size", "storage",storageSize ); - submit_gauge("file_size", "index",indexSize ); - submit_gauge("file_size", "data",dataSize ); -} - -static int do_stats(void) { - bson obj; - - /* TODO: - - change this to raw runCommand - db.runCommand( { dbstats : 1 } ); - succeeds but is getting back all zeros !?! - modify bson_print to print type 18 - repro problem w/o db name - show dbs doesn't work again - why does db.admin.dbstats() work fine in shell? - implement retries ? noticed that if db is unavailable, collectd dies - */ - - if( !mongo_simple_int_command(conn, mc_db, "dbstats", 1, &obj) ) { - ERROR("Mongo: failed to call stats Host [%s] Port [%d] User [%s]", - mc_host, mc_port, mc_user); - return FAILURE; - } - - bson_print(&obj); - - handle_stats_sizes(&obj); - handle_stats_counts(&obj); - - - bson_destroy(&obj); - - return SUCCESS; -} - - -static int do_server_status(void) { - bson obj; - - if( !mongo_simple_int_command(conn, mc_db, "serverStatus", 1, &obj) ) { - ERROR("Mongo: failed to call serverStatus Host [%s] Port [%d] User [%s]", - mc_host, mc_port, mc_user); - return FAILURE; - } - - bson_print(&obj); - - handle_opcounters(&obj); - handle_mem(&obj); - handle_connections(&obj); - handle_index_counters(&obj); - handle_lock(&obj); - - bson_destroy(&obj); - return SUCCESS; -} - -static int mc_read(void) { - DEBUG("Mongo: mongo driver read"); - - if(do_server_status() != SUCCESS) { - ERROR("Mongo: do server status failed"); - return FAILURE; - } - - if(do_stats() != SUCCESS) { - ERROR("Mongo: do stats status failed"); - return FAILURE; - } - - return SUCCESS; -} - - -static void config_set(char** dest, const char* src ) { - if( *dest ) { - sfree(*dest); - } - *dest= malloc(strlen(src)+1); - sstrncpy(*dest,src,strlen(src)+1); -} - -static int mc_config(const char *key, const char *value) { - - DEBUG("Mongo: config key [%s] value [%s]", key, value); - if(strcasecmp("Host", key) == 0) { - config_set(&mc_host,value); - return SUCCESS; - } - - if(strcasecmp("Port", key) == 0) { - long l = strtol(value,NULL,10); - - if((errno == ERANGE && (l == LONG_MAX || l == LONG_MIN)) - || (errno != 0 && l == 0)) { - ERROR("Mongo: failed to parse Port value [%s]", value); - return FAILURE; - } - - if( l < MC_MIN_PORT || l > MC_MAX_PORT ) { - ERROR("Mongo: failed Port value [%s] outside range [1..65535]", value); - return FAILURE; - } - - mc_port = l; - return SUCCESS; - } - - if(strcasecmp("User", key) == 0) { - config_set(&mc_user,value); - return SUCCESS; - } - - if(strcasecmp("Password", key) == 0) { - config_set(&mc_password,value); - return SUCCESS; - } - - if(strcasecmp("Database", key) == 0) { - config_set(&mc_db,value); - return SUCCESS; - } - - return SUCCESS; -} - -static int mc_init(void) { - - DEBUG("mongo driver initializing"); - if( !mc_host) { - DEBUG("Mongo: Host not specified. Using default [%s]",MC_MONGO_DEF_HOST); - config_set(&mc_host, MC_MONGO_DEF_HOST); - } - - if( !mc_db) { - DEBUG("Mongo: Database not specified. Using default [%s]",MC_MONGO_DEF_DB); - config_set(&mc_db, MC_MONGO_DEF_DB); - } - - mongo_connection_options opts; - sstrncpy(opts.host, mc_host, sizeof(opts.host)); - opts.port = mc_port; - - if(mongo_connect( conn , &opts )){ - ERROR("Mongo: driver failed to connect. Host [%s] Port [%d] User [%s]", - mc_host, mc_port, mc_user); - return FAILURE; - } - - return SUCCESS; -} - -static int mc_shutdown(void) { - DEBUG("Mongo: driver shutting down"); - - if( conn ) { - mongo_disconnect(conn); - mongo_destroy(conn); - } - if( mc_user ) { - sfree(mc_user); - } - - if( mc_password ) { - sfree(mc_password); - } - - if( mc_db ) { - sfree(mc_db); - } - - if( mc_host ) { - sfree(mc_host); - } -} - - -void module_register(void) { - plugin_register_config(MC_PLUGIN_NAME, mc_config,config_keys,config_keys_num); - plugin_register_read(MC_PLUGIN_NAME, mc_read); - plugin_register_init(MC_PLUGIN_NAME, mc_init); - plugin_register_shutdown(MC_PLUGIN_NAME, mc_shutdown); - DEBUG("Mongo: driver registered"); -} diff --git a/src/mongo.h b/src/mongo.h deleted file mode 100644 index e69de29b..00000000 diff --git a/src/mongodb.c b/src/mongodb.c new file mode 100644 index 00000000..7d720635 --- /dev/null +++ b/src/mongodb.c @@ -0,0 +1,473 @@ +/** + * collectd - src/mongo.c + * Copyright (C) 2010 Ryan Cox + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; only version 2 of the License is applicable. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Ryan Cox + **/ + +#include +#include +#include +#include +#include +#include "collectd.h" +#include "common.h" +#include "plugin.h" + +#define MC_PLUGIN_NAME "mongo" +#define MC_MONGO_DEF_HOST "127.0.0.1" +#define MC_MONGO_DEF_PORT 27017 +#define MC_MONGO_DEF_DB "admin" +#define MC_MIN_PORT 1 +#define MC_MAX_PORT 65535 +#define SUCCESS 0 +#define FAILURE -1 + +static char *mc_user = NULL; +static char *mc_password = NULL; +static char *mc_db = NULL; +static char *mc_host = NULL; +static int mc_port = MC_MONGO_DEF_PORT; + +static mongo_connection conn[1]; + +static const char *config_keys[] = { + "User", + "Password", + "Database", + "Host", + "Port" +}; + +static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); + +static void submit(const char *type, const char *instance, value_t *values, size_t values_len) { + INFO("Submiting [%d] for type [%s]",values_len,type); + value_list_t v = VALUE_LIST_INIT; + + v.values = values; + v.values_len = values_len; + + if( instance != NULL ) { + sstrncpy(v.type_instance,instance,sizeof(v.type_instance)); + } + + sstrncpy(v.host, hostname_g, sizeof(v.host)); + sstrncpy(v.plugin, MC_PLUGIN_NAME, sizeof(v.plugin)); + char port[12]; + sprintf(port, "%d",mc_port); + sstrncpy(v.plugin_instance, port, sizeof(v.plugin_instance)); + sstrncpy(v.type, type, sizeof(v.type)); + + plugin_dispatch_values(&v); +} + +static void submit_counter(const char *type, const char *instance, int64_t counter ) { + value_t v[1]; + v[0].counter = counter; + submit(type, instance, v, STATIC_ARRAY_SIZE (v)); +} + +static void submit_gauge(const char *type, const char *instance, gauge_t gauge ) { + value_t v[1]; + v[0].gauge = gauge; + submit(type, instance, v, STATIC_ARRAY_SIZE (v)); +} + + +static void handle_opcounters(bson* obj) { + INFO("handle op counters"); + bson_iterator it; + if(bson_find(&it, obj, "opcounters")) { + bson subobj; + bson_iterator_subobject(&it, &subobj); + bson_iterator it2; + bson_iterator_init(&it2, subobj.data); + + int64_t insert = 0; + int64_t query = 0; + int64_t delete = 0; + int64_t getmore = 0; + int64_t command = 0; + + while(bson_iterator_next(&it2)){ + if(strcmp(bson_iterator_key(&it2),"insert") == 0) { + insert = bson_iterator_long(&it2); + } + if(strcmp(bson_iterator_key(&it2),"query") == 0) { + query = bson_iterator_long(&it2); + } + if(strcmp(bson_iterator_key(&it2),"delete") == 0) { + delete = bson_iterator_long(&it2); + } + if(strcmp(bson_iterator_key(&it2),"getmore") == 0) { + getmore = bson_iterator_long(&it2); + } + if(strcmp(bson_iterator_key(&it2),"command") == 0) { + command = bson_iterator_long(&it2); + } + } + + bson_destroy(&subobj); + + submit_gauge("mongo_counter", "indert", insert ); + submit_gauge("mongo_counter", "query", query ); + submit_gauge("mongo_counter", "delete", delete ); + submit_gauge("mongo_counter", "getmore", getmore ); + submit_gauge("mongo_counter", "command", command ); + submit_gauge("mongo_counter", "insert", insert ); + } +} + +static void handle_mem(bson* obj) { + INFO("handle mem"); + bson_iterator it; + if(bson_find(&it, obj, "mem")) { + bson subobj; + bson_iterator_subobject(&it, &subobj); + bson_iterator it2; + bson_iterator_init(&it2, subobj.data); + int64_t resident = 0; + int64_t virtual = 0; + int64_t mapped = 0; + while(bson_iterator_next(&it2)) { + if(strcmp(bson_iterator_key(&it2),"resident") == 0) { + resident = bson_iterator_long(&it2); + } + if(strcmp(bson_iterator_key(&it2),"virtual") == 0) { + virtual = bson_iterator_long(&it2); + } + if(strcmp(bson_iterator_key(&it2),"mapped") == 0) { + mapped = bson_iterator_long(&it2); + } + } + value_t values[3]; + values[0].gauge = resident; + values[1].gauge = virtual; + values[2].gauge = mapped; + submit_gauge("memory", "resident", resident ); + submit_gauge("memory", "virtual", virtual ); + submit_gauge("memory", "mapped", mapped ); + bson_destroy(&subobj); + } +} + +static void handle_connections(bson* obj) { + INFO("handle connections"); + bson_iterator it; + if(bson_find(&it, obj, "connections")) { + bson subobj; + bson_iterator_subobject(&it, &subobj); + bson_iterator it2; + bson_iterator_init(&it2, subobj.data); + while(bson_iterator_next(&it2)) { + if(strcmp(bson_iterator_key(&it2),"current") == 0) { + submit_gauge("connections", "connections", bson_iterator_int(&it2)); + break; + } + } + bson_destroy(&subobj); + } +} + +static void handle_lock(bson* obj) { + INFO("handle lock"); + bson_iterator it; + if(bson_find(&it, obj, "globalLock")) { + bson subobj; + bson_iterator_subobject(&it, &subobj); + bson_iterator it2; + bson_iterator_init(&it2, subobj.data); + while(bson_iterator_next(&it2)) { + if(strcmp(bson_iterator_key(&it2),"ratio") == 0) { + submit_gauge("percent", "lock_ratio", bson_iterator_double(&it2)); + } + } + bson_destroy(&subobj); + } +} + +static void handle_index_counters(bson* obj) { + INFO("handle index counters"); + bson_iterator icit; + if(bson_find(&icit, obj, "indexCounters")) { + bson oic; + bson_iterator_subobject(&icit, &oic); + bson_iterator bit; + if(bson_find(&icit, &oic, "btree")) { + bson obt; + bson_iterator_subobject(&icit, &obt); + bson_iterator bit; + bson_iterator_init(&bit, oic.data); + int accesses; + int misses; + while(bson_iterator_next(&bit)) { + if(strcmp(bson_iterator_key(&bit),"accesses") == 0) { + accesses = bson_iterator_int(&bit); + } + if(strcmp(bson_iterator_key(&bit),"misses") == 0) { + misses = bson_iterator_int(&bit); + } + } + + double ratio = 0; + if( misses > 0 ) { + double ratio = accesses/misses; + } + submit_gauge("cache_ratio", "cache_misses", ratio ); + bson_destroy(&obt); + } + bson_destroy(&oic); + } +} + +static void handle_stats_counts(bson* obj) { + + INFO("handle stats counts"); + bson_iterator it; + bson_iterator_init(&it, obj->data); + int64_t collections = 0; + int64_t objects = 0; + int64_t numExtents = 0; + int64_t indexes = 0; + + while(bson_iterator_next(&it)) { + if(strcmp(bson_iterator_key(&it),"collections") == 0) { + collections = bson_iterator_long(&it); + } + if(strcmp(bson_iterator_key(&it),"objects") == 0) { + objects = bson_iterator_long(&it); + } + if(strcmp(bson_iterator_key(&it),"numExtents") == 0) { + numExtents = bson_iterator_long(&it); + } + if(strcmp(bson_iterator_key(&it),"indexes") == 0) { + indexes = bson_iterator_long(&it); + } + } + + submit_gauge("counter","object_count",objects); + + submit_gauge("counter", "collections",collections); + submit_gauge("counter", "num_extents",numExtents); + submit_gauge("counter", "indexes",indexes); +} + +static void handle_stats_sizes(bson* obj) { + bson_iterator it; + bson_iterator_init(&it, obj->data); + int64_t storageSize = 0; + int64_t dataSize = 0; + int64_t indexSize = 0; + while(bson_iterator_next(&it)) { + if(strcmp(bson_iterator_key(&it),"storageSize") == 0) { + storageSize = bson_iterator_long(&it); + } + if(strcmp(bson_iterator_key(&it),"dataSize") == 0) { + dataSize = bson_iterator_long(&it); + } + if(strcmp(bson_iterator_key(&it),"indexSize") == 0) { + indexSize = bson_iterator_long(&it); + } + } + + value_t values[3]; + submit_gauge("file_size", "storage",storageSize ); + submit_gauge("file_size", "index",indexSize ); + submit_gauge("file_size", "data",dataSize ); +} + +static int do_stats(void) { + bson obj; + + /* TODO: + + change this to raw runCommand + db.runCommand( { dbstats : 1 } ); + succeeds but is getting back all zeros !?! + modify bson_print to print type 18 + repro problem w/o db name - show dbs doesn't work again + why does db.admin.dbstats() work fine in shell? + implement retries ? noticed that if db is unavailable, collectd dies + */ + + if( !mongo_simple_int_command(conn, mc_db, "dbstats", 1, &obj) ) { + ERROR("Mongo: failed to call stats Host [%s] Port [%d] User [%s]", + mc_host, mc_port, mc_user); + return FAILURE; + } + + bson_print(&obj); + + handle_stats_sizes(&obj); + handle_stats_counts(&obj); + + + bson_destroy(&obj); + + return SUCCESS; +} + + +static int do_server_status(void) { + bson obj; + + if( !mongo_simple_int_command(conn, mc_db, "serverStatus", 1, &obj) ) { + ERROR("Mongo: failed to call serverStatus Host [%s] Port [%d] User [%s]", + mc_host, mc_port, mc_user); + return FAILURE; + } + + bson_print(&obj); + + handle_opcounters(&obj); + handle_mem(&obj); + handle_connections(&obj); + handle_index_counters(&obj); + handle_lock(&obj); + + bson_destroy(&obj); + return SUCCESS; +} + +static int mc_read(void) { + DEBUG("Mongo: mongo driver read"); + + if(do_server_status() != SUCCESS) { + ERROR("Mongo: do server status failed"); + return FAILURE; + } + + if(do_stats() != SUCCESS) { + ERROR("Mongo: do stats status failed"); + return FAILURE; + } + + return SUCCESS; +} + + +static void config_set(char** dest, const char* src ) { + if( *dest ) { + sfree(*dest); + } + *dest= malloc(strlen(src)+1); + sstrncpy(*dest,src,strlen(src)+1); +} + +static int mc_config(const char *key, const char *value) { + + DEBUG("Mongo: config key [%s] value [%s]", key, value); + if(strcasecmp("Host", key) == 0) { + config_set(&mc_host,value); + return SUCCESS; + } + + if(strcasecmp("Port", key) == 0) { + long l = strtol(value,NULL,10); + + if((errno == ERANGE && (l == LONG_MAX || l == LONG_MIN)) + || (errno != 0 && l == 0)) { + ERROR("Mongo: failed to parse Port value [%s]", value); + return FAILURE; + } + + if( l < MC_MIN_PORT || l > MC_MAX_PORT ) { + ERROR("Mongo: failed Port value [%s] outside range [1..65535]", value); + return FAILURE; + } + + mc_port = l; + return SUCCESS; + } + + if(strcasecmp("User", key) == 0) { + config_set(&mc_user,value); + return SUCCESS; + } + + if(strcasecmp("Password", key) == 0) { + config_set(&mc_password,value); + return SUCCESS; + } + + if(strcasecmp("Database", key) == 0) { + config_set(&mc_db,value); + return SUCCESS; + } + + return SUCCESS; +} + +static int mc_init(void) { + + DEBUG("mongo driver initializing"); + if( !mc_host) { + DEBUG("Mongo: Host not specified. Using default [%s]",MC_MONGO_DEF_HOST); + config_set(&mc_host, MC_MONGO_DEF_HOST); + } + + if( !mc_db) { + DEBUG("Mongo: Database not specified. Using default [%s]",MC_MONGO_DEF_DB); + config_set(&mc_db, MC_MONGO_DEF_DB); + } + + mongo_connection_options opts; + sstrncpy(opts.host, mc_host, sizeof(opts.host)); + opts.port = mc_port; + + if(mongo_connect( conn , &opts )){ + ERROR("Mongo: driver failed to connect. Host [%s] Port [%d] User [%s]", + mc_host, mc_port, mc_user); + return FAILURE; + } + + return SUCCESS; +} + +static int mc_shutdown(void) { + DEBUG("Mongo: driver shutting down"); + + if( conn ) { + mongo_disconnect(conn); + mongo_destroy(conn); + } + if( mc_user ) { + sfree(mc_user); + } + + if( mc_password ) { + sfree(mc_password); + } + + if( mc_db ) { + sfree(mc_db); + } + + if( mc_host ) { + sfree(mc_host); + } +} + + +void module_register(void) { + plugin_register_config(MC_PLUGIN_NAME, mc_config,config_keys,config_keys_num); + plugin_register_read(MC_PLUGIN_NAME, mc_read); + plugin_register_init(MC_PLUGIN_NAME, mc_init); + plugin_register_shutdown(MC_PLUGIN_NAME, mc_shutdown); + DEBUG("Mongo: driver registered"); +}