[PATCH 1/3] qemu_monitor: add qemuMonitorQueryStats

Martin Kletzander mkletzan at redhat.com
Fri Jul 22 14:43:25 UTC 2022


On Thu, Jul 14, 2022 at 11:22:02AM +0530, Amneesh Singh wrote:
>Related: https://gitlab.com/libvirt/libvirt/-/issues/276
>
>This patch adds an API for the "query-stats" QMP command.
>
>The query returns a JSON containing the statistics based on the target,
>which can either be vCPU or VM, and the providers. The API deserializes
>the query result into an array of GHashMaps, which can later be used to
>extract all the query statistics. GHashMaps are used to avoid traversing
>the entire array to find the statistics you are looking for. This would
>be a singleton array if the target is a VM since the returned JSON is
>also a singleton array in that case.
>
>Signed-off-by: Amneesh Singh <natto at weirdnatto.in>
>---
> src/qemu/qemu_monitor.c      |  70 +++++++++++++++++++
> src/qemu/qemu_monitor.h      |  45 ++++++++++++
> src/qemu/qemu_monitor_json.c | 130 +++++++++++++++++++++++++++++++++++
> src/qemu/qemu_monitor_json.h |   6 ++
> 4 files changed, 251 insertions(+)
>
>diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
>index 80696de7..4e228bfb 100644
>--- a/src/qemu/qemu_monitor_json.c
>+++ b/src/qemu/qemu_monitor_json.c
>@@ -9031,3 +9031,133 @@ qemuMonitorJSONMigrateRecover(qemuMonitor *mon,
>
>     return qemuMonitorJSONCheckError(cmd, reply);
> }
>+
>+static GPtrArray *
>+qemuMonitorJSONExtractQueryStats(virJSONValue *arr)
>+{
>+    g_autoptr(GPtrArray) queried_stats = NULL;
>+    size_t nstats = virJSONValueArraySize(arr);
>+    size_t i;
>+
>+    /* Create a GPtrArray for GHashTables */
>+    queried_stats = g_ptr_array_new_full(nstats, (GDestroyNotify) g_hash_table_destroy);
>+
>+    for (i = 0; i < nstats; i++) {
>+        virJSONValue *obj = virJSONValueArrayGet(arr, i);
>+        virJSONValue *stats = virJSONValueObjectGetArray(obj, "stats");
>+        size_t j;
>+
>+        /* Create a GHashTable for virJSONValues */
>+        GHashTable *hash_table = virHashNew((GDestroyNotify) virJSONValueFree);
>+
>+        for (j = 0; j < virJSONValueArraySize(stats); j++) {
>+            virJSONValue *stat = virJSONValueArrayGet(stats, j);
>+
>+            g_hash_table_insert(hash_table,
>+                                g_strdup(virJSONValueObjectGetString(stat, "name")),
>+                                virJSONValueObjectGet(stat, "value"));
>+        }
>+
>+        g_ptr_array_add(queried_stats, hash_table);
>+    }
>+
>+    return g_steal_pointer(&queried_stats);
>+}
>+
>+
>+/**
>+ * qemuMonitorJSONQueryStats:
>+ * @mon: monitor object
>+ * @target: the target type for the query
>+ * @vcpus: a list of vCPU QOM paths for filtering the statistics
>+ * @providers: an array of providers to filter statistics
>+ *
>+ * @vcpus is a NULL terminated array of strings. @providers is a GPtrArray
>+ * for qemuMonitorQueryStatsProvider.
>+ * @vcpus and @providers are optional and can be NULL.
>+ *
>+ * Queries for the @target based statistics.
>+ * Returns a GPtrArray of GHashTables containing the statistics on success or
>+ * NULL on failure.
>+ */
>+
>+GPtrArray *
>+qemuMonitorJSONQueryStats(qemuMonitor *mon,
>+                          qemuMonitorQueryStatsTargetType target,
>+                          char **vcpus,
>+                          GPtrArray *providers)
>+{
>+    g_autoptr(virJSONValue) cmd = NULL;
>+    g_autoptr(virJSONValue) reply = NULL;
>+    g_autoptr(virJSONValue) vcpu_list = NULL;
>+    g_autoptr(virJSONValue) provider_list = NULL;
>+    virJSONValue *rv = NULL;
>+
>+    size_t i;
>+
>+    if (providers) {
>+        provider_list = virJSONValueNewArray();
>+
>+        for (i = 0; i < providers->len; i++) {
>+            g_autoptr(virJSONValue) provider_obj = virJSONValueNewObject();
>+            qemuMonitorQueryStatsProvider *provider = providers->pdata[i];
>+            const char *type_str = qemuMonitorQueryStatsProviderTypeToString(provider->provider);
>+            virBitmap *names = provider->names;
>+            int rc;
>+
>+            rc = virJSONValueObjectAppendString(provider_obj, "provider", type_str);
>+
>+            if (rc < 0)
>+                return NULL;
>+
>+            if (names) {
>+                g_autoptr(virJSONValue) provider_names = virJSONValueNewArray();
>+                int curBit = virBitmapNextSetBit(names, -1);
>+
>+                while (curBit >= 0) {
>+                    const char *name = qemuMonitorQueryStatsNameTypeToString(curBit);
>+
>+                    if (virJSONValueArrayAppendString(provider_names, name) < 0)
>+                        return NULL;
>+
>+                    curBit = virBitmapNextSetBit(names, curBit);
>+                }

Also this can be shorter with:

int curBit = -1;

while ((curBit = virBitmapNextSetBit(names, curBit)) != -1) {
    ...
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20220722/463a8ee6/attachment.sig>


More information about the libvir-list mailing list