From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: berrange@redhat.com, qemu-devel@nongnu.org, armbru@redhat.com
Subject: Re: [PATCH 1/8] qmp: Support for querying stats
Date: Wed, 27 Apr 2022 10:19:45 +0100 [thread overview]
Message-ID: <YmkKsQ9rFh+Ydfsu@work-vm> (raw)
In-Reply-To: <20220426141619.304611-2-pbonzini@redhat.com>
* Paolo Bonzini (pbonzini@redhat.com) wrote:
> From: Mark Kanda <mark.kanda@oracle.com>
>
> Introduce QMP support for querying stats. Provide a framework for adding new
> stats and support for the following commands:
>
> - query-stats
> Returns a list of all stats per target type (only VM and vCPU to start), with
> additional options for specifying stat names, vCPU qom paths, and providers.
>
> - query-stats-schemas
> Returns a list of stats included in each target type, with an option for
> specifying the provider. The concepts in the schema are based on the
> KVM binary stats' own introspection data, just translated to QAPI.
>
> The framework provides a method to register callbacks for these QMP commands.
> Most of the work in fact is done by the callbacks, and a large majority of
> this patch is new QAPI structs and commands.
>
> The first use-case will be for fd-based KVM stats (in an upcoming patch).
>
> Examples (with fd-based KVM stats):
>
> - Query all VM stats:
>
> { "execute": "query-stats", "arguments" : { "target": "vm" } }
>
> { "return": [
> { "provider": "kvm",
> "stats": [
> { "name": "max_mmu_page_hash_collisions", "value": 0 },
> { "name": "max_mmu_rmap_size", "value": 0 },
> { "name": "nx_lpage_splits", "value": 148 },
Is there any hierarchy to the naming or is it just a big flat name
space?
> ... ] },
> { "provider": "xyz",
> "stats": [ ... ] }
> ] }
>
> - Query all vCPU stats:
>
> { "execute": "query-stats", "arguments" : { "target": "vcpu" } }
>
> { "return": [
> { "provider": "kvm",
> "qom_path": "/machine/unattached/device[0]"
> "stats": [
> { "name": "guest_mode", "value": 0 },
> { "name": "directed_yield_successful", "value": 0 },
> { "name": "directed_yield_attempted", "value": 106 },
> ... ] },
> { "provider": "kvm",
> "qom_path": "/machine/unattached/device[1]"
> "stats": [
> { "name": "guest_mode", "value": 0 },
> { "name": "directed_yield_successful", "value": 0 },
> { "name": "directed_yield_attempted", "value": 106 },
> ... ] },
> ] }
>
> - Retrieve the schemas:
>
> { "execute": "query-stats-schemas" }
>
> { "return": [
> { "provider": "kvm",
> "target": "vcpu",
> "stats": [
> { "name": "guest_mode",
> "unit": "none",
> "base": 10,
> "exponent": 0,
> "type": "instant" },
> { "name": "directed_yield_successful",
> "unit": "none",
> "base": 10,
> "exponent": 0,
> "type": "cumulative" },
> ... ]
> },
> { "provider": "kvm",
> "target": "vm",
> "stats": [
> { "name": "max_mmu_page_hash_collisions",
> "unit": "none",
> "base": 10,
> "exponent": 0,
> "type": "peak" },
> ... ]
> },
Is there some way to reset the peak or cumulative values?
Dave
> { "provider": "xyz",
> "target": "vm",
> "stats": [ ... ]
> }
> ] }
>
> Signed-off-by: Mark Kanda <mark.kanda@oracle.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> include/monitor/stats.h | 33 +++++++
> monitor/qmp-cmds.c | 71 +++++++++++++++
> qapi/meson.build | 1 +
> qapi/qapi-schema.json | 1 +
> qapi/stats.json | 192 ++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 298 insertions(+)
> create mode 100644 include/monitor/stats.h
> create mode 100644 qapi/stats.json
>
> diff --git a/include/monitor/stats.h b/include/monitor/stats.h
> new file mode 100644
> index 0000000000..89552ab06f
> --- /dev/null
> +++ b/include/monitor/stats.h
> @@ -0,0 +1,33 @@
> +/*
> + * Copyright (c) 2022 Oracle and/or its affiliates.
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#ifndef STATS_H
> +#define STATS_H
> +
> +#include "qapi/qapi-types-stats.h"
> +
> +typedef void StatRetrieveFunc(StatsResultList **result, StatsTarget target, Error **errp);
> +typedef void SchemaRetrieveFunc(StatsSchemaList **result, Error **errp);
> +
> +/*
> + * Register callbacks for the QMP query-stats command.
> + *
> + * @stats_fn: routine to query stats:
> + * @schema_fn: routine to query stat schemas:
> + */
> +void add_stats_callbacks(StatRetrieveFunc *stats_fn,
> + SchemaRetrieveFunc *schemas_fn);
> +
> +/*
> + * Helper routines for adding stats entries to the results lists.
> + */
> +void add_stats_entry(StatsResultList **, StatsProvider, const char *id,
> + StatsList *stats_list);
> +void add_stats_schema(StatsSchemaList **, StatsProvider, StatsTarget,
> + StatsSchemaValueList *);
> +
> +#endif /* STATS_H */
> diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
> index 5e7302cbb9..97825b25fa 100644
> --- a/monitor/qmp-cmds.c
> +++ b/monitor/qmp-cmds.c
> @@ -35,6 +35,7 @@
> #include "qapi/qapi-commands-control.h"
> #include "qapi/qapi-commands-machine.h"
> #include "qapi/qapi-commands-misc.h"
> +#include "qapi/qapi-commands-stats.h"
> #include "qapi/qapi-commands-ui.h"
> #include "qapi/type-helpers.h"
> #include "qapi/qmp/qerror.h"
> @@ -43,6 +44,7 @@
> #include "hw/acpi/acpi_dev_interface.h"
> #include "hw/intc/intc.h"
> #include "hw/rdma/rdma.h"
> +#include "monitor/stats.h"
>
> NameInfo *qmp_query_name(Error **errp)
> {
> @@ -426,3 +428,72 @@ HumanReadableText *qmp_x_query_irq(Error **errp)
>
> return human_readable_text_from_str(buf);
> }
> +
> +typedef struct StatsCallbacks {
> + StatRetrieveFunc *stats_cb;
> + SchemaRetrieveFunc *schemas_cb;
> + QTAILQ_ENTRY(StatsCallbacks) next;
> +} StatsCallbacks;
> +
> +static QTAILQ_HEAD(, StatsCallbacks) stats_callbacks =
> + QTAILQ_HEAD_INITIALIZER(stats_callbacks);
> +
> +void add_stats_callbacks(StatRetrieveFunc *stats_fn,
> + SchemaRetrieveFunc *schemas_fn)
> +{
> + StatsCallbacks *entry = g_new(StatsCallbacks, 1);
> + entry->stats_cb = stats_fn;
> + entry->schemas_cb = schemas_fn;
> +
> + QTAILQ_INSERT_TAIL(&stats_callbacks, entry, next);
> +}
> +
> +StatsResultList *qmp_query_stats(StatsFilter *filter, Error **errp)
> +{
> + StatsResultList *stats_results = NULL;
> + StatsCallbacks *entry;
> +
> + QTAILQ_FOREACH(entry, &stats_callbacks, next) {
> + entry->stats_cb(&stats_results, filter->target, errp);
> + }
> +
> + return stats_results;
> +}
> +
> +StatsSchemaList *qmp_query_stats_schemas(Error **errp)
> +{
> + StatsSchemaList *stats_results = NULL;
> + StatsCallbacks *entry;
> +
> + QTAILQ_FOREACH(entry, &stats_callbacks, next) {
> + entry->schemas_cb(&stats_results, errp);
> + }
> +
> + return stats_results;
> +}
> +
> +void add_stats_entry(StatsResultList **stats_results, StatsProvider provider,
> + const char *qom_path, StatsList *stats_list)
> +{
> + StatsResult *entry = g_new0(StatsResult, 1);
> + entry->provider = provider;
> + if (qom_path) {
> + entry->has_qom_path = true;
> + entry->qom_path = g_strdup(qom_path);
> + }
> + entry->stats = stats_list;
> +
> + QAPI_LIST_PREPEND(*stats_results, entry);
> +}
> +
> +void add_stats_schema(StatsSchemaList **schema_results,
> + StatsProvider provider, StatsTarget target,
> + StatsSchemaValueList *stats_list)
> +{
> + StatsSchema *entry = g_new0(StatsSchema, 1);
> +
> + entry->provider = provider;
> + entry->target = target;
> + entry->stats = stats_list;
> + QAPI_LIST_PREPEND(*schema_results, entry);
> +}
> diff --git a/qapi/meson.build b/qapi/meson.build
> index 656ef0e039..fd5c93d643 100644
> --- a/qapi/meson.build
> +++ b/qapi/meson.build
> @@ -46,6 +46,7 @@ qapi_all_modules = [
> 'replay',
> 'run-state',
> 'sockets',
> + 'stats',
> 'trace',
> 'transaction',
> 'yank',
> diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json
> index 4912b9744e..92d7ecc52c 100644
> --- a/qapi/qapi-schema.json
> +++ b/qapi/qapi-schema.json
> @@ -93,3 +93,4 @@
> { 'include': 'audio.json' }
> { 'include': 'acpi.json' }
> { 'include': 'pci.json' }
> +{ 'include': 'stats.json' }
> diff --git a/qapi/stats.json b/qapi/stats.json
> new file mode 100644
> index 0000000000..7454dd7daa
> --- /dev/null
> +++ b/qapi/stats.json
> @@ -0,0 +1,192 @@
> +# -*- Mode: Python -*-
> +# vim: filetype=python
> +#
> +# Copyright (c) 2022 Oracle and/or its affiliates.
> +#
> +# This work is licensed under the terms of the GNU GPL, version 2 or later.
> +# See the COPYING file in the top-level directory.
> +#
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +
> +##
> +# = Statistics
> +##
> +
> +##
> +# @StatsType:
> +#
> +# Enumeration of statistics types
> +#
> +# @cumulative: stat is cumulative; value can only increase.
> +# @instant: stat is instantaneous; value can increase or decrease.
> +# @peak: stat is the peak value; value can only increase.
> +# @linear-hist: stat is a linear histogram.
> +# @log-hist: stat is a logarithmic histogram.
> +#
> +# Since: 7.1
> +##
> +{ 'enum' : 'StatsType',
> + 'data' : [ 'cumulative', 'instant', 'peak', 'linear-hist', 'log-hist' ] }
> +
> +##
> +# @StatsUnit:
> +#
> +# Enumeration of unit of measurement for statistics
> +#
> +# @bytes: stat reported in bytes.
> +# @seconds: stat reported in seconds.
> +# @cycles: stat reported in clock cycles.
> +#
> +# Since: 7.1
> +##
> +{ 'enum' : 'StatsUnit',
> + 'data' : [ 'bytes', 'seconds', 'cycles' ] }
> +
> +##
> +# @StatsProvider:
> +#
> +# Enumeration of statistics providers.
> +#
> +# Since: 7.1
> +##
> +{ 'enum': 'StatsProvider',
> + 'data': [ ] }
> +
> +##
> +# @StatsTarget:
> +#
> +# The kinds of objects on which one can request statistics.
> +#
> +# @vm: the entire virtual machine.
> +# @vcpu: a virtual CPU.
> +#
> +# Since: 7.1
> +##
> +{ 'enum': 'StatsTarget',
> + 'data': [ 'vm', 'vcpu' ] }
> +
> +##
> +# @StatsFilter:
> +#
> +# The arguments to the query-stats command; specifies a target for which to
> +# request statistics, and which statistics are requested from each provider.
> +#
> +# Since: 7.1
> +##
> +{ 'struct': 'StatsFilter',
> + 'data': { 'target': 'StatsTarget' } }
> +
> +##
> +# @StatsValue:
> +#
> +# @scalar: single uint64.
> +# @list: list of uint64.
> +#
> +# Since: 7.1
> +##
> +{ 'alternate': 'StatsValue',
> + 'data': { 'scalar': 'uint64',
> + 'list': [ 'uint64' ] } }
> +
> +##
> +# @Stats:
> +#
> +# @name: name of stat.
> +# @value: stat value.
> +#
> +# Since: 7.1
> +##
> +{ 'struct': 'Stats',
> + 'data': { 'name': 'str',
> + 'value' : 'StatsValue' } }
> +
> +##
> +# @StatsResult:
> +#
> +# @provider: provider for this set of statistics.
> +# @qom-path: QOM path of the object for which the statistics are returned
> +# @stats: list of statistics.
> +#
> +# Since: 7.1
> +##
> +{ 'struct': 'StatsResult',
> + 'data': { 'provider': 'StatsProvider',
> + '*qom-path': 'str',
> + 'stats': [ 'Stats' ] } }
> +
> +##
> +# @query-stats:
> +#
> +# Return runtime-collected statistics for objects such as the
> +# VM or its vCPUs.
> +#
> +# The arguments are a StatsFilter and specify the provider and objects
> +# to return statistics about.
> +#
> +# Returns: a list of StatsResult, one for each provider and object
> +# (e.g., for each vCPU).
> +#
> +# Since: 7.1
> +##
> +{ 'command': 'query-stats',
> + 'data': 'StatsFilter',
> + 'boxed': true,
> + 'returns': [ 'StatsResult' ] }
> +
> +##
> +# @StatsSchemaValue:
> +#
> +# Schema for a single statistic.
> +#
> +# @name: stat name.
> +#
> +# @type: kind of statistic, a @StatType.
> +#
> +# @unit: base unit of measurement for the statistics @StatUnit.
> +#
> +# @base: base for the multiple of @unit that the statistic uses, either 2 or 10.
> +# Only present if @exponent is non-zero.
> +#
> +# @exponent: exponent for the multiple of @unit that the statistic uses
> +#
> +# @bucket-size: Used with linear-hist to report the width of each bucket
> +# of the histogram.
> +#
> +# Since: 7.1
> +##
> +{ 'struct': 'StatsSchemaValue',
> + 'data': { 'name': 'str',
> + 'type': 'StatsType',
> + '*unit': 'StatsUnit',
> + '*base': 'int8',
> + 'exponent': 'int16',
> + '*bucket-size': 'uint32' } }
> +
> +##
> +# @StatsSchema:
> +#
> +# Schema for all available statistics for a provider and target.
> +#
> +# @provider: provider for this set of statistics.
> +#
> +# @target: kind of object that can be queried through this provider.
> +#
> +# @stats: list of statistics.
> +#
> +# Since: 7.1
> +##
> +{ 'struct': 'StatsSchema',
> + 'data': { 'provider': 'StatsProvider',
> + 'target': 'StatsTarget',
> + 'stats': [ 'StatsSchemaValue' ] } }
> +
> +##
> +# @query-stats-schemas:
> +#
> +# Return the schema for all available runtime-collected statistics.
> +#
> +# Since: 7.1
> +##
> +{ 'command': 'query-stats-schemas',
> + 'data': { },
> + 'returns': [ 'StatsSchema' ] }
> --
> 2.35.1
>
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
next prev parent reply other threads:[~2022-04-27 9:23 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-26 14:16 [PATCH 0/8] qmp, hmp: statistics subsystem and KVM suport Paolo Bonzini
2022-04-26 14:16 ` [PATCH 1/8] qmp: Support for querying stats Paolo Bonzini
2022-04-27 9:19 ` Dr. David Alan Gilbert [this message]
2022-04-27 12:10 ` Paolo Bonzini
2022-05-04 13:22 ` Markus Armbruster
2022-05-05 7:10 ` Paolo Bonzini
2022-05-05 8:00 ` Daniel P. Berrangé
2022-05-05 13:28 ` Markus Armbruster
2022-05-05 13:39 ` Daniel P. Berrangé
2022-05-05 17:21 ` Dr. David Alan Gilbert
2022-05-05 13:58 ` Paolo Bonzini
2022-05-13 13:10 ` Markus Armbruster
2022-05-13 13:57 ` Paolo Bonzini
2022-05-13 14:35 ` Markus Armbruster
2022-05-13 15:50 ` Paolo Bonzini
2022-05-13 17:47 ` Markus Armbruster
2022-04-26 14:16 ` [PATCH 2/8] kvm: Support for querying fd-based stats Paolo Bonzini
2022-04-26 14:16 ` [PATCH 3/8] qmp: add filtering of statistics by target vCPU Paolo Bonzini
2022-05-05 13:45 ` Markus Armbruster
2022-05-05 13:59 ` Paolo Bonzini
2022-04-26 14:16 ` [PATCH 4/8] hmp: add basic "info stats" implementation Paolo Bonzini
2022-04-26 14:16 ` [PATCH 5/8] qmp: add filtering of statistics by provider Paolo Bonzini
2022-04-26 14:16 ` [PATCH 6/8] hmp: " Paolo Bonzini
2022-04-26 14:16 ` [PATCH 7/8] qmp: add filtering of statistics by name Paolo Bonzini
2022-04-27 12:01 ` Dr. David Alan Gilbert
2022-04-27 12:18 ` Paolo Bonzini
2022-04-27 12:34 ` Dr. David Alan Gilbert
2022-04-27 14:17 ` Paolo Bonzini
2022-04-27 15:16 ` Dr. David Alan Gilbert
2022-04-27 15:50 ` Paolo Bonzini
2022-04-27 17:16 ` Dr. David Alan Gilbert
2022-04-28 9:53 ` Paolo Bonzini
2022-04-26 14:16 ` [PATCH 8/8] hmp: " Paolo Bonzini
-- strict thread matches above, loose matches on Subject: below --
2022-05-23 15:05 [PATCH v4 0/8] qmp, hmp: statistics subsystem and KVM suport Paolo Bonzini
2022-05-23 15:07 ` [PATCH 1/8] qmp: Support for querying stats Paolo Bonzini
2022-05-24 10:41 ` Markus Armbruster
2022-05-24 16:47 ` Paolo Bonzini
2022-05-24 12:20 ` Markus Armbruster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YmkKsQ9rFh+Ydfsu@work-vm \
--to=dgilbert@redhat.com \
--cc=armbru@redhat.com \
--cc=berrange@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).