]> granicus.if.org Git - sysstat/commitdiff
sadf: PCP: Add support for A_NET_DEV and A_NET_EDEV activities
authorSebastien GODARD <sysstat@users.noreply.github.com>
Sat, 23 Mar 2019 10:58:25 +0000 (11:58 +0100)
committerSebastien GODARD <sysstat@users.noreply.github.com>
Sat, 23 Mar 2019 10:58:25 +0000 (11:58 +0100)
Add metrics displayed by "sar -n DEV" and "sar -n EDEV" (network
interfaces statistics) to PCP archive.

Signed-off-by: Sebastien GODARD <sysstat@users.noreply.github.com>
activity.c
pcp_def_metrics.c
pcp_def_metrics.h
pcp_stats.c
pcp_stats.h
sadf.c
sadf_misc.c

index 4f4c854380c3f9f589f06838d2977e5e0a72f372..6187bfebf834fc7f875ed706980218e0acbfefb1 100644 (file)
@@ -599,6 +599,7 @@ struct activity net_dev_act = {
        .f_json_print   = json_print_net_dev_stats,
        .f_svg_print    = svg_print_net_dev_stats,
        .f_raw_print    = raw_print_net_dev_stats,
+       .f_pcp_print    = pcp_print_net_dev_stats,
        .f_count_new    = count_new_net_dev,
        .item_list      = NULL,
        .desc           = "Network interfaces statistics",
@@ -645,6 +646,7 @@ struct activity net_edev_act = {
        .f_json_print   = json_print_net_edev_stats,
        .f_svg_print    = svg_print_net_edev_stats,
        .f_raw_print    = raw_print_net_edev_stats,
+       .f_pcp_print    = pcp_print_net_edev_stats,
        .f_count_new    = count_new_net_edev,
        .item_list      = NULL,
        .desc           = "Network interfaces errors statistics",
index 99350cfed9e2044e0b1b6a3c91ed4a6d5ca5bc43..86bb05378ef8fed6ffbb59be402323029f57bffb 100644 (file)
@@ -446,3 +446,103 @@ void pcp_def_queue_metrics(void)
 #endif /* HAVE_PCP */
 }
 
+/*
+ ***************************************************************************
+ * Define PCP metrics for network interfaces (errors) statistics.
+ *
+ * IN:
+ * @a          Activity structure with statistics.
+ ***************************************************************************
+ */
+void pcp_def_net_dev_metrics(struct activity *a)
+{
+#ifdef HAVE_PCP
+       int inst = 0;
+       static pmInDom indom = PM_INDOM_NULL;
+       struct sa_item *list = a->item_list;
+
+       if (indom == PM_INDOM_NULL) {
+               /* Create domain */
+               indom = pmInDom_build(0, 2);
+
+               /* Create instances */
+               while (list != NULL) {
+                       pmiAddInstance(indom, list->item_name, inst++);
+                       list = list->next;
+               }
+       }
+
+       if (a->id == A_NET_DEV) {
+               /* Creating metrics for A_NET_DEV */
+               pmiAddMetric("network.interface.in.packets",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(0, -1, 1, 0, PM_TIME_SEC, PM_COUNT_ONE));
+
+               pmiAddMetric("network.interface.out.packets",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(0, -1, 1, 0, PM_TIME_SEC, PM_COUNT_ONE));
+
+               pmiAddMetric("network.interface.in.bytes",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(1, -1, 0, PM_SPACE_KBYTE, PM_TIME_SEC, 0));
+
+               pmiAddMetric("network.interface.out.bytes",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(1, -1, 0, PM_SPACE_KBYTE, PM_TIME_SEC, 0));
+
+               pmiAddMetric("network.interface.in.compressed",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(0, -1, 1, 0, PM_TIME_SEC, PM_COUNT_ONE));
+
+               pmiAddMetric("network.interface.out.compressed",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(0, -1, 1, 0, PM_TIME_SEC, PM_COUNT_ONE));
+
+               pmiAddMetric("network.interface.in.multicast",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(0, -1, 1, 0, PM_TIME_SEC, PM_COUNT_ONE));
+
+               pmiAddMetric("network.interface.util",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(0, 0, 0, 0, 0, 0));
+       }
+       else {
+               /* Creating metrics for A_NET_EDEV */
+               pmiAddMetric("network.interface.in.errors",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(0, -1, 1, 0, PM_TIME_SEC, PM_COUNT_ONE));
+
+               pmiAddMetric("network.interface.out.errors",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(0, -1, 1, 0, PM_TIME_SEC, PM_COUNT_ONE));
+
+               pmiAddMetric("network.interface.out.collisions",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(0, -1, 1, 0, PM_TIME_SEC, PM_COUNT_ONE));
+
+               pmiAddMetric("network.interface.in.drops",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(0, -1, 1, 0, PM_TIME_SEC, PM_COUNT_ONE));
+
+               pmiAddMetric("network.interface.out.drops",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(0, -1, 1, 0, PM_TIME_SEC, PM_COUNT_ONE));
+
+               pmiAddMetric("network.interface.out.carrier",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(0, -1, 1, 0, PM_TIME_SEC, PM_COUNT_ONE));
+
+               pmiAddMetric("network.interface.in.frame",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(0, -1, 1, 0, PM_TIME_SEC, PM_COUNT_ONE));
+
+               pmiAddMetric("network.interface.in.fifo",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(0, -1, 1, 0, PM_TIME_SEC, PM_COUNT_ONE));
+
+               pmiAddMetric("network.interface.out.fifo",
+                            PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT,
+                            pmiUnits(0, -1, 1, 0, PM_TIME_SEC, PM_COUNT_ONE));
+       }
+#endif /* HAVE_PCP */
+}
index 2148fce4ae5eb27a1decd00548002aca55d2fb28..238a23ace44edfac596c24701d63a07c4b2af71b 100644 (file)
@@ -21,5 +21,6 @@ void pcp_def_io_metrics(void);
 void pcp_def_memory_metrics(struct activity *);
 void pcp_def_ktables_metrics(void);
 void pcp_def_queue_metrics(void);
+void pcp_def_net_dev_metrics(struct activity *);
 
 #endif /* _PCP_DEF_METRICS_H */
index 13bda77b5b58175a83343ba7eb8d46ab6bd3a24d..af5279b49dc66c57ffca697eb4c49d4175906225 100644 (file)
@@ -554,3 +554,161 @@ __print_funct_t pcp_print_queue_stats(struct activity *a, int curr, unsigned lon
        pmiPutValue("kernel.all.load", "15 min", buf);
 #endif /* HAVE_PCP */
 }
+
+/*
+ ***************************************************************************
+ * Display network interfaces statistics in PCP format.
+ *
+ * IN:
+ * @a          Activity structure with statistics.
+ * @curr       Index in array for current sample statistics.
+ * @itv                Interval of time in 1/100th of a second.
+ * @record_hdr Record header for current sample.
+ ***************************************************************************
+ */
+__print_funct_t pcp_print_net_dev_stats(struct activity *a, int curr, unsigned long long itv,
+                                       struct record_header *record_hdr)
+{
+#ifdef HAVE_PCP
+       int i, j;
+       struct stats_net_dev *sndc, *sndp, sndzero;
+       double rxkb, txkb, ifutil;
+       char buf[64];
+
+       memset(&sndzero, 0, STATS_NET_DEV_SIZE);
+
+       for (i = 0; i < a->nr[curr]; i++) {
+
+               sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
+
+               if (a->item_list != NULL) {
+                       /* A list of devices has been entered on the command line */
+                       if (!search_list_item(a->item_list, sndc->interface))
+                               /* Device not found */
+                               continue;
+               }
+
+               j = check_net_dev_reg(a, curr, !curr, i);
+               if (j < 0) {
+                       /* This is a newly registered interface. Previous stats are zero */
+                       sndp = &sndzero;
+               }
+               else {
+                       sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
+               }
+
+               rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
+               txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
+               ifutil = compute_ifutil(sndc, rxkb, txkb);
+
+               snprintf(buf, sizeof(buf), "%f",
+                        S_VALUE(sndp->rx_packets, sndc->rx_packets, itv));
+               pmiPutValue("network.interface.in.packets", sndc->interface, buf);
+
+               snprintf(buf, sizeof(buf), "%f",
+                        S_VALUE(sndp->tx_packets, sndc->tx_packets, itv));
+               pmiPutValue("network.interface.out.packets", sndc->interface, buf);
+
+               snprintf(buf, sizeof(buf), "%f", rxkb / 1024);
+               pmiPutValue("network.interface.in.bytes", sndc->interface, buf);
+
+               snprintf(buf, sizeof(buf), "%f", txkb / 1024);
+               pmiPutValue("network.interface.out.bytes", sndc->interface, buf);
+
+               snprintf(buf, sizeof(buf), "%f",
+                        S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv));
+               pmiPutValue("network.interface.in.compressed", sndc->interface, buf);
+
+               snprintf(buf, sizeof(buf), "%f",
+                        S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv));
+               pmiPutValue("network.interface.out.compressed", sndc->interface, buf);
+
+               snprintf(buf, sizeof(buf), "%f",
+                        S_VALUE(sndp->multicast, sndc->multicast, itv));
+               pmiPutValue("network.interface.in.multicast", sndc->interface, buf);
+
+               snprintf(buf, sizeof(buf), "%f", ifutil);
+               pmiPutValue("network.interface.util", sndc->interface, buf);
+       }
+#endif /* HAVE_PCP */
+}
+
+/*
+ ***************************************************************************
+ * Display network interfaces errors statistics in PCP format.
+ *
+ * IN:
+ * @a          Activity structure with statistics.
+ * @curr       Index in array for current sample statistics.
+ * @itv                Interval of time in 1/100th of a second.
+ * @record_hdr Record header for current sample.
+ ***************************************************************************
+ */
+__print_funct_t pcp_print_net_edev_stats(struct activity *a, int curr, unsigned long long itv,
+                                       struct record_header *record_hdr)
+{
+#ifdef HAVE_PCP
+       int i, j;
+       struct stats_net_edev *snedc, *snedp, snedzero;
+       char buf[64];
+
+       memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
+
+       for (i = 0; i < a->nr[curr]; i++) {
+
+               snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
+
+               if (a->item_list != NULL) {
+                       /* A list of devices has been entered on the command line */
+                       if (!search_list_item(a->item_list, snedc->interface))
+                               /* Device not found */
+                               continue;
+               }
+
+               j = check_net_edev_reg(a, curr, !curr, i);
+               if (j < 0) {
+                       /* This is a newly registered interface. Previous stats are zero */
+                       snedp = &snedzero;
+               }
+               else {
+                       snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
+               }
+
+               snprintf(buf, sizeof(buf), "%f",
+                        S_VALUE(snedp->rx_errors, snedc->rx_errors, itv));
+               pmiPutValue("network.interface.in.errors", snedc->interface, buf);
+
+               snprintf(buf, sizeof(buf), "%f",
+                        S_VALUE(snedp->tx_errors, snedc->tx_errors, itv));
+               pmiPutValue("network.interface.out.errors", snedc->interface, buf);
+
+               snprintf(buf, sizeof(buf), "%f",
+                        S_VALUE(snedp->collisions, snedc->collisions, itv));
+               pmiPutValue("network.interface.out.collisions", snedc->interface, buf);
+
+               snprintf(buf, sizeof(buf), "%f",
+                        S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv));
+               pmiPutValue("network.interface.in.drops", snedc->interface, buf);
+
+               snprintf(buf, sizeof(buf), "%f",
+                        S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv));
+               pmiPutValue("network.interface.out.drops", snedc->interface, buf);
+
+               snprintf(buf, sizeof(buf), "%f",
+                        S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv));
+               pmiPutValue("network.interface.out.carrier", snedc->interface, buf);
+
+               snprintf(buf, sizeof(buf), "%f",
+                        S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv));
+               pmiPutValue("network.interface.in.frame", snedc->interface, buf);
+
+               snprintf(buf, sizeof(buf), "%f",
+                        S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv));
+               pmiPutValue("network.interface.in.fifo", snedc->interface, buf);
+
+               snprintf(buf, sizeof(buf), "%f",
+                        S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv));
+               pmiPutValue("network.interface.out.fifo", snedc->interface, buf);
+       }
+#endif /* HAVE_PCP */
+}
index dc06461f824e0e509feaa1e5becd049f7cf0d6d0..443ba079356f5564efbb596336b1f02ae6476248 100644 (file)
@@ -31,5 +31,9 @@ __print_funct_t pcp_print_ktables_stats
        (struct activity *, int, unsigned long long, struct record_header *);
 __print_funct_t pcp_print_queue_stats
        (struct activity *, int, unsigned long long, struct record_header *);
