libosmocore/src/stats_statsd.c

174 lines
4.5 KiB
C

/*
* (C) 2015 by Sysmocom s.f.m.c. GmbH
*
* Author: Jacob Erlbeck <jerlbeck@sysmocom.de>
*
* 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 "config.h"
#if !defined(EMBEDDED)
#include <osmocom/core/stats.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/logging.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/stat_item.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/stats.h>
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, int64_t 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, int64_t 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, int64_t value)
{
const char *unit = desc->unit;
if (unit == OSMO_STAT_ITEM_NO_UNIT) {
unit = "g";
if (value < 0)
osmo_stats_reporter_statsd_send(srep,
statg->desc->group_name_prefix,
statg->idx,
desc->name, 0, unit);
}
return osmo_stats_reporter_statsd_send(srep,
statg->desc->group_name_prefix,
statg->idx,
desc->name, value, unit);
}
#endif /* !EMBEDDED */