qmp: add filtering of statistics by provider
Allow retrieving the statistics from a specific provider only. This can be used in the future by HMP commands such as "info sync-profile" or "info profile". The next patch also adds filter-by-provider capabilities to the HMP equivalent of query-stats, "info stats". Example: { "execute": "query-stats", "arguments": { "target": "vm", "providers": [ { "provider": "kvm" } ] } } The QAPI is a bit more verbose than just a list of StatsProvider, so that it can be subsequently extended with filtering of statistics by name. If a provider is specified more than once in the filter, each request will be included separately in the output. Extracted from a patch by Mark Kanda. Reviewed-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
433815f5bd
commit
068cc51d42
|
@ -2644,7 +2644,8 @@ static int kvm_init(MachineState *ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kvm_check_extension(kvm_state, KVM_CAP_BINARY_STATS_FD)) {
|
if (kvm_check_extension(kvm_state, KVM_CAP_BINARY_STATS_FD)) {
|
||||||
add_stats_callbacks(query_stats_cb, query_stats_schemas_cb);
|
add_stats_callbacks(STATS_PROVIDER_KVM, query_stats_cb,
|
||||||
|
query_stats_schemas_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -17,10 +17,12 @@ typedef void SchemaRetrieveFunc(StatsSchemaList **result, Error **errp);
|
||||||
/*
|
/*
|
||||||
* Register callbacks for the QMP query-stats command.
|
* Register callbacks for the QMP query-stats command.
|
||||||
*
|
*
|
||||||
|
* @provider: stats provider checked against QMP command arguments
|
||||||
* @stats_fn: routine to query stats:
|
* @stats_fn: routine to query stats:
|
||||||
* @schema_fn: routine to query stat schemas:
|
* @schema_fn: routine to query stat schemas:
|
||||||
*/
|
*/
|
||||||
void add_stats_callbacks(StatRetrieveFunc *stats_fn,
|
void add_stats_callbacks(StatsProvider provider,
|
||||||
|
StatRetrieveFunc *stats_fn,
|
||||||
SchemaRetrieveFunc *schemas_fn);
|
SchemaRetrieveFunc *schemas_fn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -2397,7 +2397,7 @@ void hmp_info_stats(Monitor *mon, const QDict *qdict)
|
||||||
goto exit_no_print;
|
goto exit_no_print;
|
||||||
}
|
}
|
||||||
|
|
||||||
schema = qmp_query_stats_schemas(&err);
|
schema = qmp_query_stats_schemas(false, STATS_PROVIDER__MAX, &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
|
@ -445,6 +445,7 @@ HumanReadableText *qmp_x_query_irq(Error **errp)
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct StatsCallbacks {
|
typedef struct StatsCallbacks {
|
||||||
|
StatsProvider provider;
|
||||||
StatRetrieveFunc *stats_cb;
|
StatRetrieveFunc *stats_cb;
|
||||||
SchemaRetrieveFunc *schemas_cb;
|
SchemaRetrieveFunc *schemas_cb;
|
||||||
QTAILQ_ENTRY(StatsCallbacks) next;
|
QTAILQ_ENTRY(StatsCallbacks) next;
|
||||||
|
@ -453,10 +454,12 @@ typedef struct StatsCallbacks {
|
||||||
static QTAILQ_HEAD(, StatsCallbacks) stats_callbacks =
|
static QTAILQ_HEAD(, StatsCallbacks) stats_callbacks =
|
||||||
QTAILQ_HEAD_INITIALIZER(stats_callbacks);
|
QTAILQ_HEAD_INITIALIZER(stats_callbacks);
|
||||||
|
|
||||||
void add_stats_callbacks(StatRetrieveFunc *stats_fn,
|
void add_stats_callbacks(StatsProvider provider,
|
||||||
|
StatRetrieveFunc *stats_fn,
|
||||||
SchemaRetrieveFunc *schemas_fn)
|
SchemaRetrieveFunc *schemas_fn)
|
||||||
{
|
{
|
||||||
StatsCallbacks *entry = g_new(StatsCallbacks, 1);
|
StatsCallbacks *entry = g_new(StatsCallbacks, 1);
|
||||||
|
entry->provider = provider;
|
||||||
entry->stats_cb = stats_fn;
|
entry->stats_cb = stats_fn;
|
||||||
entry->schemas_cb = schemas_fn;
|
entry->schemas_cb = schemas_fn;
|
||||||
|
|
||||||
|
@ -465,12 +468,18 @@ void add_stats_callbacks(StatRetrieveFunc *stats_fn,
|
||||||
|
|
||||||
static bool invoke_stats_cb(StatsCallbacks *entry,
|
static bool invoke_stats_cb(StatsCallbacks *entry,
|
||||||
StatsResultList **stats_results,
|
StatsResultList **stats_results,
|
||||||
StatsFilter *filter,
|
StatsFilter *filter, StatsRequest *request,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
strList *targets = NULL;
|
strList *targets = NULL;
|
||||||
ERRP_GUARD();
|
ERRP_GUARD();
|
||||||
|
|
||||||
|
if (request) {
|
||||||
|
if (request->provider != entry->provider) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (filter->target) {
|
switch (filter->target) {
|
||||||
case STATS_TARGET_VM:
|
case STATS_TARGET_VM:
|
||||||
break;
|
break;
|
||||||
|
@ -500,29 +509,43 @@ StatsResultList *qmp_query_stats(StatsFilter *filter, Error **errp)
|
||||||
{
|
{
|
||||||
StatsResultList *stats_results = NULL;
|
StatsResultList *stats_results = NULL;
|
||||||
StatsCallbacks *entry;
|
StatsCallbacks *entry;
|
||||||
|
StatsRequestList *request;
|
||||||
|
|
||||||
QTAILQ_FOREACH(entry, &stats_callbacks, next) {
|
QTAILQ_FOREACH(entry, &stats_callbacks, next) {
|
||||||
if (!invoke_stats_cb(entry, &stats_results, filter, errp)) {
|
if (filter->has_providers) {
|
||||||
|
for (request = filter->providers; request; request = request->next) {
|
||||||
|
if (!invoke_stats_cb(entry, &stats_results, filter,
|
||||||
|
request->value, errp)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (!invoke_stats_cb(entry, &stats_results, filter, NULL, errp)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return stats_results;
|
return stats_results;
|
||||||
}
|
}
|
||||||
|
|
||||||
StatsSchemaList *qmp_query_stats_schemas(Error **errp)
|
StatsSchemaList *qmp_query_stats_schemas(bool has_provider,
|
||||||
|
StatsProvider provider,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
StatsSchemaList *stats_results = NULL;
|
StatsSchemaList *stats_results = NULL;
|
||||||
StatsCallbacks *entry;
|
StatsCallbacks *entry;
|
||||||
ERRP_GUARD();
|
ERRP_GUARD();
|
||||||
|
|
||||||
QTAILQ_FOREACH(entry, &stats_callbacks, next) {
|
QTAILQ_FOREACH(entry, &stats_callbacks, next) {
|
||||||
|
if (!has_provider || provider == entry->provider) {
|
||||||
entry->schemas_cb(&stats_results, errp);
|
entry->schemas_cb(&stats_results, errp);
|
||||||
if (*errp) {
|
if (*errp) {
|
||||||
qapi_free_StatsSchemaList(stats_results);
|
qapi_free_StatsSchemaList(stats_results);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return stats_results;
|
return stats_results;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,18 @@
|
||||||
{ 'enum': 'StatsTarget',
|
{ 'enum': 'StatsTarget',
|
||||||
'data': [ 'vm', 'vcpu' ] }
|
'data': [ 'vm', 'vcpu' ] }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @StatsRequest:
|
||||||
|
#
|
||||||
|
# Indicates a set of statistics that should be returned by query-stats.
|
||||||
|
#
|
||||||
|
# @provider: provider for which to return statistics.
|
||||||
|
#
|
||||||
|
# Since: 7.1
|
||||||
|
##
|
||||||
|
{ 'struct': 'StatsRequest',
|
||||||
|
'data': { 'provider': 'StatsProvider' } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @StatsVCPUFilter:
|
# @StatsVCPUFilter:
|
||||||
#
|
#
|
||||||
|
@ -86,11 +98,14 @@
|
||||||
# request statistics and optionally the required subset of information for
|
# request statistics and optionally the required subset of information for
|
||||||
# that target:
|
# that target:
|
||||||
# - which vCPUs to request statistics for
|
# - which vCPUs to request statistics for
|
||||||
|
# - which providers to request statistics from
|
||||||
#
|
#
|
||||||
# Since: 7.1
|
# Since: 7.1
|
||||||
##
|
##
|
||||||
{ 'union': 'StatsFilter',
|
{ 'union': 'StatsFilter',
|
||||||
'base': { 'target': 'StatsTarget' },
|
'base': {
|
||||||
|
'target': 'StatsTarget',
|
||||||
|
'*providers': [ 'StatsRequest' ] },
|
||||||
'discriminator': 'target',
|
'discriminator': 'target',
|
||||||
'data': { 'vcpu': 'StatsVCPUFilter' } }
|
'data': { 'vcpu': 'StatsVCPUFilter' } }
|
||||||
|
|
||||||
|
@ -226,5 +241,5 @@
|
||||||
# Since: 7.1
|
# Since: 7.1
|
||||||
##
|
##
|
||||||
{ 'command': 'query-stats-schemas',
|
{ 'command': 'query-stats-schemas',
|
||||||
'data': { },
|
'data': { '*provider': 'StatsProvider' },
|
||||||
'returns': [ 'StatsSchema' ] }
|
'returns': [ 'StatsSchema' ] }
|
||||||
|
|
Loading…
Reference in New Issue