From 3b2a7de5c7c1057df513625977cf5ab54b42a68c Mon Sep 17 00:00:00 2001 From: Sebastien GODARD Date: Sun, 19 May 2019 09:44:10 +0200 Subject: [PATCH] sadf: PCP: Add support for A_DISK activity Add metrics displayed by "sar -d" (disks statistics) to PCP archive. Signed-off-by: Sebastien GODARD --- activity.c | 1 + pcp_def_metrics.c | 60 +++++++++++++++++++++++++++++++++ pcp_def_metrics.h | 2 ++ pcp_stats.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++ pcp_stats.h | 2 ++ sadf_misc.c | 4 +++ 6 files changed, 153 insertions(+) diff --git a/activity.c b/activity.c index 8651bdb..c300895 100644 --- a/activity.c +++ b/activity.c @@ -555,6 +555,7 @@ struct activity disk_act = { .f_json_print = json_print_disk_stats, .f_svg_print = svg_print_disk_stats, .f_raw_print = raw_print_disk_stats, + .f_pcp_print = pcp_print_disk_stats, .f_count_new = count_new_disk, .item_list = NULL, .desc = "Block devices statistics", diff --git a/pcp_def_metrics.c b/pcp_def_metrics.c index cde34d1..262722c 100644 --- a/pcp_def_metrics.c +++ b/pcp_def_metrics.c @@ -545,6 +545,66 @@ void pcp_def_queue_metrics(void) #endif /* HAVE_PCP */ } +/* + *************************************************************************** + * Define PCP metrics for disks statistics. + * + * IN: + * @a Activity structure with statistics. + *************************************************************************** + */ +void pcp_def_disk_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, PM_INDOM_DISK); + + /* Create instances */ + while (list != NULL) { + pmiAddInstance(indom, list->item_name, inst++); + list = list->next; + } + } + + pmiAddMetric("disk.device.tps", + PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT, + pmiUnits(0, -1, 1, 0, PM_TIME_SEC, PM_COUNT_ONE)); + + pmiAddMetric("disk.device.read_bytes", + PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT, + pmiUnits(1, -1, 0, PM_SPACE_KBYTE, PM_TIME_SEC, 0)); + + pmiAddMetric("disk.device.write_bytes", + PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT, + pmiUnits(1, -1, 0, PM_SPACE_KBYTE, PM_TIME_SEC, 0)); + + pmiAddMetric("disk.device.discard_bytes", + PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT, + pmiUnits(1, -1, 0, PM_SPACE_KBYTE, PM_TIME_SEC, 0)); + + pmiAddMetric("disk.device.areq_sz", + PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT, + pmiUnits(1, 0, 0, PM_SPACE_KBYTE, 0, 0)); + + pmiAddMetric("disk.device.aqu_sz", + PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT, + pmiUnits(0, 0, 0, 0, 0, 0)); + + pmiAddMetric("disk.device.await", + PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT, + pmiUnits(0, 0, 0, 0, 0, 0)); + + pmiAddMetric("disk.device.util", + PM_IN_NULL, PM_TYPE_FLOAT, indom, PM_SEM_INSTANT, + pmiUnits(0, 0, 0, 0, 0, 0)); +#endif /* HAVE_PCP */ +} + /* *************************************************************************** * Define PCP metrics for network interfaces (errors) statistics. diff --git a/pcp_def_metrics.h b/pcp_def_metrics.h index 15a4875..383c320 100644 --- a/pcp_def_metrics.h +++ b/pcp_def_metrics.h @@ -22,6 +22,7 @@ void pcp_def_memory_metrics(struct activity *); void pcp_def_ktables_metrics(void); void pcp_def_queue_metrics(void); void pcp_def_serial_metrics(struct activity *); +void pcp_def_disk_metrics(struct activity *); void pcp_def_net_dev_metrics(struct activity *); void pcp_def_net_nfs_metrics(void); void pcp_def_net_nfsd_metrics(void); @@ -53,6 +54,7 @@ void pcp_def_fchost_metrics(struct activity *); #define PM_INDOM_FILESYSTEM 5 #define PM_INDOM_FCHOST 6 #define PM_INDOM_USB 7 +#define PM_INDOM_DISK 8 #endif /* _PCP_DEF_METRICS_H */ diff --git a/pcp_stats.c b/pcp_stats.c index 935042d..f30bd7c 100644 --- a/pcp_stats.c +++ b/pcp_stats.c @@ -573,6 +573,90 @@ __print_funct_t pcp_print_queue_stats(struct activity *a, int curr, unsigned lon #endif /* HAVE_PCP */ } +/* + *************************************************************************** + * Display disks 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_disk_stats(struct activity *a, int curr, unsigned long long itv, + struct record_header *record_hdr) +{ +#ifdef HAVE_PCP + int i, j; + struct stats_disk *sdc, *sdp, sdpzero; + struct ext_disk_stats xds; + char *dev_name; + char buf[64]; + + memset(&sdpzero, 0, STATS_DISK_SIZE); + + for (i = 0; i < a->nr[curr]; i++) { + + sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize); + + j = check_disk_reg(a, curr, !curr, i); + if (j < 0) { + /* This is a newly registered interface. Previous stats are zero */ + sdp = &sdpzero; + } + else { + sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize); + } + + /* Get device name */ + dev_name = get_sa_devname(sdc->major, sdc->minor, flags); + + if (a->item_list != NULL) { + /* A list of devices has been entered on the command line */ + if (!search_list_item(a->item_list, dev_name)) + /* Device not found */ + continue; + } + + /* Compute extended statistics values */ + compute_ext_disk_stats(sdc, sdp, itv, &xds); + + snprintf(buf, sizeof(buf), "%f", + S_VALUE(sdp->nr_ios, sdc->nr_ios, itv)); + pmiPutValue("disk.device.tps", dev_name, buf); + + snprintf(buf, sizeof(buf), "%f", + S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2); + pmiPutValue("disk.device.read_bytes", dev_name, buf); + + snprintf(buf, sizeof(buf), "%f", + S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2); + pmiPutValue("disk.device.write_bytes", dev_name, buf); + + snprintf(buf, sizeof(buf), "%f", + S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2); + pmiPutValue("disk.device.discard_bytes", dev_name, buf); + + snprintf(buf, sizeof(buf), "%f", + xds.arqsz / 2); + pmiPutValue("disk.device.areq_sz", dev_name, buf); + + snprintf(buf, sizeof(buf), "%f", + S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0); + pmiPutValue("disk.device.aqu_sz", dev_name, buf); + + snprintf(buf, sizeof(buf), "%f", + xds.await); + pmiPutValue("disk.device.await", dev_name, buf); + + snprintf(buf, sizeof(buf), "%f", + xds.util / 10.0); + pmiPutValue("disk.device.util", dev_name, buf); + } +#endif /* HAVE_PCP */ +} + /* *************************************************************************** * Display network interfaces statistics in PCP format. diff --git a/pcp_stats.h b/pcp_stats.h index 79e1e60..970664d 100644 --- a/pcp_stats.h +++ b/pcp_stats.h @@ -31,6 +31,8 @@ __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_disk_stats + (struct activity *, int, unsigned long long, struct record_header *); __print_funct_t pcp_print_serial_stats (struct activity *, int, unsigned long long, struct record_header *); __print_funct_t pcp_print_net_dev_stats diff --git a/sadf_misc.c b/sadf_misc.c index 7e33f6f..8c33965 100644 --- a/sadf_misc.c +++ b/sadf_misc.c @@ -692,6 +692,10 @@ __printf_funct_t print_pcp_statistics(int *tab, int action, struct activity *act pcp_def_serial_metrics(act[p]); break; + case A_DISK: + pcp_def_disk_metrics(act[p]); + break; + case A_NET_DEV: case A_NET_EDEV: pcp_def_net_dev_metrics(act[p]); -- 2.40.0