[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