Add sink.utils.counter
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Tue, 20 Jun 2017 19:40:17 +0000 (15:40 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 6 Jul 2017 21:26:38 +0000 (17:26 -0400)
A sink.utils.counter component counts the number of received
notifications (one count per notification type) and prints the counts
every 1000 notifications (total) by default and at the end. You can
use the `step` parameter to modify how frequent the component prints
the counts:

    babeltrace /path/to/trace -c sink.utils.counter -p step=5000

You can set `step` to 0 to print the counts only at the end:

    babeltrace /path/to/trace -c sink.utils.counter -p step=0

Notifications of which the type is not known (if this component is used
in future releases of Babeltrace 2) are classified under "Other
(unknown)", which is only printed if there's at least one unknown
notification.

You can use the `hide-zero` parameter (boolean) to hide the counts which
are 0.

The goal of this component class is to have a dummy sink component with
regular updates, for debugging and benchmarking purposes.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
configure.ac
plugins/text/plugin.c
plugins/utils/Makefile.am
plugins/utils/counter/Makefile.am [new file with mode: 0644]
plugins/utils/counter/counter.c [new file with mode: 0644]
plugins/utils/counter/counter.h [new file with mode: 0644]
plugins/utils/plugin.c

index 3a6eca9a3c14b2015a7f4e620c60ec1b1ee14382..f7503d5cef46f96a437acb0269fe3ce77d29351c 100644 (file)
@@ -523,6 +523,7 @@ AC_CONFIG_FILES([
        plugins/text/pretty/Makefile
        plugins/utils/Makefile
        plugins/utils/dummy/Makefile
+       plugins/utils/counter/Makefile
        plugins/utils/trimmer/Makefile
        plugins/utils/muxer/Makefile
        python-plugin-provider/Makefile
index 563c8d77ad860f49620cebccf0dce34c90dbe89f..302c079f1b6efdb79009cb00980c0026294e20ce 100644 (file)
@@ -39,4 +39,4 @@ BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(pretty, pretty_finalize);
 BT_PLUGIN_SINK_COMPONENT_CLASS_PORT_CONNECTED_METHOD(pretty,
        pretty_port_connected);
 BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(pretty,
-       "Pretty-printing text output (`text` format of Babeltrace 1).");
+       "Pretty-print notifications (`text` format of Babeltrace 1).");
index decee2c51454783dba0700bf4df81aac92648f3f..e0b3094f9dcf520c68d6aa433b758cd9584d0e92 100644 (file)
@@ -1,6 +1,6 @@
 AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/plugins
 
-SUBDIRS = dummy trimmer muxer .
+SUBDIRS = dummy counter trimmer muxer .
 
 plugindir = "$(PLUGINSDIR)"
 plugin_LTLIBRARIES = babeltrace-plugin-utils.la
@@ -11,6 +11,7 @@ babeltrace_plugin_utils_la_LDFLAGS = \
        -avoid-version -module
 babeltrace_plugin_utils_la_LIBADD = \
        dummy/libbabeltrace-plugin-dummy-cc.la \
+       counter/libbabeltrace-plugin-counter-cc.la \
        trimmer/libbabeltrace-plugin-trimmer.la \
        muxer/libbabeltrace-plugin-muxer.la
 
diff --git a/plugins/utils/counter/Makefile.am b/plugins/utils/counter/Makefile.am
new file mode 100644 (file)
index 0000000..d46bafe
--- /dev/null
@@ -0,0 +1,4 @@
+AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/plugins
+
+noinst_LTLIBRARIES = libbabeltrace-plugin-counter-cc.la
+libbabeltrace_plugin_counter_cc_la_SOURCES = counter.c counter.h
diff --git a/plugins/utils/counter/counter.c b/plugins/utils/counter/counter.c
new file mode 100644 (file)
index 0000000..a1c1cd4
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/plugin/plugin-dev.h>
+#include <babeltrace/graph/connection.h>
+#include <babeltrace/graph/component.h>
+#include <babeltrace/graph/private-component.h>
+#include <babeltrace/graph/private-component-sink.h>
+#include <babeltrace/graph/private-port.h>
+#include <babeltrace/graph/port.h>
+#include <babeltrace/graph/private-connection.h>
+#include <babeltrace/graph/component-sink.h>
+#include <babeltrace/graph/notification-iterator.h>
+#include <babeltrace/graph/notification.h>
+#include <babeltrace/graph/notification-discarded-events.h>
+#include <babeltrace/graph/notification-discarded-packets.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/common-internal.h>
+#include <babeltrace/values.h>
+#include <plugins-common.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <stdint.h>
+
+#include "counter.h"
+
+#define PRINTF_COUNT(_what_sing, _what_plur, _var, args...)            \
+       do {                                                            \
+               if (counter->count._var != 0 || !counter->hide_zero) {  \
+                       printf("%15" PRIu64 " %s\n",                    \
+                               counter->count._var,                    \
+                               counter->count._var == 1 ? _what_sing : _what_plur); \
+               }                                                       \
+       } while (0)
+
+static
+uint64_t get_total_count(struct counter *counter)
+{
+       return counter->count.event +
+               counter->count.stream_begin +
+               counter->count.stream_end +
+               counter->count.packet_begin +
+               counter->count.packet_end +
+               counter->count.inactivity +
+               counter->count.discarded_events +
+               counter->count.discarded_packets +
+               counter->count.other;
+}
+
+static
+void print_count(struct counter *counter, uint64_t total)
+{
+       PRINTF_COUNT("event", "events", event);
+       PRINTF_COUNT("stream beginning", "stream beginnings", stream_begin);
+       PRINTF_COUNT("stream end", "stream ends", stream_end);
+       PRINTF_COUNT("packet beginning", "packet beginnings", packet_begin);
+       PRINTF_COUNT("packet end", "packet ends", packet_end);
+       PRINTF_COUNT("inactivity", "inactivities", inactivity);
+       PRINTF_COUNT("discarded events notification",
+               "discarded events notifications", discarded_events_notifs);
+       PRINTF_COUNT("  known discarded event", "  known discarded events",
+               discarded_events);
+       PRINTF_COUNT("discarded packets notification",
+               "discarded packets notifications", discarded_packets_notifs);
+       PRINTF_COUNT("  known discarded packet", "  known discarded packets",
+               discarded_packets);
+
+       if (counter->count.other > 0) {
+               PRINTF_COUNT("  other (unknown) notification",
+                       "  other (unknown) notifications", other);
+       }
+
+       printf("%s%15" PRIu64 " notification%s (TOTAL)%s\n",
+               bt_common_color_bold(), total, total == 1 ? "" : "s",
+               bt_common_color_reset());
+       counter->last_printed_total = total;
+}
+
+static
+void try_print_count(struct counter *counter)
+{
+       uint64_t total;
+
+       if (counter->step == 0) {
+               /* No update */
+               return;
+       }
+
+       total = get_total_count(counter);
+
+       if (total % counter->step == 0) {
+               print_count(counter, total);
+               putchar('\n');
+       }
+}
+
+static
+void try_print_last(struct counter *counter)
+{
+       const uint64_t total = get_total_count(counter);
+
+       if (total != counter->last_printed_total) {
+               print_count(counter, total);
+       }
+}
+
+void destroy_private_counter_data(struct counter *counter)
+{
+       bt_put(counter->notif_iter);
+       g_free(counter);
+}
+
+void counter_finalize(struct bt_private_component *component)
+{
+       struct counter *counter;
+
+       assert(component);
+       counter = bt_private_component_get_user_data(component);
+       assert(counter);
+       try_print_last(counter);
+       bt_put(counter->notif_iter);
+       g_free(counter);
+}
+
+enum bt_component_status counter_init(struct bt_private_component *component,
+               struct bt_value *params, UNUSED_VAR void *init_method_data)
+{
+       enum bt_component_status ret;
+       struct counter *counter = g_new0(struct counter, 1);
+       struct bt_value *step = NULL;
+       struct bt_value *hide_zero = NULL;
+
+       if (!counter) {
+               ret = BT_COMPONENT_STATUS_NOMEM;
+               goto end;
+       }
+
+       ret = bt_private_component_sink_add_input_private_port(component,
+               "in", NULL, NULL);
+       if (ret != BT_COMPONENT_STATUS_OK) {
+               goto end;
+       }
+
+       counter->last_printed_total = -1ULL;
+       counter->step = 1000;
+       step = bt_value_map_get(params, "step");
+       if (bt_value_is_integer(step)) {
+               int64_t val;
+               int vret = bt_value_integer_get(step, &val);
+
+               assert(vret == 0);
+
+               if (val >= 0) {
+                       counter->step = (uint64_t) val;
+               }
+       }
+
+       hide_zero = bt_value_map_get(params, "hide-zero");
+       if (bt_value_is_bool(hide_zero)) {
+               bt_bool val;
+               int vret = bt_value_bool_get(hide_zero, &val);
+
+               assert(vret == 0);
+               counter->hide_zero = (bool) val;
+       }
+
+       ret = bt_private_component_set_user_data(component, counter);
+       if (ret != BT_COMPONENT_STATUS_OK) {
+               goto error;
+       }
+
+       goto end;
+
+error:
+       destroy_private_counter_data(counter);
+
+end:
+       bt_put(step);
+       bt_put(hide_zero);
+       return ret;
+}
+
+void counter_port_connected(
+               struct bt_private_component *component,
+               struct bt_private_port *self_port,
+               struct bt_port *other_port)
+{
+       struct counter *counter;
+       struct bt_notification_iterator *iterator;
+       struct bt_private_connection *connection;
+       enum bt_connection_status conn_status;
+
+       counter = bt_private_component_get_user_data(component);
+       assert(counter);
+       connection = bt_private_port_get_private_connection(self_port);
+       assert(connection);
+       conn_status = bt_private_connection_create_notification_iterator(
+               connection, NULL, &iterator);
+       if (conn_status != BT_CONNECTION_STATUS_OK) {
+               counter->error = true;
+               goto end;
+       }
+
+       BT_MOVE(counter->notif_iter, iterator);
+
+end:
+       bt_put(connection);
+}
+
+enum bt_component_status counter_consume(struct bt_private_component *component)
+{
+       enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+       struct bt_notification *notif = NULL;
+       struct counter *counter;
+       enum bt_notification_iterator_status it_ret;
+       int64_t count;
+
+       counter = bt_private_component_get_user_data(component);
+       assert(counter);
+
+       if (unlikely(counter->error)) {
+               ret = BT_COMPONENT_STATUS_ERROR;
+               goto end;
+       }
+
+       if (unlikely(!counter->notif_iter)) {
+               try_print_last(counter);
+               ret = BT_COMPONENT_STATUS_END;
+               goto end;
+       }
+
+       /* Consume one notification  */
+       it_ret = bt_notification_iterator_next(counter->notif_iter);
+       if (it_ret < 0) {
+               ret = BT_COMPONENT_STATUS_ERROR;
+               goto end;
+       }
+
+       switch (it_ret) {
+       case BT_NOTIFICATION_ITERATOR_STATUS_AGAIN:
+               ret = BT_COMPONENT_STATUS_AGAIN;
+               goto end;
+       case BT_NOTIFICATION_ITERATOR_STATUS_END:
+               try_print_last(counter);
+               ret = BT_COMPONENT_STATUS_END;
+               goto end;
+       case BT_NOTIFICATION_ITERATOR_STATUS_OK:
+       {
+               struct bt_notification *notif =
+                       bt_notification_iterator_get_notification(counter->notif_iter);
+
+               assert(notif);
+               switch (bt_notification_get_type(notif)) {
+               case BT_NOTIFICATION_TYPE_EVENT:
+                       counter->count.event++;
+                       break;
+               case BT_NOTIFICATION_TYPE_INACTIVITY:
+                       counter->count.inactivity++;
+                       break;
+               case BT_NOTIFICATION_TYPE_STREAM_BEGIN:
+                       counter->count.stream_begin++;
+                       break;
+               case BT_NOTIFICATION_TYPE_STREAM_END:
+                       counter->count.stream_end++;
+                       break;
+               case BT_NOTIFICATION_TYPE_PACKET_BEGIN:
+                       counter->count.packet_begin++;
+                       break;
+               case BT_NOTIFICATION_TYPE_PACKET_END:
+                       counter->count.packet_end++;
+                       break;
+               case BT_NOTIFICATION_TYPE_DISCARDED_EVENTS:
+                       counter->count.discarded_events_notifs++;
+                       count = bt_notification_discarded_events_get_count(
+                               notif);
+                       if (count >= 0) {
+                               counter->count.discarded_events += count;
+                       }
+                       break;
+               case BT_NOTIFICATION_TYPE_DISCARDED_PACKETS:
+                       counter->count.discarded_packets_notifs++;
+                       count = bt_notification_discarded_packets_get_count(
+                               notif);
+                       if (count >= 0) {
+                               counter->count.discarded_packets += count;
+                       }
+                       break;
+               default:
+                       counter->count.other++;
+               }
+
+               bt_put(notif);
+       }
+       default:
+               break;
+       }
+
+       try_print_count(counter);
+
+end:
+       bt_put(notif);
+       return ret;
+}
diff --git a/plugins/utils/counter/counter.h b/plugins/utils/counter/counter.h
new file mode 100644 (file)
index 0000000..33dda03
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef BABELTRACE_PLUGINS_UTILS_COUNTER_H
+#define BABELTRACE_PLUGINS_UTILS_COUNTER_H
+
+/*
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <glib.h>
+#include <babeltrace/graph/private-component.h>
+#include <babeltrace/graph/private-port.h>
+#include <babeltrace/graph/port.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+struct counter {
+       struct bt_notification_iterator *notif_iter;
+       struct {
+               uint64_t event;
+               uint64_t stream_begin;
+               uint64_t stream_end;
+               uint64_t packet_begin;
+               uint64_t packet_end;
+               uint64_t inactivity;
+               uint64_t discarded_events_notifs;
+               uint64_t discarded_events;
+               uint64_t discarded_packets_notifs;
+               uint64_t discarded_packets;
+               uint64_t other;
+       } count;
+       uint64_t last_printed_total;
+       uint64_t step;
+       bool hide_zero;
+       bool error;
+};
+
+enum bt_component_status counter_init(struct bt_private_component *component,
+               struct bt_value *params, void *init_method_data);
+void counter_finalize(struct bt_private_component *component);
+void counter_port_connected(struct bt_private_component *component,
+               struct bt_private_port *self_port,
+               struct bt_port *other_port);
+enum bt_component_status counter_consume(struct bt_private_component *component);
+
+#endif /* BABELTRACE_PLUGINS_UTILS_COUNTER_H */
index c5ed25a3731b83e733e9559b46fff3c0e298a266..be39891b4afd796f723bb93a84a16d47c432763d 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <babeltrace/plugin/plugin-dev.h>
 #include "dummy/dummy.h"
+#include "counter/counter.h"
 #include "trimmer/trimmer.h"
 #include "trimmer/iterator.h"
 #include "muxer/muxer.h"
@@ -35,7 +36,7 @@ BT_PLUGIN_DESCRIPTION("Graph utilities");
 BT_PLUGIN_AUTHOR("Julien Desfossez, Jérémie Galarneau, Philippe Proulx");
 BT_PLUGIN_LICENSE("MIT");
 
-/* dummy sink */
+/* sink.utils.dummy */
 BT_PLUGIN_SINK_COMPONENT_CLASS(dummy, dummy_consume);
 BT_PLUGIN_SINK_COMPONENT_CLASS_INIT_METHOD(dummy, dummy_init);
 BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(dummy, dummy_finalize);
@@ -44,7 +45,16 @@ BT_PLUGIN_SINK_COMPONENT_CLASS_PORT_CONNECTED_METHOD(dummy,
 BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(dummy,
        "Consume notifications and discard them.");
 
-/* trimmer filter */
+/* sink.utils.counter */
+BT_PLUGIN_SINK_COMPONENT_CLASS(counter, counter_consume);
+BT_PLUGIN_SINK_COMPONENT_CLASS_INIT_METHOD(counter, counter_init);
+BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(counter, counter_finalize);
+BT_PLUGIN_SINK_COMPONENT_CLASS_PORT_CONNECTED_METHOD(counter,
+       counter_port_connected);
+BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(counter,
+       "Count notifications and print the results.");
+
+/* flt.utils.trimmer */
 BT_PLUGIN_FILTER_COMPONENT_CLASS(trimmer, trimmer_iterator_next);
 BT_PLUGIN_FILTER_COMPONENT_CLASS_DESCRIPTION(trimmer,
        "Keep notifications that occur within a specific time range.");
@@ -57,7 +67,7 @@ BT_PLUGIN_FILTER_COMPONENT_CLASS_NOTIFICATION_ITERATOR_FINALIZE_METHOD(trimmer,
 BT_PLUGIN_FILTER_COMPONENT_CLASS_NOTIFICATION_ITERATOR_SEEK_TIME_METHOD(trimmer,
        trimmer_iterator_seek_time);
 
-/* muxer filter */
+/* flt.utils.muxer */
 BT_PLUGIN_FILTER_COMPONENT_CLASS(muxer, muxer_notif_iter_next);
 BT_PLUGIN_FILTER_COMPONENT_CLASS_DESCRIPTION(muxer,
        "Sort notifications from multiple input ports to a single output port by time.");
This page took 0.031279 seconds and 4 git commands to generate.