[RFC PATCH 12/16] Expose qemu timed block statistics via bulk stats API

Peter Krempa via Devel posted 16 patches 2 weeks, 4 days ago
[RFC PATCH 12/16] Expose qemu timed block statistics via bulk stats API
Posted by Peter Krempa via Devel 2 weeks, 4 days ago
From: Peter Krempa <pkrempa@redhat.com>

The statistics show various disk access timing parameters collected in
configurable interval which can be useful for performance
investigations.

Note that the statistic collection needs to be enabled explicitly for
the statistics to be collected and displayed.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
---
 docs/manpages/virsh.rst          |  33 ++++++
 include/libvirt/libvirt-domain.h | 178 +++++++++++++++++++++++++++++++
 src/qemu/qemu_driver.c           |  94 ++++++++++++++++
 3 files changed, 305 insertions(+)

diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index 5b4eb236a4..73263ffc7f 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -2772,6 +2772,39 @@ Information listed includes:
   that no bounce buffer is needed
 * ``block.<num>.limits.memory_alignment_optimal`` - memory alignment in bytes
   that is used for bounce buffers
+* ``block.<num>.timed_group.count`` - number of blocks of timed group statistics
+* ``block.<num>.timed_group.<num>.interval_length`` - The time interval in
+  seconds for which the statistics in this group were collected.
+* ``block.<num>.timed_group.<num>.rd_latency_min`` - minimum latency of read
+  operations in the defined interval in nanoseconds
+* ``block.<num>.timed_group.<num>.rd_latency_max`` - maximum latency of read
+  operations in the defined interval in nanoseconds
+* ``block.<num>.timed_group.<num>.rd_latency_avg`` - average latency of read
+  operations in the defined interval in nanoseconds
+* ``block.<num>.timed_group.<num>.wr_latency_min`` - minimum latency of write
+  operations in the defined interval in nanoseconds
+* ``block.<num>.timed_group.<num>.wr_latency_max`` - maximum latency of write
+  operations in the defined interval in nanoseconds
+* ``block.<num>.timed_group.<num>.wr_latency_avg`` - average latency of write
+  operations in the defined interval in nanoseconds
+* ``block.<num>.timed_group.<num>.zone_append_latency_min`` - minimum latency
+  of zone append operations in the defined interval in nanoseconds
+* ``block.<num>.timed_group.<num>.zone_append_latency_max`` - maximum latency
+  of zone append operations in the defined interval in nanoseconds
+* ``block.<num>.timed_group.<num>.zone_append_latency_avg`` - average latency
+  of zone append operations in the defined interval in nanoseconds
+* ``block.<num>.timed_group.<num>.flush_latency_min`` - minimum latency
+  of flush operations in the defined interval in nanoseconds
+* ``block.<num>.timed_group.<num>.flush_latency_max`` - maximum latency of flush
+  operations in the defined interval in nanoseconds
+* ``block.<num>.timed_group.<num>.flush_latency_avg`` - average latency of flush
+  operations in the defined interval in nanoseconds
+* ``block.<num>.timed_group.<num>.rd_queue_depth_avg`` - average number of
+  pending read operations in the defined interval
+* ``block.<num>.timed_group.<num>.wr_queue_depth_avg`` - average number of
+  pending write operations in the defined interval
+* ``block.<num>.timed_group.<num>.zone_append_queue_depth_avg`` - average number
+  of pending zone append operations in the defined interval


 *--iothread* returns information about IOThreads on the running guest
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 90c37a575c..56bd085ef5 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -3637,6 +3637,184 @@ struct _virDomainStatsRecord {
  */
 # define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LIMITS_MEMORY_ALIGNMENT_OPTIMAL ".limits.memory_alignment_optimal"

+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_COUNT:
+ *
+ * Number of groups of statistics accounted in a configured time intervals as
+ * unsigned long long.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_COUNT ".timed_group.count"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX:
+ *
+ * The parameter name prefix to access each group of timed stats. Concatenate the
+ * prefix, the entry number formatted as an unsigned integer and one of the
+ * timed group suffix parameters to form a complete paramter name.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX ".timed_group."
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_INTERVAL:
+ *
+ * The time interval in seconds as unsigned long long for which the statistics
+ * in this group were collected.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_INTERVAL ".interval"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_RD_LATENCY_MIN:
+ *
+ * Minimum latency of read operations in the defined interval, in nanoseconds as
+ * unsigned long long.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_RD_LATENCY_MIN ".rd_latency_min"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_RD_LATENCY_MAX:
+ *
+ * Maximum latency of read operations in the defined interval, in nanoseconds as
+ * unsigned long long.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_RD_LATENCY_MAX ".rd_latency_max"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_RD_LATENCY_AVG:
+ *
+ * Average latency of read operations in the defined interval, in nanoseconds as
+ * unsigned long long.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_RD_LATENCY_AVG ".rd_latency_avg"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_WR_LATENCY_MIN:
+ *
+ * Minimum latency of write operations in the defined interval, in nanoseconds
+ * as unsigned long long.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_WR_LATENCY_MIN ".wr_latency_min"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_WR_LATENCY_MAX:
+ *
+ * Maximum latency of write operations in the defined interval, in nanoseconds
+ * as unsigned long long.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_WR_LATENCY_MAX ".wr_latency_max"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_WR_LATENCY_AVG:
+ *
+ * Average latency of write operations in the defined interval, in nanoseconds
+ * as unsigned long long.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_WR_LATENCY_AVG ".wr_latency_avg"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_ZONE_APPEND_LATENCY_MIN:
+ * Minimum latency of zone append operations in the defined interval, in
+ * nanoseconds as unsigned long long.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_ZONE_APPEND_LATENCY_MIN ".zone_append_latency_min"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_ZONE_APPEND_LATENCY_MAX:
+ *
+ * Maximum latency of zone append operations in the defined interval, in
+ * nanoseconds as unsigned long long.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_ZONE_APPEND_LATENCY_MAX ".zone_append_latency_max"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_ZONE_APPEND_LATENCY_AVG:
+ *
+ * Average latency of zone append operations in the defined interval, in
+ * nanoseconds as unsigned long long.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_ZONE_APPEND_LATENCY_AVG ".zone_append_latency_avg"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_FLUSH_LATENCY_MIN:
+ *
+ * Minimum latency of flush operations in the defined interval, in nanoseconds
+ * as unsigned long long.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_FLUSH_LATENCY_MIN ".flush_latency_min"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_FLUSH_LATENCY_MAX:
+ *
+ * Maximum latency of flush operations in the defined interval, in nanoseconds
+ * as unsigned long long.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_FLUSH_LATENCY_MAX ".flush_latency_max"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_FLUSH_LATENCY_AVG:
+ *
+ * Average latency of flush operations in the defined interval, in nanoseconds
+ * as unsigned long long.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_FLUSH_LATENCY_AVG ".flush_latency_avg"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_RD_QUEUE_DEPTH_AVG:
+ *
+ * Average number of pending read operations in the defined interval as double.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_RD_QUEUE_DEPTH_AVG ".rd_queue_depth_avg"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_WR_QUEUE_DEPTH_AVG:
+ *
+ * Average number of pending write operations in the defined interval as double.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_WR_QUEUE_DEPTH_AVG ".wr_queue_depth_avg"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_ZONE_APPEND_QUEUE_DEPTH_AVG:
+ *
+ * Average number of pending zone append operations in the defined interval as
+ * double.
+ *
+ * Since: 11.9.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_ZONE_APPEND_QUEUE_DEPTH_AVG ".zone_append_queue_depth_avg"
+
 /**
  * VIR_DOMAIN_STATS_PERF_CMT:
  *
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 4e5e2fed0f..b8157bd3fe 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -17581,6 +17581,7 @@ qemuDomainGetStatsBlockExportFrontend(const char *frontendname,
                                       virTypedParamList *par)
 {
     qemuBlockStats *en;
+    size_t i;

     /* In case where qemu didn't provide the stats we stop here rather than
      * trying to refresh the stats from the disk. Inability to provide stats is
@@ -17604,6 +17605,99 @@ qemuDomainGetStatsBlockExportFrontend(const char *frontendname,
                                VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu" VIR_DOMAIN_STATS_BLOCK_SUFFIX_FL_REQS, idx);
     virTypedParamListAddULLong(par, en->flush_total_times,
                                VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu" VIR_DOMAIN_STATS_BLOCK_SUFFIX_FL_TIMES, idx);
+
+    if (en->n_timed_stats > 0) {
+        virTypedParamListAddULLong(par, en->n_timed_stats,
+                                   VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu" VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_COUNT, idx);
+
+        for (i = 0; i < en->n_timed_stats; i++) {
+            virTypedParamListAddULLong(par, en->timed_stats[i].interval_length,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_INTERVAL,
+                                       idx, i);
+
+            virTypedParamListAddULLong(par, en->timed_stats[i].rd_latency_min,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_RD_LATENCY_MIN,
+                                       idx, i);
+            virTypedParamListAddULLong(par, en->timed_stats[i].rd_latency_max,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_RD_LATENCY_MAX,
+                                       idx, i);
+            virTypedParamListAddULLong(par, en->timed_stats[i].rd_latency_avg,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_RD_LATENCY_AVG,
+                                       idx, i);
+
+            virTypedParamListAddULLong(par, en->timed_stats[i].wr_latency_min,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_WR_LATENCY_MIN,
+                                       idx, i);
+            virTypedParamListAddULLong(par, en->timed_stats[i].wr_latency_max,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_WR_LATENCY_MAX,
+                                       idx, i);
+            virTypedParamListAddULLong(par, en->timed_stats[i].wr_latency_avg,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_WR_LATENCY_AVG,
+                                       idx, i);
+
+            virTypedParamListAddULLong(par, en->timed_stats[i].zone_append_latency_min,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_ZONE_APPEND_LATENCY_MIN,
+                                       idx, i);
+            virTypedParamListAddULLong(par, en->timed_stats[i].zone_append_latency_max,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_ZONE_APPEND_LATENCY_MAX,
+                                       idx, i);
+            virTypedParamListAddULLong(par, en->timed_stats[i].zone_append_latency_avg,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_ZONE_APPEND_LATENCY_AVG,
+                                       idx, i);
+
+            virTypedParamListAddULLong(par, en->timed_stats[i].flush_latency_min,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_FLUSH_LATENCY_MIN,
+                                       idx, i);
+            virTypedParamListAddULLong(par, en->timed_stats[i].flush_latency_max,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_FLUSH_LATENCY_MAX,
+                                       idx, i);
+            virTypedParamListAddULLong(par, en->timed_stats[i].flush_latency_avg,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_FLUSH_LATENCY_AVG,
+                                       idx, i);
+
+            virTypedParamListAddDouble(par, en->timed_stats[i].rd_queue_depth_avg,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_RD_QUEUE_DEPTH_AVG,
+                                       idx, i);
+            virTypedParamListAddDouble(par, en->timed_stats[i].wr_queue_depth_avg,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_WR_QUEUE_DEPTH_AVG,
+                                       idx, i);
+            virTypedParamListAddDouble(par, en->timed_stats[i].zone_append_queue_depth_avg,
+                                       VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX "%zu"
+                                       VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_ZONE_APPEND_QUEUE_DEPTH_AVG,
+                                       idx, i);
+        }
+    }
 }


-- 
2.51.0