From: Peter Krempa <pkrempa@redhat.com>
The 'timed_stats' block is a set of statistics gathered in configurable
time intervals. The stats include latency timings of reads/writes as
well as the depth of the request queues.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
---
src/qemu/qemu_monitor.c | 1 +
src/qemu/qemu_monitor.h | 29 ++++++++++++++++++++++++
src/qemu/qemu_monitor_json.c | 44 ++++++++++++++++++++++++++++++++++++
3 files changed, 74 insertions(+)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 554898b93f..fb01335f89 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1984,6 +1984,7 @@ qemuBlockStatsFinalize(GObject *object)
return;
g_free(stats->limits);
+ g_free(stats->timed_stats);
G_OBJECT_CLASS(qemu_block_stats_parent_class)->finalize(object);
}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 9b9292e48d..a93d722418 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -806,6 +806,31 @@ struct qemuBlockStatsLimits {
};
+struct qemuBlockStatsTimed {
+ unsigned long long interval_length;
+
+ /* latencies are in nanoseconds */
+ unsigned long long rd_latency_min;
+ unsigned long long rd_latency_max;
+ unsigned long long rd_latency_avg;
+
+ unsigned long long wr_latency_min;
+ unsigned long long wr_latency_max;
+ unsigned long long wr_latency_avg;
+
+ unsigned long long zone_append_latency_min;
+ unsigned long long zone_append_latency_max;
+ unsigned long long zone_append_latency_avg;
+
+ unsigned long long flush_latency_min;
+ unsigned long long flush_latency_max;
+ unsigned long long flush_latency_avg;
+
+ double rd_queue_depth_avg;
+ double wr_queue_depth_avg;
+ double zone_append_queue_depth_avg;
+};
+
struct _qemuBlockStats {
GObject parent;
@@ -829,6 +854,10 @@ struct _qemuBlockStats {
unsigned long long write_threshold;
struct qemuBlockStatsLimits *limits;
+
+ /* block accounting/timed stats from qemu - one entry per interval configured */
+ size_t n_timed_stats;
+ struct qemuBlockStatsTimed *timed_stats;
};
G_DECLARE_FINAL_TYPE(qemuBlockStats, qemu_block_stats, QEMU, BLOCK_STATS, GObject);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index cf63f43318..0cb20d4387 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2386,6 +2386,45 @@ qemuMonitorJSONGetBlockInfo(qemuMonitor *mon,
}
+static void
+qemuMonitorJSONBlockStatsCollectDataTimedOne(virJSONValue *j,
+ struct qemuBlockStatsTimed *s)
+{
+ virJSONValueObjectGetNumberUlong(j, "interval_length", &s->interval_length);
+
+ virJSONValueObjectGetNumberUlong(j, "min_rd_latency_ns", &s->rd_latency_min);
+ virJSONValueObjectGetNumberUlong(j, "max_rd_latency_ns", &s->rd_latency_max);
+ virJSONValueObjectGetNumberUlong(j, "avg_rd_latency_ns", &s->rd_latency_avg);
+
+ virJSONValueObjectGetNumberUlong(j, "min_wr_latency_ns", &s->wr_latency_min);
+ virJSONValueObjectGetNumberUlong(j, "max_wr_latency_ns", &s->wr_latency_max);
+ virJSONValueObjectGetNumberUlong(j, "avg_wr_latency_ns", &s->wr_latency_avg);
+
+ virJSONValueObjectGetNumberUlong(j, "min_zone_append_latency_ns", &s->zone_append_latency_min);
+ virJSONValueObjectGetNumberUlong(j, "max_zone_append_latency_ns", &s->zone_append_latency_max);
+ virJSONValueObjectGetNumberUlong(j, "avg_zone_append_latency_ns", &s->zone_append_latency_avg);
+
+ virJSONValueObjectGetNumberDouble(j, "avg_rd_queue_depth", &s->rd_queue_depth_avg);
+ virJSONValueObjectGetNumberDouble(j, "avg_wr_queue_depth", &s->wr_queue_depth_avg);
+ virJSONValueObjectGetNumberDouble(j, "avg_zone_append_queue_depth", &s->zone_append_queue_depth_avg);
+}
+
+
+static void
+qemuMonitorJSONBlockStatsCollectDataTimed(virJSONValue *timed_stats,
+ qemuBlockStats *bstats)
+{
+ size_t i;
+
+ bstats->n_timed_stats = virJSONValueArraySize(timed_stats);
+ bstats->timed_stats = g_new0(struct qemuBlockStatsTimed, bstats->n_timed_stats);
+
+ for (i = 0; i < bstats->n_timed_stats; i++)
+ qemuMonitorJSONBlockStatsCollectDataTimedOne(virJSONValueArrayGet(timed_stats, i),
+ bstats->timed_stats + i);
+}
+
+
static qemuBlockStats *
qemuMonitorJSONBlockStatsCollectData(virJSONValue *dev,
int *nstats)
@@ -2394,6 +2433,7 @@ qemuMonitorJSONBlockStatsCollectData(virJSONValue *dev,
virJSONValue *parent;
virJSONValue *parentstats;
virJSONValue *stats;
+ virJSONValue *timed_stats;
if ((stats = virJSONValueObjectGetObject(dev, "stats")) == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -2429,6 +2469,10 @@ qemuMonitorJSONBlockStatsCollectData(virJSONValue *dev,
bstats->wr_highest_offset_valid = true;
}
+ if ((timed_stats = virJSONValueObjectGetArray(stats, "timed_stats")) &&
+ virJSONValueArraySize(timed_stats) > 0)
+ qemuMonitorJSONBlockStatsCollectDataTimed(timed_stats, bstats);
+
return g_steal_pointer(&bstats);
}
--
2.51.0