aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/source/telemetry.md15
-rw-r--r--telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c124
-rw-r--r--telemetry/vpp-collectd/vpp/vpp.c138
3 files changed, 188 insertions, 89 deletions
diff --git a/docs/source/telemetry.md b/docs/source/telemetry.md
index 041c032b4..8887b8f1f 100644
--- a/docs/source/telemetry.md
+++ b/docs/source/telemetry.md
@@ -66,6 +66,11 @@ If you need the custom types that the two plugins define, they are present in
the type database for multi-value metrics
(see [CollectD protocol support in InfluxDB](https://docs.influxdata.com/influxdb/v1.7/supported_protocols/collectd/)).
+## Plugin options
+`vpp` and `vpp-hicn` have the same two options:
+- `Verbose` enables additional statistics. You can check the sources to have an exact list of available metrics.
+- `Tag` tags the data with the given string. Useful for identifying the context in which the data was retrieved in InfluxDB for instance. If the tag value is `None`, no tag is applied.
+
### Example: storing statistics from vpp and vpp-hicn
We'll use the rrdtool and csv plugins to store statistics from vpp and vpp-hicn.
@@ -113,6 +118,16 @@ LoadPlugin vpp_hicn
<Plugin rrdtool>
DataDir "/var/lib/collectd/rrd" # the folder where statistics are stored in rrd
</Plugin>
+
+<Plugin vpp>
+ Verbose true
+ Tag "None"
+</Plugin>
+
+<Plugin vpp_hicn>
+ Verbose true
+ Tag "None"
+</Plugin>
```
Run vpp and collectd:
diff --git a/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c b/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c
index b90646073..591b8f584 100644
--- a/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c
+++ b/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c
@@ -28,6 +28,7 @@
#endif /* DISABLE_ISOC99 */
#endif /* ! HAVE_CONFIG */
+/* Keep order as it is */
#include <config.h>
#include <collectd.h>
#include <common.h>
@@ -41,6 +42,15 @@
DEFINE_VAPI_MSG_IDS_HICN_API_JSON
vapi_ctx_t vapi_ctx;
+/************** OPTIONS ***********************************/
+static const char *config_keys[2] = {
+ "Verbose",
+ "Tag",
+};
+static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
+static bool verbose = false;
+static char *tag = NULL;
+
/************** DATA SOURCES ******************************/
static data_source_t packets_dsrc[1] = {
{"packets", DS_TYPE_GAUGE, 0, NAN},
@@ -184,8 +194,7 @@ static data_set_t dtx_ds = {
* value_list_t and pass it to plugin_dispatch_values.
*/
static int submit(const char *plugin_instance, const char *type,
- const char *type_instance, value_t *values, size_t values_len,
- cdtime_t *timestamp) {
+ value_t *values, size_t values_len, cdtime_t *timestamp) {
value_list_t vl = VALUE_LIST_INIT;
vl.values = values;
vl.values_len = values_len;
@@ -198,8 +207,8 @@ static int submit(const char *plugin_instance, const char *type,
sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance));
sstrncpy(vl.type, type, sizeof(vl.type));
- if (type_instance != NULL)
- sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
+ if (tag != NULL)
+ sstrncpy(vl.type_instance, tag, sizeof(vl.type_instance));
return plugin_dispatch_values(&vl);
}
@@ -209,6 +218,28 @@ static int submit(const char *plugin_instance, const char *type,
/**********************************************************/
/*
+ * This function is called for each configuration item.
+ */
+static int vpp_hicn_config(const char *key, const char *value) {
+ if (strcasecmp(key, "Verbose") == 0) {
+ verbose = IS_TRUE(value);
+ } else if (strcasecmp(key, "Tag") == 0) {
+ if (tag != NULL) {
+ free(tag);
+ tag = NULL;
+ }
+
+ if (strcasecmp(value, "None")) {
+ tag = strdup(value);
+ }
+ } else {
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
* Callback called by the hICN plugin API when node stats are ready.
*/
static vapi_error_e
@@ -226,36 +257,38 @@ parse_node_stats(vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv,
cdtime_t timestamp = cdtime();
values[0] = (value_t){.gauge = reply->pkts_processed};
- submit(node_name, pkts_processed_ds.type, NULL, values, 1, &timestamp);
+ submit(node_name, pkts_processed_ds.type, values, 1, &timestamp);
values[0] = (value_t){.gauge = reply->pkts_interest_count};
- submit(node_name, pkts_interest_count_ds.type, NULL, values, 1, &timestamp);
+ submit(node_name, pkts_interest_count_ds.type, values, 1, &timestamp);
values[0] = (value_t){.gauge = reply->pkts_data_count};
- submit(node_name, pkts_data_count_ds.type, NULL, values, 1, &timestamp);
- values[0] = (value_t){.gauge = reply->pkts_from_cache_count};
- submit(node_name, pkts_from_cache_count_ds.type, NULL, values, 1, &timestamp);
- values[0] = (value_t){.gauge = reply->pkts_no_pit_count};
- submit(node_name, pkts_no_pit_count_ds.type, NULL, values, 1, &timestamp);
- values[0] = (value_t){.gauge = reply->pit_expired_count};
- submit(node_name, pit_expired_count_ds.type, NULL, values, 1, &timestamp);
- values[0] = (value_t){.gauge = reply->cs_expired_count};
- submit(node_name, cs_expired_count_ds.type, NULL, values, 1, &timestamp);
- values[0] = (value_t){.gauge = reply->cs_lru_count};
- submit(node_name, cs_lru_count_ds.type, NULL, values, 1, &timestamp);
- values[0] = (value_t){.gauge = reply->pkts_drop_no_buf};
- submit(node_name, pkts_drop_no_buf_ds.type, NULL, values, 1, &timestamp);
- values[0] = (value_t){.gauge = reply->interests_aggregated};
- submit(node_name, interests_aggregated_ds.type, NULL, values, 1, &timestamp);
+ submit(node_name, pkts_data_count_ds.type, values, 1, &timestamp);
values[0] = (value_t){.gauge = reply->interests_retx};
- submit(node_name, interests_retx_ds.type, NULL, values, 1, &timestamp);
- values[0] = (value_t){.gauge = reply->interests_hash_collision};
- submit(node_name, interests_hash_collision_ds.type, NULL, values, 1,
- &timestamp);
+ submit(node_name, interests_retx_ds.type, values, 1, &timestamp);
values[0] = (value_t){.gauge = reply->pit_entries_count};
- submit(node_name, pit_entries_count_ds.type, NULL, values, 1, &timestamp);
+ submit(node_name, pit_entries_count_ds.type, values, 1, &timestamp);
values[0] = (value_t){.gauge = reply->cs_entries_count};
- submit(node_name, cs_entries_count_ds.type, NULL, values, 1, &timestamp);
- values[0] = (value_t){.gauge = reply->cs_entries_ntw_count};
- submit(node_name, cs_entries_ntw_count_ds.type, NULL, values, 1, &timestamp);
+ submit(node_name, cs_entries_count_ds.type, values, 1, &timestamp);
+
+ if (verbose) {
+ values[0] = (value_t){.gauge = reply->pkts_from_cache_count};
+ submit(node_name, pkts_from_cache_count_ds.type, values, 1, &timestamp);
+ values[0] = (value_t){.gauge = reply->interests_aggregated};
+ submit(node_name, interests_aggregated_ds.type, values, 1, &timestamp);
+ values[0] = (value_t){.gauge = reply->cs_expired_count};
+ submit(node_name, cs_expired_count_ds.type, values, 1, &timestamp);
+ values[0] = (value_t){.gauge = reply->cs_lru_count};
+ submit(node_name, cs_lru_count_ds.type, values, 1, &timestamp);
+ values[0] = (value_t){.gauge = reply->pit_expired_count};
+ submit(node_name, pit_expired_count_ds.type, values, 1, &timestamp);
+ values[0] = (value_t){.gauge = reply->pkts_no_pit_count};
+ submit(node_name, pkts_no_pit_count_ds.type, values, 1, &timestamp);
+ values[0] = (value_t){.gauge = reply->pkts_drop_no_buf};
+ submit(node_name, pkts_drop_no_buf_ds.type, values, 1, &timestamp);
+ values[0] = (value_t){.gauge = reply->interests_hash_collision};
+ submit(node_name, interests_hash_collision_ds.type, values, 1, &timestamp);
+ values[0] = (value_t){.gauge = reply->cs_entries_ntw_count};
+ submit(node_name, cs_entries_ntw_count_ds.type, values, 1, &timestamp);
+ }
return VAPI_OK;
}
@@ -280,16 +313,16 @@ parse_face_stats(vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv,
values[0] = (value_t){.derive = reply->irx_packets};
values[1] = (value_t){.derive = reply->irx_bytes};
- submit(face_name, irx_ds.type, NULL, values, 2, &timestamp);
+ submit(face_name, irx_ds.type, values, 2, &timestamp);
values[0] = (value_t){.derive = reply->itx_packets};
values[1] = (value_t){.derive = reply->itx_bytes};
- submit(face_name, itx_ds.type, NULL, values, 2, &timestamp);
+ submit(face_name, itx_ds.type, values, 2, &timestamp);
values[0] = (value_t){.derive = reply->drx_packets};
values[1] = (value_t){.derive = reply->drx_bytes};
- submit(face_name, drx_ds.type, NULL, values, 2, &timestamp);
+ submit(face_name, drx_ds.type, values, 2, &timestamp);
values[0] = (value_t){.derive = reply->dtx_packets};
values[1] = (value_t){.derive = reply->dtx_bytes};
- submit(face_name, dtx_ds.type, NULL, values, 2, &timestamp);
+ submit(face_name, dtx_ds.type, values, 2, &timestamp);
return VAPI_OK;
}
@@ -297,7 +330,7 @@ parse_face_stats(vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv,
/*
* This function is called once upon startup to initialize the plugin.
*/
-static int my_init(void) {
+static int vpp_hicn_init(void) {
int ret = vapi_connect_safe(&vapi_ctx, 0);
if (ret)
@@ -309,7 +342,7 @@ static int my_init(void) {
/*
* This function is called in regular intervalls to collect the data.
*/
-static int my_read(void) {
+static int vpp_hicn_read(void) {
int err = VAPI_OK;
vapi_lock();
@@ -365,7 +398,7 @@ END:
/*
* This function is called when plugin_log () has been used.
*/
-static void my_log(int severity, const char *msg, user_data_t *ud) {
+static void vpp_hicn_log(int severity, const char *msg, user_data_t *ud) {
printf("[LOG %i] %s\n", severity, msg);
return;
}
@@ -373,11 +406,18 @@ static void my_log(int severity, const char *msg, user_data_t *ud) {
/*
* This function is called before shutting down collectd.
*/
-static int my_shutdown(void) {
+static int vpp_hicn_shutdown(void) {
plugin_log(LOG_INFO, "vpp_hicn plugin: shutting down");
+
int ret = vapi_disconnect_safe();
plugin_log(LOG_INFO, "vpp_hicn plugin: disconnect vapi %s",
ret == 0 ? "ok" : "error");
+
+ if (tag != NULL) {
+ free(tag);
+ tag = NULL;
+ }
+
return ret;
}
@@ -408,9 +448,11 @@ void module_register(void) {
plugin_register_data_set(&cs_entries_count_ds);
plugin_register_data_set(&cs_entries_ntw_count_ds);
// callbacks
- plugin_register_log("vpp_hicn", my_log, /* user data */ NULL);
- plugin_register_init("vpp_hicn", my_init);
- plugin_register_read("vpp_hicn", my_read);
- plugin_register_shutdown("vpp_hicn", my_shutdown);
+ plugin_register_log("vpp_hicn", vpp_hicn_log, /* user data */ NULL);
+ plugin_register_config("vpp_hicn", vpp_hicn_config, config_keys,
+ config_keys_num);
+ plugin_register_init("vpp_hicn", vpp_hicn_init);
+ plugin_register_read("vpp_hicn", vpp_hicn_read);
+ plugin_register_shutdown("vpp_hicn", vpp_hicn_shutdown);
return;
}
diff --git a/telemetry/vpp-collectd/vpp/vpp.c b/telemetry/vpp-collectd/vpp/vpp.c
index 72c052212..0fec85dc8 100644
--- a/telemetry/vpp-collectd/vpp/vpp.c
+++ b/telemetry/vpp-collectd/vpp/vpp.c
@@ -28,6 +28,7 @@
#endif /* DISABLE_ISOC99 */
#endif /* ! HAVE_CONFIG */
+/* Keep order as it is */
#include <config.h>
#include <collectd.h>
#include <common.h>
@@ -38,6 +39,15 @@
#include <vppinfra/vec.h>
#undef counter_t
+/************** OPTIONS ***********************************/
+static const char *config_keys[2] = {
+ "Verbose",
+ "Tag",
+};
+static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
+static bool verbose = false;
+static char *tag = NULL;
+
/************** DATA SOURCES ******************************/
static data_source_t combined_dsrc[2] = {
{"packets", DS_TYPE_DERIVE, 0, NAN},
@@ -160,8 +170,7 @@ static data_set_t if_tx_broadcast_ds = {
* value_list_t and pass it to plugin_dispatch_values.
*/
static int submit(const char *plugin_instance, const char *type,
- const char *type_instance, value_t *values, size_t values_len,
- cdtime_t *timestamp) {
+ value_t *values, size_t values_len, cdtime_t *timestamp) {
value_list_t vl = VALUE_LIST_INIT;
vl.values = values;
vl.values_len = values_len;
@@ -174,8 +183,8 @@ static int submit(const char *plugin_instance, const char *type,
sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance));
sstrncpy(vl.type, type, sizeof(vl.type));
- if (type_instance != NULL)
- sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
+ if (tag != NULL)
+ sstrncpy(vl.type_instance, tag, sizeof(vl.type_instance));
return plugin_dispatch_values(&vl);
}
@@ -188,44 +197,50 @@ static int get_data_set(const char *stat_name, data_set_t *data_set_ptr) {
return 1;
}
- if (strcmp(stat_name, "/if/drops") == 0) {
- *data_set_ptr = if_drops_ds;
- } else if (strcmp(stat_name, "/if/punt") == 0) {
- *data_set_ptr = if_punt_ds;
+ if (strcmp(stat_name, "/if/rx") == 0) {
+ *data_set_ptr = if_rx_ds;
+ } else if (strcmp(stat_name, "/if/tx") == 0) {
+ *data_set_ptr = if_tx_ds;
} else if (strcmp(stat_name, "/if/ip4") == 0) {
*data_set_ptr = if_ip4_ds;
} else if (strcmp(stat_name, "/if/ip6") == 0) {
*data_set_ptr = if_ip6_ds;
- } else if (strcmp(stat_name, "/if/rx-no-buf") == 0) {
- *data_set_ptr = if_rx_no_buf_ds;
- } else if (strcmp(stat_name, "/if/rx-miss") == 0) {
- *data_set_ptr = if_rx_miss_ds;
- } else if (strcmp(stat_name, "/if/rx-error") == 0) {
- *data_set_ptr = if_rx_error_ds;
- } else if (strcmp(stat_name, "/if/tx-error") == 0) {
- *data_set_ptr = if_tx_error_ds;
- } else if (strcmp(stat_name, "/if/mpls") == 0) {
- *data_set_ptr = if_mpls_ds;
- } else if (strcmp(stat_name, "/if/rx") == 0) {
- *data_set_ptr = if_rx_ds;
- } else if (strcmp(stat_name, "/if/rx-unicast") == 0) {
- *data_set_ptr = if_rx_unicast_ds;
- } else if (strcmp(stat_name, "/if/rx-multicast") == 0) {
- *data_set_ptr = if_rx_multicast_ds;
- } else if (strcmp(stat_name, "/if/rx-broadcast") == 0) {
- *data_set_ptr = if_rx_broadcast_ds;
- } else if (strcmp(stat_name, "/if/tx") == 0) {
- *data_set_ptr = if_tx_ds;
- } else if (strcmp(stat_name, "/if/tx-unicast") == 0) {
- *data_set_ptr = if_tx_unicast_ds;
- } else if (strcmp(stat_name, "/if/tx-multicast") == 0) {
- *data_set_ptr = if_tx_multicast_ds;
- } else if (strcmp(stat_name, "/if/tx-broadcast") == 0) {
- *data_set_ptr = if_tx_broadcast_ds;
- } else {
+ } else if (strcmp(stat_name, "/if/drops") == 0) {
+ *data_set_ptr = if_drops_ds;
+ } else if (!verbose) {
return 1;
}
+ if (verbose) {
+ if (strcmp(stat_name, "/if/punt") == 0) {
+ *data_set_ptr = if_punt_ds;
+ } else if (strcmp(stat_name, "/if/mpls") == 0) {
+ *data_set_ptr = if_mpls_ds;
+ } else if (strcmp(stat_name, "/if/rx-no-buf") == 0) {
+ *data_set_ptr = if_rx_no_buf_ds;
+ } else if (strcmp(stat_name, "/if/rx-miss") == 0) {
+ *data_set_ptr = if_rx_miss_ds;
+ } else if (strcmp(stat_name, "/if/rx-error") == 0) {
+ *data_set_ptr = if_rx_error_ds;
+ } else if (strcmp(stat_name, "/if/rx-unicast") == 0) {
+ *data_set_ptr = if_rx_unicast_ds;
+ } else if (strcmp(stat_name, "/if/rx-multicast") == 0) {
+ *data_set_ptr = if_rx_multicast_ds;
+ } else if (strcmp(stat_name, "/if/rx-broadcast") == 0) {
+ *data_set_ptr = if_rx_broadcast_ds;
+ } else if (strcmp(stat_name, "/if/tx-error") == 0) {
+ *data_set_ptr = if_tx_error_ds;
+ } else if (strcmp(stat_name, "/if/tx-unicast") == 0) {
+ *data_set_ptr = if_tx_unicast_ds;
+ } else if (strcmp(stat_name, "/if/tx-multicast") == 0) {
+ *data_set_ptr = if_tx_multicast_ds;
+ } else if (strcmp(stat_name, "/if/tx-broadcast") == 0) {
+ *data_set_ptr = if_tx_broadcast_ds;
+ } else {
+ return 1;
+ }
+ }
+
return 0;
}
@@ -234,9 +249,31 @@ static int get_data_set(const char *stat_name, data_set_t *data_set_ptr) {
/**********************************************************/
/*
+ * This function is called for each configuration item.
+ */
+static int vpp_config(const char *key, const char *value) {
+ if (strcasecmp(key, "Verbose") == 0) {
+ verbose = IS_TRUE(value);
+ } else if (strcasecmp(key, "Tag") == 0) {
+ if (tag != NULL) {
+ free(tag);
+ tag = NULL;
+ }
+
+ if (strcasecmp(value, "None")) {
+ tag = strdup(value);
+ }
+ } else {
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
* This function is called once upon startup to initialize the plugin.
*/
-static int my_init(void) {
+static int vpp_init(void) {
u8 *stat_segment_name = (u8 *)STAT_SEGMENT_SOCKET_FILE;
int ret = stat_segment_connect((char *)stat_segment_name);
@@ -249,7 +286,7 @@ static int my_init(void) {
/*
* This function is called in regular intervalls to collect the data.
*/
-static int my_read(void) {
+static int vpp_read(void) {
uint8_t **patterns = {0};
char **interfaces = {0};
@@ -258,7 +295,6 @@ static int my_read(void) {
uint32_t *dir = stat_segment_ls(patterns);
stat_segment_data_t *res = stat_segment_dump(dir);
- plugin_log(LOG_INFO, "vpp plugin: performed ls and dump");
/* Read all available interfaces */
for (int k = 0; k < vec_len(res); k++) {
@@ -291,8 +327,7 @@ static int my_read(void) {
continue;
}
- err =
- submit(interfaces[j], data_set.type, NULL, values, 1, &timestamp);
+ err = submit(interfaces[j], data_set.type, values, 1, &timestamp);
if (err)
goto END;
@@ -314,8 +349,7 @@ static int my_read(void) {
continue;
}
- err =
- submit(interfaces[j], data_set.type, NULL, values, 2, &timestamp);
+ err = submit(interfaces[j], data_set.type, values, 2, &timestamp);
if (err)
goto END;
@@ -354,7 +388,7 @@ END:
/*
* This function is called when plugin_log () has been used.
*/
-static void my_log(int severity, const char *msg, user_data_t *ud) {
+static void vpp_log(int severity, const char *msg, user_data_t *ud) {
printf("[LOG %i] %s\n", severity, msg);
return;
}
@@ -362,9 +396,16 @@ static void my_log(int severity, const char *msg, user_data_t *ud) {
/*
* This function is called before shutting down collectd.
*/
-static int my_shutdown(void) {
+static int vpp_shutdown(void) {
plugin_log(LOG_INFO, "vpp plugin: shutting down");
+
+ if (tag != NULL) {
+ free(tag);
+ tag = NULL;
+ }
+
stat_segment_disconnect();
+
return 0;
}
@@ -390,9 +431,10 @@ void module_register(void) {
plugin_register_data_set(&if_tx_unicast_ds);
plugin_register_data_set(&if_tx_multicast_ds);
plugin_register_data_set(&if_tx_broadcast_ds);
- plugin_register_log("vpp", my_log, /* user data */ NULL);
- plugin_register_init("vpp", my_init);
- plugin_register_read("vpp", my_read);
- plugin_register_shutdown("vpp", my_shutdown);
+ plugin_register_log("vpp", vpp_log, /* user data */ NULL);
+ plugin_register_config("vpp", vpp_config, config_keys, config_keys_num);
+ plugin_register_init("vpp", vpp_init);
+ plugin_register_read("vpp", vpp_read);
+ plugin_register_shutdown("vpp", vpp_shutdown);
return;
}