stats: Add log reporter

This reporter passes the measurement values to the logging subsystem
as DSTATS (which is currently DLGLOBAL) level INFO messages.

Sponsored-by: On-Waves ehf
diff --git a/src/stats.c b/src/stats.c
index f4c0b62..5027a62 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -68,6 +68,14 @@
 	const struct stat_item_group *statg,
 	const struct stat_item_desc *desc, int value);
 
+static int stats_reporter_log_send_counter(struct stats_reporter *srep,
+	const struct rate_ctr_group *ctrg,
+	const struct rate_ctr_desc *desc,
+	int64_t value, int64_t delta);
+static int stats_reporter_log_send_item(struct stats_reporter *srep,
+	const struct stat_item_group *statg,
+	const struct stat_item_desc *desc, int value);
+
 static int stats_reporter_send(struct stats_reporter *srep, const char *data,
 	int data_len);
 static int stats_reporter_send_buffer(struct stats_reporter *srep);
@@ -309,6 +317,61 @@
 	return rc;
 }
 
+/*** log reporter ***/
+
+struct stats_reporter *stats_reporter_create_log(const char *name)
+{
+	struct stats_reporter *srep;
+	srep = stats_reporter_alloc(STATS_REPORTER_LOG, name);
+
+	srep->have_net_config = 0;
+
+	srep->send_counter = stats_reporter_log_send_counter;
+	srep->send_item = stats_reporter_log_send_item;
+
+	return srep;
+}
+
+static int stats_reporter_log_send(struct stats_reporter *srep,
+	const char *type,
+	const char *name1, int index1, const char *name2, int value,
+	const char *unit)
+{
+	LOGP(DSTATS, LOGL_INFO,
+		"stats t=%s p=%s g=%s i=%d n=%s v=%d u=%s\n",
+		type, srep->name_prefix ? srep->name_prefix : "",
+		name1 ? name1 : "", index1,
+		name2, value, unit ? unit : "");
+
+	return 0;
+}
+
+
+static int stats_reporter_log_send_counter(struct stats_reporter *srep,
+	const struct rate_ctr_group *ctrg,
+	const struct rate_ctr_desc *desc,
+	int64_t value, int64_t delta)
+{
+	if (ctrg)
+		return stats_reporter_log_send(srep, "c",
+			ctrg->desc->group_name_prefix,
+			ctrg->idx,
+			desc->name, value, NULL);
+	else
+		return stats_reporter_log_send(srep, "c",
+			NULL, -1,
+			desc->name, value, NULL);
+}
+
+static int stats_reporter_log_send_item(struct stats_reporter *srep,
+	const struct stat_item_group *statg,
+	const struct stat_item_desc *desc, int value)
+{
+	return stats_reporter_log_send(srep, "i",
+		statg->desc->group_name_prefix, statg->idx,
+		desc->name, value, desc->unit);
+}
+
 /*** statsd reporter ***/
 
 struct stats_reporter *stats_reporter_create_statsd(const char *name)
diff --git a/src/vty/stats_vty.c b/src/vty/stats_vty.c
index 18ad283..839dc82 100644
--- a/src/vty/stats_vty.c
+++ b/src/vty/stats_vty.c
@@ -258,6 +258,47 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_stats_reporter_log, cfg_stats_reporter_log_cmd,
+	"stats reporter log",
+	CFG_STATS_STR CFG_REPORTER_STR "Report to the logger\n")
+{
+	struct stats_reporter *srep;
+
+	srep = stats_reporter_find(STATS_REPORTER_LOG, NULL);
+	if (!srep) {
+		srep = stats_reporter_create_log(NULL);
+		if (!srep) {
+			vty_out(vty, "%% Unable to create log reporter%s",
+				VTY_NEWLINE);
+			return CMD_WARNING;
+		}
+		/* TODO: if needed, add stats_add_reporter(srep); */
+	}
+
+	vty->index = srep;
+	vty->node = CFG_STATS_NODE;
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_no_stats_reporter_log, cfg_no_stats_reporter_log_cmd,
+	"no stats reporter log",
+	NO_STR CFG_STATS_STR CFG_REPORTER_STR "Report to the logger\n")
+{
+	struct stats_reporter *srep;
+
+	srep = stats_reporter_find(STATS_REPORTER_LOG, NULL);
+	if (!srep) {
+		vty_out(vty, "%% No log reporting active%s",
+			VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	stats_reporter_free(srep);
+
+	return CMD_SUCCESS;
+}
+
 DEFUN(show_stats,
       show_stats_cmd,
       "show stats",
@@ -277,6 +318,9 @@
 	case STATS_REPORTER_STATSD:
 		vty_out(vty, "stats reporter statsd%s", VTY_NEWLINE);
 		break;
+	case STATS_REPORTER_LOG:
+		vty_out(vty, "stats reporter log%s", VTY_NEWLINE);
+		break;
 	}
 
 	vty_out(vty, "  disable%s", VTY_NEWLINE);
@@ -312,8 +356,11 @@
 {
 	struct stats_reporter *srep;
 
+	/* TODO: loop through all reporters */
 	srep = stats_reporter_find(STATS_REPORTER_STATSD, NULL);
 	config_write_stats_reporter(vty, srep);
+	srep = stats_reporter_find(STATS_REPORTER_LOG, NULL);
+	config_write_stats_reporter(vty, srep);
 
 	vty_out(vty, "stats interval %d%s", stats_config->interval, VTY_NEWLINE);
 
@@ -326,6 +373,8 @@
 
 	install_element(CONFIG_NODE, &cfg_stats_reporter_statsd_cmd);
 	install_element(CONFIG_NODE, &cfg_no_stats_reporter_statsd_cmd);
+	install_element(CONFIG_NODE, &cfg_stats_reporter_log_cmd);
+	install_element(CONFIG_NODE, &cfg_no_stats_reporter_log_cmd);
 	install_element(CONFIG_NODE, &cfg_stats_interval_cmd);
 
 	install_node(&cfg_stats_node, config_write_stats);