diff options
-rw-r--r-- | docs/source/telemetry.md | 15 | ||||
-rw-r--r-- | telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c | 124 | ||||
-rw-r--r-- | telemetry/vpp-collectd/vpp/vpp.c | 138 |
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, ×tamp); + submit(node_name, pkts_processed_ds.type, values, 1, ×tamp); values[0] = (value_t){.gauge = reply->pkts_interest_count}; - submit(node_name, pkts_interest_count_ds.type, NULL, values, 1, ×tamp); + submit(node_name, pkts_interest_count_ds.type, values, 1, ×tamp); values[0] = (value_t){.gauge = reply->pkts_data_count}; - submit(node_name, pkts_data_count_ds.type, NULL, values, 1, ×tamp); - values[0] = (value_t){.gauge = reply->pkts_from_cache_count}; - submit(node_name, pkts_from_cache_count_ds.type, NULL, values, 1, ×tamp); - values[0] = (value_t){.gauge = reply->pkts_no_pit_count}; - submit(node_name, pkts_no_pit_count_ds.type, NULL, values, 1, ×tamp); - values[0] = (value_t){.gauge = reply->pit_expired_count}; - submit(node_name, pit_expired_count_ds.type, NULL, values, 1, ×tamp); - values[0] = (value_t){.gauge = reply->cs_expired_count}; - submit(node_name, cs_expired_count_ds.type, NULL, values, 1, ×tamp); - values[0] = (value_t){.gauge = reply->cs_lru_count}; - submit(node_name, cs_lru_count_ds.type, NULL, values, 1, ×tamp); - values[0] = (value_t){.gauge = reply->pkts_drop_no_buf}; - submit(node_name, pkts_drop_no_buf_ds.type, NULL, values, 1, ×tamp); - values[0] = (value_t){.gauge = reply->interests_aggregated}; - submit(node_name, interests_aggregated_ds.type, NULL, values, 1, ×tamp); + submit(node_name, pkts_data_count_ds.type, values, 1, ×tamp); values[0] = (value_t){.gauge = reply->interests_retx}; - submit(node_name, interests_retx_ds.type, NULL, values, 1, ×tamp); - values[0] = (value_t){.gauge = reply->interests_hash_collision}; - submit(node_name, interests_hash_collision_ds.type, NULL, values, 1, - ×tamp); + submit(node_name, interests_retx_ds.type, values, 1, ×tamp); values[0] = (value_t){.gauge = reply->pit_entries_count}; - submit(node_name, pit_entries_count_ds.type, NULL, values, 1, ×tamp); + submit(node_name, pit_entries_count_ds.type, values, 1, ×tamp); values[0] = (value_t){.gauge = reply->cs_entries_count}; - submit(node_name, cs_entries_count_ds.type, NULL, values, 1, ×tamp); - values[0] = (value_t){.gauge = reply->cs_entries_ntw_count}; - submit(node_name, cs_entries_ntw_count_ds.type, NULL, values, 1, ×tamp); + submit(node_name, cs_entries_count_ds.type, values, 1, ×tamp); + + if (verbose) { + values[0] = (value_t){.gauge = reply->pkts_from_cache_count}; + submit(node_name, pkts_from_cache_count_ds.type, values, 1, ×tamp); + values[0] = (value_t){.gauge = reply->interests_aggregated}; + submit(node_name, interests_aggregated_ds.type, values, 1, ×tamp); + values[0] = (value_t){.gauge = reply->cs_expired_count}; + submit(node_name, cs_expired_count_ds.type, values, 1, ×tamp); + values[0] = (value_t){.gauge = reply->cs_lru_count}; + submit(node_name, cs_lru_count_ds.type, values, 1, ×tamp); + values[0] = (value_t){.gauge = reply->pit_expired_count}; + submit(node_name, pit_expired_count_ds.type, values, 1, ×tamp); + values[0] = (value_t){.gauge = reply->pkts_no_pit_count}; + submit(node_name, pkts_no_pit_count_ds.type, values, 1, ×tamp); + values[0] = (value_t){.gauge = reply->pkts_drop_no_buf}; + submit(node_name, pkts_drop_no_buf_ds.type, values, 1, ×tamp); + values[0] = (value_t){.gauge = reply->interests_hash_collision}; + submit(node_name, interests_hash_collision_ds.type, values, 1, ×tamp); + values[0] = (value_t){.gauge = reply->cs_entries_ntw_count}; + submit(node_name, cs_entries_ntw_count_ds.type, values, 1, ×tamp); + } 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, ×tamp); + submit(face_name, irx_ds.type, values, 2, ×tamp); 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, ×tamp); + submit(face_name, itx_ds.type, values, 2, ×tamp); 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, ×tamp); + submit(face_name, drx_ds.type, values, 2, ×tamp); 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, ×tamp); + submit(face_name, dtx_ds.type, values, 2, ×tamp); 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, ×tamp); + err = submit(interfaces[j], data_set.type, values, 1, ×tamp); if (err) goto END; @@ -314,8 +349,7 @@ static int my_read(void) { continue; } - err = - submit(interfaces[j], data_set.type, NULL, values, 2, ×tamp); + err = submit(interfaces[j], data_set.type, values, 2, ×tamp); 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; } |