diff --git a/include/osmocom/core/stats.h b/include/osmocom/core/stats.h index 39eae088a..96f687e52 100644 --- a/include/osmocom/core/stats.h +++ b/include/osmocom/core/stats.h @@ -38,8 +38,8 @@ enum osmo_stats_class { }; enum osmo_stats_reporter_type { - OSMO_STATS_REPORTER_STATSD, OSMO_STATS_REPORTER_LOG, + OSMO_STATS_REPORTER_STATSD, }; struct osmo_stats_reporter { @@ -96,9 +96,6 @@ struct osmo_stats_reporter *osmo_stats_reporter_alloc(enum osmo_stats_reporter_t const char *name); void osmo_stats_reporter_free(struct osmo_stats_reporter *srep); -struct osmo_stats_reporter *osmo_stats_reporter_create_statsd(const char *name); -struct osmo_stats_reporter *osmo_stats_reporter_create_log(const char *name); - struct osmo_stats_reporter *osmo_stats_reporter_find(enum osmo_stats_reporter_type type, const char *name); @@ -111,3 +108,14 @@ int osmo_stats_reporter_set_max_class(struct osmo_stats_reporter *srep, int osmo_stats_reporter_set_name_prefix(struct osmo_stats_reporter *srep, const char *prefix); int osmo_stats_reporter_enable(struct osmo_stats_reporter *srep); int osmo_stats_reporter_disable(struct osmo_stats_reporter *srep); + +/* reporter creation */ +struct osmo_stats_reporter *osmo_stats_reporter_create_log(const char *name); +struct osmo_stats_reporter *osmo_stats_reporter_create_statsd(const char *name); + +/* helper functions for reporter implementations */ +int osmo_stats_reporter_send(struct osmo_stats_reporter *srep, const char *data, + int data_len); +int osmo_stats_reporter_send_buffer(struct osmo_stats_reporter *srep); +int osmo_stats_reporter_udp_open(struct osmo_stats_reporter *srep); +int osmo_stats_reporter_udp_close(struct osmo_stats_reporter *srep); diff --git a/src/Makefile.am b/src/Makefile.am index 7aa6a78a1..00b97d084 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,7 +15,7 @@ libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c bits.c \ gsmtap_util.c crc16.c panic.c backtrace.c \ conv.c application.c rbtree.c strrb.c \ loggingrb.c crc8gen.c crc16gen.c crc32gen.c crc64gen.c \ - macaddr.c stat_item.c stats.c + macaddr.c stat_item.c stats.c stats_statsd.c BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c diff --git a/src/stats.c b/src/stats.c index 16e2971d3..55479109b 100644 --- a/src/stats.c +++ b/src/stats.c @@ -42,7 +42,7 @@ #include #define STATS_DEFAULT_INTERVAL 5 /* secs */ -#define STATS_DEFAULT_STATSD_BUFLEN 256 +#define STATS_DEFAULT_BUFLEN 256 static LLIST_HEAD(osmo_stats_reporter_list); static void *osmo_stats_ctx = NULL; @@ -56,16 +56,6 @@ struct osmo_stats_config *osmo_stats_config = &s_stats_config; static struct osmo_timer_list osmo_stats_timer; -static int osmo_stats_reporter_statsd_open(struct osmo_stats_reporter *srep); -static int osmo_stats_reporter_statsd_close(struct osmo_stats_reporter *srep); -static int osmo_stats_reporter_statsd_send_counter(struct osmo_stats_reporter *srep, - const struct rate_ctr_group *ctrg, - const struct rate_ctr_desc *desc, - int64_t value, int64_t delta); -static int osmo_stats_reporter_statsd_send_item(struct osmo_stats_reporter *srep, - const struct osmo_stat_item_group *statg, - const struct osmo_stat_item_desc *desc, int value); - static int osmo_stats_reporter_log_send_counter(struct osmo_stats_reporter *srep, const struct rate_ctr_group *ctrg, const struct rate_ctr_desc *desc, @@ -74,10 +64,6 @@ static int osmo_stats_reporter_log_send_item(struct osmo_stats_reporter *srep, const struct osmo_stat_item_group *statg, const struct osmo_stat_item_desc *desc, int value); -static int osmo_stats_reporter_send(struct osmo_stats_reporter *srep, const char *data, - int data_len); -static int osmo_stats_reporter_send_buffer(struct osmo_stats_reporter *srep); - static int update_srep_config(struct osmo_stats_reporter *srep) { int rc = 0; @@ -300,7 +286,7 @@ int osmo_stats_reporter_disable(struct osmo_stats_reporter *srep) return update_srep_config(srep); } -static int osmo_stats_reporter_send(struct osmo_stats_reporter *srep, const char *data, +int osmo_stats_reporter_send(struct osmo_stats_reporter *srep, const char *data, int data_len) { int rc; @@ -314,7 +300,7 @@ static int osmo_stats_reporter_send(struct osmo_stats_reporter *srep, const char return rc; } -static int osmo_stats_reporter_send_buffer(struct osmo_stats_reporter *srep) +int osmo_stats_reporter_send_buffer(struct osmo_stats_reporter *srep) { int rc; @@ -394,31 +380,16 @@ static int osmo_stats_reporter_log_send_item(struct osmo_stats_reporter *srep, desc->name, value, desc->unit); } -/*** statsd reporter ***/ +/*** i/o helper functions ***/ -struct osmo_stats_reporter *osmo_stats_reporter_create_statsd(const char *name) -{ - struct osmo_stats_reporter *srep; - srep = osmo_stats_reporter_alloc(OSMO_STATS_REPORTER_STATSD, name); - - srep->have_net_config = 1; - - srep->open = osmo_stats_reporter_statsd_open; - srep->close = osmo_stats_reporter_statsd_close; - srep->send_counter = osmo_stats_reporter_statsd_send_counter; - srep->send_item = osmo_stats_reporter_statsd_send_item; - - return srep; -} - -static int osmo_stats_reporter_statsd_open(struct osmo_stats_reporter *srep) +int osmo_stats_reporter_udp_open(struct osmo_stats_reporter *srep) { int sock; int rc; - int buffer_size = STATS_DEFAULT_STATSD_BUFLEN; + int buffer_size = STATS_DEFAULT_BUFLEN; - if (srep->fd != -1) - osmo_stats_reporter_statsd_close(srep); + if (srep->fd != -1 && srep->close) + srep->close(srep); sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock == -1) @@ -448,7 +419,7 @@ failed: return rc; } -static int osmo_stats_reporter_statsd_close(struct osmo_stats_reporter *srep) +int osmo_stats_reporter_udp_close(struct osmo_stats_reporter *srep) { int rc; if (srep->fd == -1) @@ -463,107 +434,6 @@ static int osmo_stats_reporter_statsd_close(struct osmo_stats_reporter *srep) return rc == -1 ? -errno : 0; } -static int osmo_stats_reporter_statsd_send(struct osmo_stats_reporter *srep, - const char *name1, unsigned int index1, const char *name2, int value, - const char *unit) -{ - char *buf; - int buf_size; - int nchars, rc = 0; - char *fmt = NULL; - char *prefix = srep->name_prefix; - int old_len = msgb_length(srep->buffer); - - if (prefix) { - if (name1) { - if (index1 != 0) - fmt = "%1$s.%2$s.%6$u.%3$s:%4$d|%5$s"; - else - fmt = "%1$s.%2$s.%3$s:%4$d|%5$s"; - } else { - fmt = "%1$s.%2$0.0s%3$s:%4$d|%5$s"; - } - } else { - prefix = ""; - if (name1) { - if (index1 != 0) - fmt = "%1$s%2$s.%6$u.%3$s:%4$d|%5$s"; - else - fmt = "%1$s%2$s.%3$s:%4$d|%5$s"; - } else { - fmt = "%1$s%2$0.0s%3$s:%4$d|%5$s"; - } - } - - if (srep->agg_enabled) { - if (msgb_length(srep->buffer) > 0 && - msgb_tailroom(srep->buffer) > 0) - { - msgb_put_u8(srep->buffer, '\n'); - } - } - - buf = (char *)msgb_put(srep->buffer, 0); - buf_size = msgb_tailroom(srep->buffer); - - nchars = snprintf(buf, buf_size, fmt, - prefix, name1, name2, - value, unit, index1); - - if (nchars >= buf_size) { - /* Truncated */ - /* Restore original buffer (without trailing LF) */ - msgb_trim(srep->buffer, old_len); - /* Send it */ - rc = osmo_stats_reporter_send_buffer(srep); - - /* Try again */ - buf = (char *)msgb_put(srep->buffer, 0); - buf_size = msgb_tailroom(srep->buffer); - - nchars = snprintf(buf, buf_size, fmt, - prefix, name1, name2, - value, unit, index1); - - if (nchars >= buf_size) - return -EMSGSIZE; - } - - if (nchars > 0) - msgb_trim(srep->buffer, msgb_length(srep->buffer) + nchars); - - if (!srep->agg_enabled) - rc = osmo_stats_reporter_send_buffer(srep); - - return rc; -} - -static int osmo_stats_reporter_statsd_send_counter(struct osmo_stats_reporter *srep, - const struct rate_ctr_group *ctrg, - const struct rate_ctr_desc *desc, - int64_t value, int64_t delta) -{ - if (ctrg) - return osmo_stats_reporter_statsd_send(srep, - ctrg->desc->group_name_prefix, - ctrg->idx, - desc->name, delta, "c"); - else - return osmo_stats_reporter_statsd_send(srep, - NULL, 0, - desc->name, delta, "c"); -} - -static int osmo_stats_reporter_statsd_send_item(struct osmo_stats_reporter *srep, - const struct osmo_stat_item_group *statg, - const struct osmo_stat_item_desc *desc, int value) -{ - return osmo_stats_reporter_statsd_send(srep, - statg->desc->group_name_prefix, - statg->idx, - desc->name, value, desc->unit); -} - /*** generic rate counter support ***/ static int osmo_stats_reporter_send_counter(struct osmo_stats_reporter *srep, diff --git a/src/stats_statsd.c b/src/stats_statsd.c new file mode 100644 index 000000000..c76f8f696 --- /dev/null +++ b/src/stats_statsd.c @@ -0,0 +1,158 @@ +/* + * (C) 2015 by Sysmocom s.f.m.c. GmbH + * + * Author: Jacob Erlbeck + * + * All Rights Reserved + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +static int osmo_stats_reporter_statsd_send_counter(struct osmo_stats_reporter *srep, + const struct rate_ctr_group *ctrg, + const struct rate_ctr_desc *desc, + int64_t value, int64_t delta); +static int osmo_stats_reporter_statsd_send_item(struct osmo_stats_reporter *srep, + const struct osmo_stat_item_group *statg, + const struct osmo_stat_item_desc *desc, int value); + +struct osmo_stats_reporter *osmo_stats_reporter_create_statsd(const char *name) +{ + struct osmo_stats_reporter *srep; + srep = osmo_stats_reporter_alloc(OSMO_STATS_REPORTER_STATSD, name); + + srep->have_net_config = 1; + + srep->open = osmo_stats_reporter_udp_open; + srep->close = osmo_stats_reporter_udp_close; + srep->send_counter = osmo_stats_reporter_statsd_send_counter; + srep->send_item = osmo_stats_reporter_statsd_send_item; + + return srep; +} + +static int osmo_stats_reporter_statsd_send(struct osmo_stats_reporter *srep, + const char *name1, unsigned int index1, const char *name2, int value, + const char *unit) +{ + char *buf; + int buf_size; + int nchars, rc = 0; + char *fmt = NULL; + char *prefix = srep->name_prefix; + int old_len = msgb_length(srep->buffer); + + if (prefix) { + if (name1) { + if (index1 != 0) + fmt = "%1$s.%2$s.%6$u.%3$s:%4$d|%5$s"; + else + fmt = "%1$s.%2$s.%3$s:%4$d|%5$s"; + } else { + fmt = "%1$s.%2$0.0s%3$s:%4$d|%5$s"; + } + } else { + prefix = ""; + if (name1) { + if (index1 != 0) + fmt = "%1$s%2$s.%6$u.%3$s:%4$d|%5$s"; + else + fmt = "%1$s%2$s.%3$s:%4$d|%5$s"; + } else { + fmt = "%1$s%2$0.0s%3$s:%4$d|%5$s"; + } + } + + if (srep->agg_enabled) { + if (msgb_length(srep->buffer) > 0 && + msgb_tailroom(srep->buffer) > 0) + { + msgb_put_u8(srep->buffer, '\n'); + } + } + + buf = (char *)msgb_put(srep->buffer, 0); + buf_size = msgb_tailroom(srep->buffer); + + nchars = snprintf(buf, buf_size, fmt, + prefix, name1, name2, + value, unit, index1); + + if (nchars >= buf_size) { + /* Truncated */ + /* Restore original buffer (without trailing LF) */ + msgb_trim(srep->buffer, old_len); + /* Send it */ + rc = osmo_stats_reporter_send_buffer(srep); + + /* Try again */ + buf = (char *)msgb_put(srep->buffer, 0); + buf_size = msgb_tailroom(srep->buffer); + + nchars = snprintf(buf, buf_size, fmt, + prefix, name1, name2, + value, unit, index1); + + if (nchars >= buf_size) + return -EMSGSIZE; + } + + if (nchars > 0) + msgb_trim(srep->buffer, msgb_length(srep->buffer) + nchars); + + if (!srep->agg_enabled) + rc = osmo_stats_reporter_send_buffer(srep); + + return rc; +} + +static int osmo_stats_reporter_statsd_send_counter(struct osmo_stats_reporter *srep, + const struct rate_ctr_group *ctrg, + const struct rate_ctr_desc *desc, + int64_t value, int64_t delta) +{ + if (ctrg) + return osmo_stats_reporter_statsd_send(srep, + ctrg->desc->group_name_prefix, + ctrg->idx, + desc->name, delta, "c"); + else + return osmo_stats_reporter_statsd_send(srep, + NULL, 0, + desc->name, delta, "c"); +} + +static int osmo_stats_reporter_statsd_send_item(struct osmo_stats_reporter *srep, + const struct osmo_stat_item_group *statg, + const struct osmo_stat_item_desc *desc, int value) +{ + return osmo_stats_reporter_statsd_send(srep, + statg->desc->group_name_prefix, + statg->idx, + desc->name, value, desc->unit); +}