build: Update config.guess and config.sub
[asterisk/asterisk.git] / res / res_statsd.c
index 65ca786..01a1fd8 100644 (file)
@@ -52,8 +52,6 @@
 
 #include "asterisk.h"
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
 #include "asterisk/config_options.h"
 #include "asterisk/module.h"
 #include "asterisk/netsock2.h"
@@ -97,11 +95,11 @@ static void conf_server(const struct conf *cfg, struct ast_sockaddr *addr)
        }
 }
 
-void AST_OPTIONAL_API_NAME(ast_statsd_log_full)(const char *metric_name,
-       const char *metric_type, intmax_t value, double sample_rate)
+void AST_OPTIONAL_API_NAME(ast_statsd_log_string)(const char *metric_name,
+       const char *metric_type, const char *value, double sample_rate)
 {
-       RAII_VAR(struct conf *, cfg, NULL, ao2_cleanup);
-       RAII_VAR(struct ast_str *, msg, NULL, ast_free);
+       struct conf *cfg;
+       struct ast_str *msg;
        size_t len;
        struct ast_sockaddr statsd_server;
 
@@ -109,9 +107,6 @@ void AST_OPTIONAL_API_NAME(ast_statsd_log_full)(const char *metric_name,
                return;
        }
 
-       cfg = ao2_global_obj_ref(confs);
-       conf_server(cfg, &statsd_server);
-
        /* Rates <= 0.0 never get logged.
         * Rates >= 1.0 always get logged.
         * All others leave it to chance.
@@ -122,9 +117,11 @@ void AST_OPTIONAL_API_NAME(ast_statsd_log_full)(const char *metric_name,
        }
 
        cfg = ao2_global_obj_ref(confs);
+       conf_server(cfg, &statsd_server);
 
        msg = ast_str_create(40);
        if (!msg) {
+               ao2_cleanup(cfg);
                return;
        }
 
@@ -132,7 +129,7 @@ void AST_OPTIONAL_API_NAME(ast_statsd_log_full)(const char *metric_name,
                ast_str_append(&msg, 0, "%s.", cfg->global->prefix);
        }
 
-       ast_str_append(&msg, 0, "%s:%jd|%s", metric_name, value, metric_type);
+       ast_str_append(&msg, 0, "%s:%s|%s", metric_name, value, metric_type);
 
        if (sample_rate < 1.0) {
                ast_str_append(&msg, 0, "|@%.2f", sample_rate);
@@ -144,20 +141,87 @@ void AST_OPTIONAL_API_NAME(ast_statsd_log_full)(const char *metric_name,
 
        len = ast_str_strlen(msg);
 
-       ast_debug(6, "send: %s\n", ast_str_buffer(msg));
+       ast_debug(6, "Sending statistic %s to StatsD server\n", ast_str_buffer(msg));
        ast_sendto(socket_fd, ast_str_buffer(msg), len, 0, &statsd_server);
+
+       ao2_cleanup(cfg);
+       ast_free(msg);
+}
+
+void AST_OPTIONAL_API_NAME(ast_statsd_log_full)(const char *metric_name,
+       const char *metric_type, intmax_t value, double sample_rate)
+{
+       char char_value[30];
+       snprintf(char_value, sizeof(char_value), "%jd", value);
+
+       ast_statsd_log_string(metric_name, metric_type, char_value, sample_rate);
+
+}
+
+AST_THREADSTORAGE(statsd_buf);
+
+void AST_OPTIONAL_API_NAME(ast_statsd_log_string_va)(const char *metric_name,
+       const char *metric_type, const char *value, double sample_rate, ...)
+{
+       struct ast_str *buf;
+       va_list ap;
+       int res;
+
+       buf = ast_str_thread_get(&statsd_buf, 128);
+       if (!buf) {
+               return;
+       }
+
+       va_start(ap, sample_rate);
+       res = ast_str_set_va(&buf, 0, metric_name, ap);
+       va_end(ap);
+
+       if (res == AST_DYNSTR_BUILD_FAILED) {
+               return;
+       }
+
+       ast_statsd_log_string(ast_str_buffer(buf), metric_type, value, sample_rate);
+}
+
+void AST_OPTIONAL_API_NAME(ast_statsd_log_full_va)(const char *metric_name,
+       const char *metric_type, intmax_t value, double sample_rate, ...)
+{
+       struct ast_str *buf;
+       va_list ap;
+       int res;
+
+       buf = ast_str_thread_get(&statsd_buf, 128);
+       if (!buf) {
+               return;
+       }
+
+       va_start(ap, sample_rate);
+       res = ast_str_set_va(&buf, 0, metric_name, ap);
+       va_end(ap);
+
+       if (res == AST_DYNSTR_BUILD_FAILED) {
+               return;
+       }
+
+       ast_statsd_log_full(ast_str_buffer(buf), metric_type, value, sample_rate);
 }
 
 void AST_OPTIONAL_API_NAME(ast_statsd_log)(const char *metric_name,
        const char *metric_type, intmax_t value)
 {
-       ast_statsd_log_full(metric_name, metric_type, value, 1.0);
+       char char_value[30];
+       snprintf(char_value, sizeof(char_value), "%jd", value);
+
+       ast_statsd_log_string(metric_name, metric_type, char_value, 1.0);
 }
 
 void AST_OPTIONAL_API_NAME(ast_statsd_log_sample)(const char *metric_name,
        intmax_t value, double sample_rate)
 {
-       ast_statsd_log_full(metric_name, AST_STATSD_COUNTER, value,
+       char char_value[30];
+       snprintf(char_value, sizeof(char_value), "%jd", value);
+
+       ast_statsd_log_string(metric_name, AST_STATSD_COUNTER, char_value,
                sample_rate);
 }
 
@@ -167,8 +231,8 @@ static struct aco_type global_option = {
        .type = ACO_GLOBAL,
        .name = "global",
        .item_offset = offsetof(struct conf, global),
-       .category = "^general$",
-       .category_match = ACO_WHITELIST
+       .category = "general",
+       .category_match = ACO_WHITELIST_EXACT,
 };
 
 static struct aco_type *global_options[] = ACO_TYPES(&global_option);
@@ -252,6 +316,14 @@ static void statsd_shutdown(void)
        }
 }
 
+static int unload_module(void)
+{
+       statsd_shutdown();
+       aco_info_destroy(&cfg_info);
+       ao2_global_obj_release(confs);
+       return 0;
+}
+
 static int load_module(void)
 {
        if (aco_info_init(&cfg_info)) {
@@ -275,50 +347,68 @@ static int load_module(void)
                "", OPT_CHAR_ARRAY_T, 0,
                CHARFLDSET(struct conf_global_options, prefix));
 
-       if (aco_process_config(&cfg_info, 0)) {
-               aco_info_destroy(&cfg_info);
-               return AST_MODULE_LOAD_DECLINE;
+       if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
+               struct conf *cfg;
+
+               ast_log(LOG_NOTICE, "Could not load statsd config; using defaults\n");
+               cfg = conf_alloc();
+               if (!cfg) {
+                       aco_info_destroy(&cfg_info);
+                       return AST_MODULE_LOAD_DECLINE;
+               }
+
+               if (aco_set_defaults(&global_option, "general", cfg->global)) {
+                       ast_log(LOG_ERROR, "Failed to initialize statsd defaults.\n");
+                       ao2_ref(cfg, -1);
+                       aco_info_destroy(&cfg_info);
+                       return AST_MODULE_LOAD_DECLINE;
+               }
+
+               ao2_global_obj_replace_unref(confs, cfg);
+               ao2_ref(cfg, -1);
        }
 
        if (!is_enabled()) {
                return AST_MODULE_LOAD_SUCCESS;
        }
 
-       if (statsd_init() != 0) {
-               return AST_MODULE_LOAD_FAILURE;
+       if (statsd_init()) {
+               unload_module();
+               return AST_MODULE_LOAD_DECLINE;
        }
 
        return AST_MODULE_LOAD_SUCCESS;
 }
 
-static int unload_module(void)
-{
-       statsd_shutdown();
-       aco_info_destroy(&cfg_info);
-       ao2_global_obj_release(confs);
-       return 0;
-}
-
 static int reload_module(void)
 {
-       if (aco_process_config(&cfg_info, 1)) {
+       switch (aco_process_config(&cfg_info, 1)) {
+       case ACO_PROCESS_OK:
+               break;
+       case ACO_PROCESS_UNCHANGED:
+               return AST_MODULE_LOAD_SUCCESS;
+       case ACO_PROCESS_ERROR:
+       default:
                return AST_MODULE_LOAD_DECLINE;
        }
 
        if (is_enabled()) {
-               return statsd_init();
+               if (statsd_init()) {
+                       return AST_MODULE_LOAD_DECLINE;
+               }
        } else {
                statsd_shutdown();
-               return AST_MODULE_LOAD_SUCCESS;
        }
+       return AST_MODULE_LOAD_SUCCESS;
 }
 
-/* The priority of this module is set to be as low as possible, since it could
- * be used by any other sort of module.
+/* The priority of this module is set just after realtime, since it loads
+ * configuration and could be used by any other sort of module.
  */
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Statsd client support",
+       .support_level = AST_MODULE_SUPPORT_EXTENDED,
        .load = load_module,
        .unload = unload_module,
        .reload = reload_module,
-       .load_pri = 0,
-       );
+       .load_pri = AST_MODPRI_REALTIME_DRIVER + 5,
+);