[libvirt] [PATCH v2 3/3] add per cpu stats to all domain stats

Nikolay Shirokovskiy nshirokovskiy at virtuozzo.com
Thu Feb 2 11:09:33 UTC 2017


Add per host cpu info provided in virDomainGetCPUStats to the
stats provided in virConnectGetAllDomainStats. Namely:

"cpu.count" - number of host cpus
"cpu.<num>.time" - total cpu time spent for this domain in nanoseconds
"cpu.<num>.vtime" - time spent in virtual cpu threads for this domain
                    in nanoseconds
---
 docs/news.xml                    |  9 ++++++
 include/libvirt/libvirt-domain.h |  1 +
 src/libvirt-domain.c             |  7 +++++
 src/qemu/qemu_driver.c           | 64 ++++++++++++++++++++++++++++++++++++++++
 tools/virsh-domain-monitor.c     |  7 +++++
 tools/virsh.pod                  | 11 +++++--
 6 files changed, 97 insertions(+), 2 deletions(-)

diff --git a/docs/news.xml b/docs/news.xml
index f408293..6e40c33 100644
--- a/docs/news.xml
+++ b/docs/news.xml
@@ -42,6 +42,15 @@
           Allow setting MTU size for some types of domain interface.
         </description>
       </change>
+      <change>
+        <summary>
+          Show per host cpu stats in all domain stats
+        </summary>
+        <description>
+          Show stats provided in virDomainGetCPUStats in all domain stats
+          as well.
+        </description>
+      </change>
     </section>
     <section title="Bug fixes">
       <change>
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index e303140..2691ebe 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -2020,6 +2020,7 @@ typedef enum {
     VIR_DOMAIN_STATS_INTERFACE = (1 << 4), /* return domain interfaces info */
     VIR_DOMAIN_STATS_BLOCK = (1 << 5), /* return domain block info */
     VIR_DOMAIN_STATS_PERF = (1 << 6), /* return domain perf event info */
+    VIR_DOMAIN_STATS_PER_CPU = (1 << 7), /* return domain per host CPU info */
 } virDomainStatsTypes;
 
 typedef enum {
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 5b3e842..3726938 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -11126,6 +11126,13 @@ virConnectGetDomainCapabilities(virConnectPtr conn,
  *     "cpu.system" - system cpu time spent in nanoseconds as unsigned long
  *                    long.
  *
+ * VIR_DOMAIN_STATS_PER_CPU:
+ *     Return per host CPU statistics
+ *     "cpu.count" - number of host cpus
+ *     "cpu.<num>.time" - total cpu time spent for this domain in nanoseconds
+ *     "cpu.<num>.vtime" - time spent in virtual cpu threads for this domain
+ *                         in nanoseconds
+ *
  * VIR_DOMAIN_STATS_BALLOON:
  *     Return memory balloon device information.
  *     The typed parameter keys are in this format:
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 088f55e..d457a71 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -18806,6 +18806,69 @@ qemuDomainGetStatsCpu(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
 }
 
 static int
+qemuDomainGetStatsPerCpu(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
+                         virDomainObjPtr dom,
+                         virDomainStatsRecordPtr record,
+                         int *maxparams,
+                         unsigned int privflags ATTRIBUTE_UNUSED)
+{
+    qemuDomainObjPrivatePtr priv = dom->privateData;
+    virCgroupCpuStats stats = {0};
+    virBitmapPtr guestvcpus = NULL;
+    char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
+    int ncpus;
+    size_t i;
+    int ret = -1;
+
+    if (qemuDomainHasVcpuPids(dom))
+        guestvcpus = virDomainDefGetOnlineVcpumap(dom->def);
+
+    ncpus = virCgroupGetCpuStats(priv->cgroup, guestvcpus, &stats);
+
+    if (ncpus > 0) {
+        if (virTypedParamsAddUInt(&record->params,
+                                  &record->nparams,
+                                  maxparams,
+                                  "cpu.count",
+                                  ncpus) < 0)
+            goto cleanup;
+
+        for (i = 0; i < ncpus; i++) {
+            snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
+                     "cpu.%zu.time", i);
+            if (virTypedParamsAddULLong(&record->params,
+                                        &record->nparams,
+                                        maxparams,
+                                        param_name,
+                                        stats.time[i]) < 0)
+                goto cleanup;
+
+
+            if (stats.vtime) {
+                snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
+                         "cpu.%zu.vtime", i);
+                if (virTypedParamsAddULLong(&record->params,
+                                            &record->nparams,
+                                            maxparams,
+                                            param_name,
+                                            stats.vtime[i]) < 0)
+                    goto cleanup;
+            }
+        }
+    }
+
+    ret = 0;
+
+ cleanup:
+    if (!ret && virGetLastError())
+        virResetLastError();
+    virBitmapFree(guestvcpus);
+    virCgroupCpuStatsFree(&stats);
+
+    return ret;
+}
+
+static int
 qemuDomainGetStatsBalloon(virQEMUDriverPtr driver,
                           virDomainObjPtr dom,
                           virDomainStatsRecordPtr record,
@@ -19381,6 +19444,7 @@ struct qemuDomainGetStatsWorker {
 static struct qemuDomainGetStatsWorker qemuDomainGetStatsWorkers[] = {
     { qemuDomainGetStatsState, VIR_DOMAIN_STATS_STATE, false },
     { qemuDomainGetStatsCpu, VIR_DOMAIN_STATS_CPU_TOTAL, false },
+    { qemuDomainGetStatsPerCpu, VIR_DOMAIN_STATS_PER_CPU, false },
     { qemuDomainGetStatsBalloon, VIR_DOMAIN_STATS_BALLOON, true },
     { qemuDomainGetStatsVcpu, VIR_DOMAIN_STATS_VCPU, true },
     { qemuDomainGetStatsInterface, VIR_DOMAIN_STATS_INTERFACE, false },
diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index 77aa272..7707a96 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -1953,6 +1953,10 @@ static const vshCmdOptDef opts_domstats[] = {
      .type = VSH_OT_BOOL,
      .help = N_("report domain physical cpu usage"),
     },
+    {.name = "per-cpu",
+     .type = VSH_OT_BOOL,
+     .help = N_("report domain per physical cpu usage"),
+    },
     {.name = "balloon",
      .type = VSH_OT_BOOL,
      .help = N_("report domain balloon statistics"),
@@ -2072,6 +2076,9 @@ cmdDomstats(vshControl *ctl, const vshCmd *cmd)
     if (vshCommandOptBool(cmd, "cpu-total"))
         stats |= VIR_DOMAIN_STATS_CPU_TOTAL;
 
+    if (vshCommandOptBool(cmd, "per-cpu"))
+        stats |= VIR_DOMAIN_STATS_PER_CPU;
+
     if (vshCommandOptBool(cmd, "balloon"))
         stats |= VIR_DOMAIN_STATS_BALLOON;
 
diff --git a/tools/virsh.pod b/tools/virsh.pod
index a470409..c10a4ee 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -860,8 +860,9 @@ I<snapshot-create> for disk snapshots) will accept either target
 or unique source names printed by this command.
 
 =item B<domstats> [I<--raw>] [I<--enforce>] [I<--backing>] [I<--state>]
-[I<--cpu-total>] [I<--balloon>] [I<--vcpu>] [I<--interface>] [I<--block>]
-[I<--perf>] [[I<--list-active>] [I<--list-inactive>] [I<--list-persistent>]
+[I<--cpu-total>] [I<--per-cpu>] [I<--balloon>] [I<--vcpu>] [I<--interface>]
+[I<--block>] [I<--perf>]
+[[I<--list-active>] [I<--list-inactive>] [I<--list-persistent>]
 [I<--list-transient>] [I<--list-running>] [I<--list-paused>]
 [I<--list-shutoff>] [I<--list-other>]] | [I<domain> ...]
 
@@ -894,6 +895,12 @@ I<--cpu-total> returns:
 "cpu.user" - user cpu time spent in nanoseconds,
 "cpu.system" - system cpu time spent in nanoseconds
 
+I<--per-cpu> returns:
+"cpu.count" - number of host cpus,
+"cpu.<num>.time" - total cpu time spent for this domain in nanoseconds,
+"cpu.<num>.vtime" - time spent in virtual cpu threads for this domain
+in nanoseconds.
+
 I<--balloon> returns:
 "balloon.current" - the memory in kiB currently used,
 "balloon.maximum" - the maximum memory in kiB allowed,
-- 
1.8.3.1




More information about the libvir-list mailing list