+__print_funct_t pcp_print_net_dev_stats
+       (struct activity *, int, unsigned long long, struct record_header *);
+__print_funct_t pcp_print_net_edev_stats
+       (struct activity *, int, unsigned long long, struct record_header *);
 
 #endif /* _PCP_STATS_H */
diff --git a/sadf.c b/sadf.c
index 14eace1d1bd2a9f21dc9bcfd1fccb85b9edd355e..332568759d0239d995cfe321e73225c4fdc5a069 100644 (file)
--- a/sadf.c
+++ b/sadf.c
@@ -1021,6 +1021,11 @@ void logic1_display_loop(int ifd, struct file_activity *file_actlst, char *file,
                setlocale(LC_NUMERIC, "C");
        }
 
+       /* Count items in file. Needed only for PCP output */
+       if (format == F_PCP_OUTPUT) {
+               count_file_items(ifd, file, file_magic, file_actlst, rectime, loctime);
+       }
+
        /* Save current file position */
        seek_file_position(ifd, DO_SAVE);
 
index 1ee69c0bc70802cc35a3ee21f35657e0155d5ba9..4e5ad57285e3af24289df81112d7b5665ada960e 100644 (file)
@@ -532,6 +532,11 @@ __printf_funct_t print_pcp_statistics(int *tab, int action, struct activity *act
                                case A_QUEUE:
                                        pcp_def_queue_metrics();
                                        break;
+
+                               case A_NET_DEV:
+                               case A_NET_EDEV:
+                                       pcp_def_net_dev_metrics(act[p]);
+                                       break;
                        }
                }
        }