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, with options for specifying a stat name and schema type. A schema type is the set of stats associated with a given component (e.g. vm or vcpu). - query-stats-schemas Returns a list of stats included in each schema type, with an option for specifying the schema name. - query-stats-instances Returns a list of stat instances and their associated schema type. The framework provides a method to register callbacks for these qmp commands. The first usecase will be for fd-based KVM stats (in an upcoming patch). Examples (with fd-based KVM stats): { "execute": "query-stats" } { "return": [ { "name": "vcpu_1", "type": "kvm-vcpu", "stats": [ { "name": "guest_mode", "unit": "none", "base": 10, "val": [ 0 ], "exponent": 0, "type": "instant" }, { "name": "directed_yield_successful", "unit": "none", "base": 10, "val": [ 0 ], "exponent": 0, "type": "cumulative" }, ... }, { "name": "vcpu_0", "type": "kvm-vcpu", "stats": ... ... }, { "name": "vm", "type": "kvm-vm", "stats": [ { "name": "max_mmu_page_hash_collisions", "unit": "none", "base": 10, "val": [ 0 ], "exponent": 0, "type": "peak" }, ... { "execute": "query-stats-schemas" } { "return": [ { "type": "kvm-vcpu", "stats": [ { "name": "guest_mode" }, { "name": "directed_yield_successful" }, ... }, { "type": "kvm-vm", "stats": [ { "name": "max_mmu_page_hash_collisions" }, { "name": "max_mmu_rmap_size" }, ... { "execute": "query-stats-instances" } { "return": [ { "name": "vcpu_1", "type": "kvm-vcpu" }, { "name": "vcpu_0", "type": "kvm-vcpu" }, { "name": "vm", "type": "kvm-vm" } ] } Signed-off-by: Mark Kanda <mark.ka...@oracle.com> --- include/monitor/monitor.h | 27 ++++++++ monitor/qmp-cmds.c | 71 +++++++++++++++++++ qapi/misc.json | 142 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 240 insertions(+) diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index 12d395d62d..14d3432ade 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -56,4 +56,31 @@ void monitor_register_hmp(const char *name, bool info, void monitor_register_hmp_info_hrt(const char *name, HumanReadableText *(*handler)(Error **errp)); +/* + * Add qmp stats callbacks to the stats_callbacks list. + * + * @name: name of stats callbacks + * @stats_fn: routine to query stats - with options for name and type: + * StatsList *(*stats_fn)(StatsList *list_tail, bool has_name, + * const char *name, bool has_type, const char *type, Error **errp) + * + * @schema_fn: routine to query stat schemas - with an option for type: + * StatsSchemaList *(*schemas_fn)(StatsSchemaList *list tail, bool has_type, + * const char *type, Error **errp) + * + * @instance_fn: routine to query stat instances: + * StatsInstanceList *(*instances_fn)(StatsInstanceList *list_tail, + * Error **errp) + */ +void add_stats_callbacks(const char *name, + StatsList *(*stats_fn)(StatsList *, + bool, const char *, + bool, const char *, + Error **), + StatsSchemaList *(*schemas_fn)(StatsSchemaList *, + bool, const char *, + Error **), + StatsInstanceList *(*instances_fn)(StatsInstanceList *, + Error **)); + #endif /* MONITOR_H */ diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c index 343353e27a..c7bdff1e1c 100644 --- a/monitor/qmp-cmds.c +++ b/monitor/qmp-cmds.c @@ -466,3 +466,74 @@ HumanReadableText *qmp_x_query_irq(Error **errp) return human_readable_text_from_str(buf); } + +typedef struct StatsCallbacks { + char *name; + StatsList *(*stats_cb)(StatsList *, bool, const char *, bool, + const char *, Error **); + StatsSchemaList *(*schemas_cb)(StatsSchemaList *, bool, const char *, + Error **); + StatsInstanceList *(*instances_cb)(StatsInstanceList *, Error **); + QTAILQ_ENTRY(StatsCallbacks) next; +} StatsCallbacks; + +static QTAILQ_HEAD(, StatsCallbacks) stats_callbacks = + QTAILQ_HEAD_INITIALIZER(stats_callbacks); + +void add_stats_callbacks(const char *name, + StatsList *(*stats_fn)(StatsList *, + bool, const char *, + bool, const char *, + Error **), + StatsSchemaList *(*schemas_fn)(StatsSchemaList *, + bool, const char *, + Error **), + StatsInstanceList *(*instances_fn)(StatsInstanceList *, + Error **)) +{ + StatsCallbacks *entry = g_malloc0(sizeof(*entry)); + entry->name = strdup(name); + entry->stats_cb = stats_fn; + entry->schemas_cb = schemas_fn; + entry->instances_cb = instances_fn; + + QTAILQ_INSERT_TAIL(&stats_callbacks, entry, next); +} + +StatsList *qmp_query_stats(bool has_name, const char *name, bool has_type, + const char *type, Error **errp) { + StatsList *list_tail = NULL; + StatsCallbacks *entry; + + QTAILQ_FOREACH(entry, &stats_callbacks, next) { + list_tail = entry->stats_cb(list_tail, has_name, name, + has_type, type, errp); + } + + return list_tail; +} + +StatsSchemaList *qmp_query_stats_schemas(bool has_type, const char *type, + Error **errp) +{ + StatsSchemaList *list_tail = NULL; + StatsCallbacks *entry; + + QTAILQ_FOREACH(entry, &stats_callbacks, next) { + list_tail = entry->schemas_cb(list_tail, has_type, type, errp); + } + + return list_tail; +} + +StatsInstanceList *qmp_query_stats_instances(Error **errp) +{ + StatsInstanceList *list_tail = NULL; + StatsCallbacks *entry; + + QTAILQ_FOREACH(entry, &stats_callbacks, next) { + list_tail = entry->instances_cb(list_tail, errp); + } + + return list_tail; +} diff --git a/qapi/misc.json b/qapi/misc.json index 358548abe1..a0a07ef0b1 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -527,3 +527,145 @@ 'data': { '*option': 'str' }, 'returns': ['CommandLineOptionInfo'], 'allow-preconfig': true } + +## +# @StatType: +# +# Enumeration of stat 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. +# +# Since: 7.0 +## +{ 'enum' : 'StatType', + 'data' : [ 'cumulative', 'instant', 'peak' ] } + +## +# @StatUnit: +# +# Enumeration of stat units +# @bytes: stat reported in bytes. +# @seconds: stat reported in seconds. +# @cycles: stat reported in clock cycles. +# @none: no unit for this stat. +# +# Since: 7.0 +## +{ 'enum' : 'StatUnit', + 'data' : [ 'bytes', 'seconds', 'cycles', 'none' ] } + +## +# @StatData: +# +# Individual stat +# @name: Stat name +# @type: @StatType +# @unit: @StatUnit +# @base: Exponent base (2 or 10) +# @exponent: Used together with @base +# @val: List of uint64 values +# +# Since: 7.0 +## +{ 'struct': 'StatData', + 'data': { 'name': 'str', + 'type': 'StatType', + 'unit': 'StatUnit', + 'base': 'uint8', + 'exponent': 'int16', + 'val': [ 'uint64' ] } } + +## +# @Stats: +# +# Stats per resource (e.g. vm or vcpu) +# @name: Resource name +# @stats: List of @StatData +# +# Since: 7.0 +## +{ 'struct': 'Stats', + 'data': {'name': 'str', + 'type': 'StatSchemaType', + 'stats': [ 'StatData' ] } } + +## +# @query-stats: +# +# @name: Stat name (optional) +# @type: Type name (optional) +# Returns: List of @Stats +# +# Since: 7.0 +## +{ 'command': 'query-stats', + 'data': { '*name': 'str', '*type': 'str' }, + 'returns': [ 'Stats' ] } + +## +# @StatSchemaType: +# +# Enumeration of stats schema types +# +# Since: 7.0 +## +{ 'enum' : 'StatSchemaType', + 'data' : [ ] } + +## +# @StatSchemaEntry: +# +# Individual stat in a schema type +# +# Since: 7.0 +## +{ 'struct': 'StatSchemaEntry', + 'data': { 'name': 'str' } } + +## +# @StatsSchema: +# +# Stats per @StatSchemaType +# @type: @StatSchemaType +# @stats: @StatCchemaName +# +# Since: 7.0 +## +{ 'struct': 'StatsSchema', + 'data': { 'type': 'StatSchemaType', + 'stats': [ 'StatSchemaEntry' ] } } + +## +# @query-stats-schemas: +# +# @type: type name (optional) +# Returns: List of @StatsSchema +# +# Since: 7.0 +## +{ 'command': 'query-stats-schemas', + 'data': { '*type': 'str' }, + 'returns': [ 'StatsSchema' ] } + +## +# @StatsInstance: +# +# @name: resource name +# @type: @StatSchemaType +# +# Since: 7.0 +## +{ 'struct': 'StatsInstance', + 'data': { 'name': 'str', + 'type': 'StatSchemaType' } } + +## +# @query-stats-instances: +# +# Returns list of @StatsInstance +# +# Since: 7.0 +## +{ 'command': 'query-stats-instances', + 'returns': [ 'StatsInstance' ] } -- 2.26.2