| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2013, Digium, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * David M. Lee, II <dlee@digium.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software, distributed under the terms of | 
					
						
							|  |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2020-01-20 12:18:17 -05:00
										 |  |  |  * \brief Support for publishing to a StatsD server. | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \author David M. Lee, II <dlee@digium.com> | 
					
						
							|  |  |  |  * \since 12 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*** MODULEINFO
 | 
					
						
							|  |  |  | 	<support_level>extended</support_level> | 
					
						
							|  |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*** DOCUMENTATION
 | 
					
						
							|  |  |  | 	<configInfo name="res_statsd" language="en_US"> | 
					
						
							| 
									
										
										
										
											2020-01-20 12:18:17 -05:00
										 |  |  | 		<synopsis>StatsD client</synopsis> | 
					
						
							|  |  |  | 		<description> | 
					
						
							|  |  |  | 			<para>The <literal>res_statsd</literal> module provides an API that | 
					
						
							|  |  |  | 			allows Asterisk and its modules to send statistics to a StatsD | 
					
						
							|  |  |  | 			server. It only provides a means to communicate with a StatsD server | 
					
						
							|  |  |  | 			and does not send any metrics of its own.</para> | 
					
						
							|  |  |  | 			<para>An example module, <literal>res_chan_stats</literal>, is | 
					
						
							|  |  |  | 			provided which uses the API exposed by this module to send channel | 
					
						
							|  |  |  | 			statistics to the configured StatsD server.</para> | 
					
						
							|  |  |  | 			<para>More information about StatsD can be found at | 
					
						
							|  |  |  | 			https://github.com/statsd/statsd</para>
 | 
					
						
							|  |  |  | 		</description> | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 		<configFile name="statsd.conf"> | 
					
						
							|  |  |  | 			<configObject name="global"> | 
					
						
							|  |  |  | 				<synopsis>Global configuration settings</synopsis> | 
					
						
							|  |  |  | 				<configOption name="enabled"> | 
					
						
							| 
									
										
										
										
											2020-01-20 12:18:17 -05:00
										 |  |  | 					<synopsis>Enable/disable the StatsD module</synopsis> | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 				</configOption> | 
					
						
							|  |  |  | 				<configOption name="server"> | 
					
						
							| 
									
										
										
										
											2020-01-20 12:18:17 -05:00
										 |  |  | 					<synopsis>Address of the StatsD server</synopsis> | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 				</configOption> | 
					
						
							|  |  |  | 				<configOption name="prefix"> | 
					
						
							|  |  |  | 					<synopsis>Prefix to prepend to every metric</synopsis> | 
					
						
							|  |  |  | 				</configOption> | 
					
						
							|  |  |  | 				<configOption name="add_newline"> | 
					
						
							| 
									
										
										
										
											2020-01-20 12:18:17 -05:00
										 |  |  | 					<synopsis>Append a newline to every event. This is useful if | 
					
						
							|  |  |  | 					you want to fake out a server using netcat | 
					
						
							|  |  |  | 					(nc -lu 8125)</synopsis> | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 				</configOption> | 
					
						
							| 
									
										
										
										
											2021-07-08 14:34:27 +02:00
										 |  |  | 				<configOption name="meter_support"> | 
					
						
							|  |  |  | 					<synopsis>Enable/disable the non-standard StatsD Meter type, | 
					
						
							|  |  |  | 					if disabled falls back to counter and will append a "_meter" suffix to the metric name</synopsis> | 
					
						
							|  |  |  | 				</configOption> | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 			</configObject> | 
					
						
							|  |  |  | 		</configFile> | 
					
						
							|  |  |  | 	</configInfo> | 
					
						
							|  |  |  | ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "asterisk/config_options.h"
 | 
					
						
							|  |  |  | #include "asterisk/module.h"
 | 
					
						
							|  |  |  | #include "asterisk/netsock2.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define AST_API_MODULE
 | 
					
						
							|  |  |  | #include "asterisk/statsd.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define DEFAULT_STATSD_PORT 8125
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MAX_PREFIX 40
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! Socket for sending statd messages */ | 
					
						
							|  |  |  | static int socket_fd = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Global configuration options for statsd client. */ | 
					
						
							|  |  |  | struct conf_global_options { | 
					
						
							|  |  |  | 	/*! Enabled by default, disabled if false. */ | 
					
						
							|  |  |  | 	int enabled; | 
					
						
							|  |  |  | 	/*! Disabled by default, appends newlines to all messages when enabled. */ | 
					
						
							|  |  |  | 	int add_newline; | 
					
						
							|  |  |  | 	/*! Statsd server address[:port]. */ | 
					
						
							|  |  |  | 	struct ast_sockaddr statsd_server; | 
					
						
							|  |  |  | 	/*! Prefix to put on every stat. */ | 
					
						
							|  |  |  | 	char prefix[MAX_PREFIX + 1]; | 
					
						
							| 
									
										
										
										
											2021-07-08 14:34:27 +02:00
										 |  |  | 	/*! Enabled support for non-standard Meter type by default, falls back to counter if disabled */ | 
					
						
							|  |  |  | 	int meter_support; | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief All configuration options for statsd client. */ | 
					
						
							|  |  |  | struct conf { | 
					
						
							|  |  |  | 	/*! The general section configuration options. */ | 
					
						
							|  |  |  | 	struct conf_global_options *global; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Locking container for safe configuration access. */ | 
					
						
							|  |  |  | static AO2_GLOBAL_OBJ_STATIC(confs); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void conf_server(const struct conf *cfg, struct ast_sockaddr *addr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	*addr = cfg->global->statsd_server; | 
					
						
							|  |  |  | 	if (ast_sockaddr_port(addr) == 0) { | 
					
						
							|  |  |  | 		ast_sockaddr_set_port(addr, DEFAULT_STATSD_PORT); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-03 14:36:43 -06:00
										 |  |  | void AST_OPTIONAL_API_NAME(ast_statsd_log_string)(const char *metric_name, | 
					
						
							|  |  |  | 	const char *metric_type, const char *value, double sample_rate) | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-11-03 14:36:43 -06:00
										 |  |  | 	struct conf *cfg; | 
					
						
							|  |  |  | 	struct ast_str *msg; | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 	size_t len; | 
					
						
							|  |  |  | 	struct ast_sockaddr statsd_server; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (socket_fd == -1) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Rates <= 0.0 never get logged.
 | 
					
						
							|  |  |  | 	 * Rates >= 1.0 always get logged. | 
					
						
							|  |  |  | 	 * All others leave it to chance. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (sample_rate <= 0.0 || | 
					
						
							|  |  |  | 		(sample_rate < 1.0 && sample_rate < ast_random_double())) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cfg = ao2_global_obj_ref(confs); | 
					
						
							| 
									
										
										
										
											2015-11-03 14:36:43 -06:00
										 |  |  | 	conf_server(cfg, &statsd_server); | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	msg = ast_str_create(40); | 
					
						
							|  |  |  | 	if (!msg) { | 
					
						
							| 
									
										
										
										
											2015-11-03 14:36:43 -06:00
										 |  |  | 		ao2_cleanup(cfg); | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!ast_strlen_zero(cfg->global->prefix)) { | 
					
						
							|  |  |  | 		ast_str_append(&msg, 0, "%s.", cfg->global->prefix); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-08 14:34:27 +02:00
										 |  |  | 	if (!cfg->global->meter_support && strcmp(metric_type, AST_STATSD_METER)) { | 
					
						
							|  |  |  | 		ast_str_append(&msg, 0, "%s_meter:%s|%s", metric_name, value, AST_STATSD_COUNTER); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ast_str_append(&msg, 0, "%s:%s|%s", metric_name, value, metric_type); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (sample_rate < 1.0) { | 
					
						
							|  |  |  | 		ast_str_append(&msg, 0, "|@%.2f", sample_rate); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (cfg->global->add_newline) { | 
					
						
							|  |  |  | 		ast_str_append(&msg, 0, "\n"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	len = ast_str_strlen(msg); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-03 14:36:43 -06:00
										 |  |  | 	ast_debug(6, "Sending statistic %s to StatsD server\n", ast_str_buffer(msg)); | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 	ast_sendto(socket_fd, ast_str_buffer(msg), len, 0, &statsd_server); | 
					
						
							| 
									
										
										
										
											2015-11-03 14:36:43 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-18 10:05:07 -06:00
										 |  |  | 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); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | void AST_OPTIONAL_API_NAME(ast_statsd_log)(const char *metric_name, | 
					
						
							|  |  |  | 	const char *metric_type, intmax_t value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-11-03 14:36:43 -06:00
										 |  |  | 	char char_value[30]; | 
					
						
							|  |  |  | 	snprintf(char_value, sizeof(char_value), "%jd", value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_statsd_log_string(metric_name, metric_type, char_value, 1.0); | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AST_OPTIONAL_API_NAME(ast_statsd_log_sample)(const char *metric_name, | 
					
						
							|  |  |  | 	intmax_t value, double sample_rate) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-11-03 14:36:43 -06:00
										 |  |  | 	char char_value[30]; | 
					
						
							|  |  |  | 	snprintf(char_value, sizeof(char_value), "%jd", value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_statsd_log_string(metric_name, AST_STATSD_COUNTER, char_value, | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 		sample_rate); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-27 23:11:02 +00:00
										 |  |  | /*! \brief Mapping of the statsd conf struct's globals to the
 | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  |  *         general context in the config file. */ | 
					
						
							|  |  |  | static struct aco_type global_option = { | 
					
						
							|  |  |  | 	.type = ACO_GLOBAL, | 
					
						
							|  |  |  | 	.name = "global", | 
					
						
							|  |  |  | 	.item_offset = offsetof(struct conf, global), | 
					
						
							| 
									
										
										
										
											2017-12-12 13:55:12 -05:00
										 |  |  | 	.category = "general", | 
					
						
							|  |  |  | 	.category_match = ACO_WHITELIST_EXACT, | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct aco_type *global_options[] = ACO_TYPES(&global_option); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-27 23:11:02 +00:00
										 |  |  | /*! \brief Disposes of the statsd conf object */ | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | static void conf_destructor(void *obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct conf *cfg = obj; | 
					
						
							|  |  |  |     ao2_cleanup(cfg->global); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Creates the statis http conf object. */ | 
					
						
							|  |  |  | static void *conf_alloc(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct conf *cfg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!(cfg = ao2_alloc(sizeof(*cfg), conf_destructor))) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!(cfg->global = ao2_alloc(sizeof(*cfg->global), NULL))) { | 
					
						
							|  |  |  |         ao2_ref(cfg, -1); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return cfg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief The conf file that's processed for the module. */ | 
					
						
							|  |  |  | static struct aco_file conf_file = { | 
					
						
							|  |  |  | 	/*! The config file name. */ | 
					
						
							|  |  |  | 	.filename = "statsd.conf", | 
					
						
							|  |  |  | 	/*! The mapping object types to be processed. */ | 
					
						
							|  |  |  | 	.types = ACO_TYPES(&global_option), | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CONFIG_INFO_STANDARD(cfg_info, confs, conf_alloc, | 
					
						
							|  |  |  | 		     .files = ACO_FILES(&conf_file)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Helper function to check if module is enabled. */ | 
					
						
							|  |  |  | static char is_enabled(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	RAII_VAR(struct conf *, cfg, ao2_global_obj_ref(confs), ao2_cleanup); | 
					
						
							|  |  |  | 	return cfg->global->enabled; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int statsd_init(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	RAII_VAR(struct conf *, cfg, ao2_global_obj_ref(confs), ao2_cleanup); | 
					
						
							|  |  |  | 	char *server; | 
					
						
							|  |  |  | 	struct ast_sockaddr statsd_server; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_assert(is_enabled()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-20 12:18:17 -05:00
										 |  |  | 	ast_debug(3, "Configuring StatsD client.\n"); | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (socket_fd == -1) { | 
					
						
							| 
									
										
										
										
											2020-01-20 12:18:17 -05:00
										 |  |  | 		ast_debug(3, "Creating StatsD socket.\n"); | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 		socket_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | 
					
						
							|  |  |  | 		if (socket_fd == -1) { | 
					
						
							| 
									
										
										
										
											2020-01-20 12:18:17 -05:00
										 |  |  | 			perror("Error creating StatsD socket"); | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	conf_server(cfg, &statsd_server); | 
					
						
							|  |  |  | 	server = ast_sockaddr_stringify_fmt(&statsd_server, | 
					
						
							|  |  |  | 		AST_SOCKADDR_STR_DEFAULT); | 
					
						
							| 
									
										
										
										
											2020-01-20 12:18:17 -05:00
										 |  |  | 	ast_debug(3, "  StatsD server = %s.\n", server); | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 	ast_debug(3, "  add newline = %s\n", AST_YESNO(cfg->global->add_newline)); | 
					
						
							|  |  |  | 	ast_debug(3, "  prefix = %s\n", cfg->global->prefix); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void statsd_shutdown(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-20 12:18:17 -05:00
										 |  |  | 	ast_debug(3, "Shutting down StatsD client.\n"); | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 	if (socket_fd != -1) { | 
					
						
							|  |  |  | 		close(socket_fd); | 
					
						
							|  |  |  | 		socket_fd = -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-09 16:18:49 -05:00
										 |  |  | static int unload_module(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	statsd_shutdown(); | 
					
						
							|  |  |  | 	aco_info_destroy(&cfg_info); | 
					
						
							|  |  |  | 	ao2_global_obj_release(confs); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | static int load_module(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (aco_info_init(&cfg_info)) { | 
					
						
							|  |  |  | 		aco_info_destroy(&cfg_info); | 
					
						
							|  |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	aco_option_register(&cfg_info, "enabled", ACO_EXACT, global_options, | 
					
						
							|  |  |  | 		"no", OPT_BOOL_T, 1, | 
					
						
							|  |  |  | 		FLDSET(struct conf_global_options, enabled)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	aco_option_register(&cfg_info, "add_newline", ACO_EXACT, global_options, | 
					
						
							|  |  |  | 		"no", OPT_BOOL_T, 1, | 
					
						
							|  |  |  | 		FLDSET(struct conf_global_options, add_newline)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	aco_option_register(&cfg_info, "server", ACO_EXACT, global_options, | 
					
						
							|  |  |  | 		"127.0.0.1", OPT_SOCKADDR_T, 0, | 
					
						
							|  |  |  | 		FLDSET(struct conf_global_options, statsd_server)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	aco_option_register(&cfg_info, "prefix", ACO_EXACT, global_options, | 
					
						
							|  |  |  | 		"", OPT_CHAR_ARRAY_T, 0, | 
					
						
							|  |  |  | 		CHARFLDSET(struct conf_global_options, prefix)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-08 14:34:27 +02:00
										 |  |  | 	aco_option_register(&cfg_info, "meter_support", ACO_EXACT, global_options, | 
					
						
							|  |  |  | 		"yes", OPT_BOOL_T, 1, | 
					
						
							|  |  |  | 		FLDSET(struct conf_global_options, meter_support)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-02 13:29:59 -05:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!is_enabled()) { | 
					
						
							|  |  |  | 		return AST_MODULE_LOAD_SUCCESS; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-09 16:18:49 -05:00
										 |  |  | 	if (statsd_init()) { | 
					
						
							|  |  |  | 		unload_module(); | 
					
						
							| 
									
										
										
										
											2017-04-11 10:07:39 -06:00
										 |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return AST_MODULE_LOAD_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int reload_module(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-10-09 16:18:49 -05:00
										 |  |  | 	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: | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (is_enabled()) { | 
					
						
							| 
									
										
										
										
											2018-10-09 16:18:49 -05:00
										 |  |  | 		if (statsd_init()) { | 
					
						
							|  |  |  | 			return AST_MODULE_LOAD_DECLINE; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		statsd_shutdown(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-09 16:18:49 -05:00
										 |  |  | 	return AST_MODULE_LOAD_SUCCESS; | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-18 10:01:26 -05:00
										 |  |  | /* The priority of this module is set just after realtime, since it loads
 | 
					
						
							|  |  |  |  * configuration and could be used by any other sort of module. | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-01-20 12:18:17 -05:00
										 |  |  | AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "StatsD client support", | 
					
						
							| 
									
										
										
										
											2014-07-25 16:47:17 +00:00
										 |  |  | 	.support_level = AST_MODULE_SUPPORT_EXTENDED, | 
					
						
							| 
									
										
										
										
											2013-04-26 20:05:15 +00:00
										 |  |  | 	.load = load_module, | 
					
						
							|  |  |  | 	.unload = unload_module, | 
					
						
							|  |  |  | 	.reload = reload_module, | 
					
						
							| 
									
										
										
										
											2018-01-18 10:01:26 -05:00
										 |  |  | 	.load_pri = AST_MODPRI_REALTIME_DRIVER + 5, | 
					
						
							| 
									
										
										
										
											2015-05-05 20:49:04 -04:00
										 |  |  | ); |