From: Tyrel D. <ty...@us...> - 2011-05-11 01:43:01
|
Update of /cvsroot/sblim/gather/plugin In directory vz-cvs-3.sog:/tmp/cvs-serv28398/plugin Modified Files: metricKvm.c metricKvm.readme metricVirt.c metricVirt.h repositoryKvm.c Log Message: Fixed 3300216: new KVM scheduler counter metrics Index: metricVirt.c =================================================================== RCS file: /cvsroot/sblim/gather/plugin/metricVirt.c,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- metricVirt.c 19 Apr 2011 23:09:44 -0000 1.8 +++ metricVirt.c 11 May 2011 01:42:58 -0000 1.9 @@ -30,6 +30,14 @@ #include <stdio.h> #include <string.h> +#define PIDDIR "/var/run/libvirt/qemu/" +#define L_piddir 22 +#define PROC "/proc/" +#define TASK "/task/" +#define SCHED "/sched" +#define L_sched 32 +#define bufsize 4096 + static virConnectPtr conn; static int hyp_type; @@ -62,6 +70,108 @@ } /* ---------------------------------------------------------------------------*/ +/* collectDomainSchedStats */ +/* get scheduler statistics for a given domain */ +/* ---------------------------------------------------------------------------*/ + +static void collectDomainSchedStats(int cnt) +{ + FILE * fd = NULL; + char * pidfile = NULL; + char * tidfile = NULL; + char tmpfile[L_tmpnam]; + char cmdbuf[128]; + char buf[bufsize]; + int * tids = NULL; + int pid = 0; + int i; + + /* default stats to 0 in case of error */ + domain_statistics.cpu_used[cnt] = 0; + domain_statistics.cpu_ready[cnt] = 0; + + /* open libvirts pid file to obtain vm pid */ + pidfile = malloc(sizeof(char *) * + (strlen(domain_statistics.domain_name[cnt]) + L_piddir + 4 + 1)); + sprintf(pidfile, "%s%s.pid", PIDDIR, domain_statistics.domain_name[cnt]); + + if ((fd = fopen(pidfile, "r")) != NULL) { + if (fgets(buf, bufsize, fd) != NULL) { + sscanf(buf, "%d", &pid); + } + fclose(fd); + } + + free(pidfile); + + /* determine thread ids for each vcpu via ps */ + if (pid) { + if (tmpnam(tmpfile)) { + sprintf(cmdbuf, "ps --no-headers -p %d -Lo lwp > %s", pid, tmpfile); + if (system(cmdbuf) == 0) { + if ((fd = fopen(tmpfile, "r")) != NULL) { + /* ignore master thread (vm pid) */ + fgets(buf, bufsize, fd); + + tids = malloc(sizeof(int *) * domain_statistics.vcpus[cnt]); + + for (i = 0; i < domain_statistics.vcpus[cnt]; i++) { + fgets(buf, bufsize, fd); + sscanf(buf, "%d", &tids[i]); + } + fclose(fd); + } + } + remove(tmpfile); + } + } + + /* retrieve scheduler stats for each vcpu/tid */ + if (tids) { + tidfile = malloc(sizeof(char *) * (L_sched + 1)); + + /* for each vcpu/tid grab stats from /proc/$pid/task/$tid/sched */ + for (i = 0; i < domain_statistics.vcpus[cnt]; i++) { + float used, ready; + + if (tmpnam(tmpfile)) { + sprintf(tidfile, "%s%d%s%d%s", PROC, pid, TASK, tids[i], SCHED); + + /* interested in se.sum_exec_runtime and se.wait_sum */ + sprintf(cmdbuf, "cat %s | awk '/exec_runtime/ || /wait_sum/ {print $3}' > %s", + tidfile, tmpfile); + + /* stats are in floating point ms, convert to microseconds */ + if (system(cmdbuf) == 0) { + if ((fd = fopen(tmpfile, "r")) != NULL) { + fgets(buf, bufsize, fd); + sscanf(buf, "%f", &used); + used = used * 1000; + domain_statistics.cpu_used[cnt] += used; + + fgets(buf, bufsize, fd); + sscanf(buf, "%f", &ready); + ready = ready * 1000; + domain_statistics.cpu_ready[cnt] += ready; + + fclose(fd); + } + } + remove(tmpfile); + } + + } + + /* Average the sum of all stats across number of vcpus */ + domain_statistics.cpu_used[cnt] = domain_statistics.cpu_used[cnt] / domain_statistics.vcpus[cnt]; + domain_statistics.cpu_ready[cnt] = domain_statistics.cpu_ready[cnt] / domain_statistics.vcpus[cnt]; + + free(tidfile); + free(tids); + } +} + +/* ---------------------------------------------------------------------------*/ /* collectNodeStats */ /* get node statistics from libvirt API */ /* ---------------------------------------------------------------------------*/ @@ -176,6 +286,8 @@ domain_statistics.vcpus[cnt] = dinfo.nrVirtCpu; domain_statistics.state[cnt] = dinfo.state; + collectDomainSchedStats(cnt); + #ifdef DEBUG fprintf(stderr, "--- %s(%i) : %s (%d)\n\t claimed %lu max %lu\n\t time %f cpus %hu\n", __FILE__, __LINE__, domain_statistics.domain_name[cnt], *ids_ptr, dinfo.memory, dinfo.maxMem, @@ -214,6 +326,8 @@ domain_statistics.cpu_time[cnt] = ((float) dinfo.cpuTime) / 1000000000; domain_statistics.vcpus[cnt] = 0; domain_statistics.state[cnt] = dinfo.state; + domain_statistics.cpu_used[cnt] = 0; + domain_statistics.cpu_ready[cnt] = 0; virDomainFree(domain); @@ -594,3 +708,122 @@ return -1; } +/* ----------------------------------------------------------------------*/ +/* Scheduler Statistic Metrics */ +/* ----------------------------------------------------------------------*/ + +int virtMetricRetrCPUUsedTimeCounter(int mid, MetricReturner mret) +{ + MetricValue *mv = NULL; + +#ifdef DEBUG + fprintf(stderr, + "--- %s(%i) : Retrieving KVM Scheduler CPUUsedTimeCounter\n", + __FILE__, __LINE__); +#endif + + collectDomainStats(); + + if (mret == NULL) { +#ifdef DEBUG + fprintf(stderr, + "--- %s(%i) : Returner pointer is NULL\n", + __FILE__, __LINE__); +#endif + } else { +#ifdef DEBUG + fprintf(stderr, + "--- %s(%i) : Sampling for Scheduler CPUUsedTimeCounter metric\n", + __FILE__, __LINE__); +#endif + + int i; + +#ifdef DEBUG + fprintf(stderr, + "--- %s(%i) : num_active_domains %d\n", + __FILE__, __LINE__, node_statistics.num_active_domains); +#endif + + for (i = 0; i < node_statistics.total_domains; i++) { + + mv = calloc(1, sizeof(MetricValue) + + sizeof(unsigned long long) + + strlen(domain_statistics.domain_name[i]) + 1); + + if (mv) { + mv->mvId = mid; + mv->mvTimeStamp = time(NULL); + mv->mvDataType = MD_UINT64; + mv->mvDataLength = sizeof(unsigned long long); + mv->mvData = (char *) mv + sizeof(MetricValue); + *(unsigned long long *) mv->mvData = htonll(domain_statistics.cpu_used[i]); + mv->mvResource = (char *) mv + sizeof(MetricValue) + sizeof(unsigned long long); + strcpy(mv->mvResource, domain_statistics.domain_name[i]); + mret(mv); + } + } + + return 1; + } + + return -1; +} + +int virtMetricRetrCPUReadyTimeCounter(int mid, MetricReturner mret) +{ + MetricValue *mv = NULL; + +#ifdef DEBUG + fprintf(stderr, + "--- %s(%i) : Retrieving KVM Scheduler CPUReadyTimeCounter\n", + __FILE__, __LINE__); +#endif + + collectDomainStats(); + + if (mret == NULL) { +#ifdef DEBUG + fprintf(stderr, + "--- %s(%i) : Returner pointer is NULL\n", + __FILE__, __LINE__); +#endif + } else { +#ifdef DEBUG + fprintf(stderr, + "--- %s(%i) : Sampling for Scheduler CPUReadyTimeCounter metric\n", + __FILE__, __LINE__); +#endif + + int i; + +#ifdef DEBUG + fprintf(stderr, + "--- %s(%i) : num_active_domains %d\n", + __FILE__, __LINE__, node_statistics.num_active_domains); +#endif + + for (i = 0; i < node_statistics.total_domains; i++) { + + mv = calloc(1, sizeof(MetricValue) + + sizeof(unsigned long long) + + strlen(domain_statistics.domain_name[i]) + 1); + + if (mv) { + mv->mvId = mid; + mv->mvTimeStamp = time(NULL); + mv->mvDataType = MD_UINT64; + mv->mvDataLength = sizeof(unsigned long long); + mv->mvData = (char *) mv + sizeof(MetricValue); + *(unsigned long long *) mv->mvData = htonll(domain_statistics.cpu_ready[i]); + mv->mvResource = (char *) mv + sizeof(MetricValue) + sizeof(unsigned long long); + strcpy(mv->mvResource, domain_statistics.domain_name[i]); + mret(mv); + } + } + + return 1; + } + + return -1; +} Index: repositoryKvm.c =================================================================== RCS file: /cvsroot/sblim/gather/plugin/repositoryKvm.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- repositoryKvm.c 8 Oct 2010 01:01:34 -0000 1.7 +++ repositoryKvm.c 11 May 2011 01:42:58 -0000 1.8 @@ -50,7 +50,7 @@ /* ---------------------------------------------------------------------------*/ -static MetricCalculationDefinition metricCalcDef[15]; +static MetricCalculationDefinition metricCalcDef[17]; // metric _Internal_CPUTime static MetricCalculator metricCalcCPUTime; @@ -85,10 +85,20 @@ // metric VirtualSystemState static MetricCalculator metricCalcVirtualSystemState; +// metric SchedulerStats +static MetricCalculator metricCalcSchedulerStats; + +// metric SumExecRuntime +// static MetricCalculator metricCalcSumExecRuntime + +// metric WaitSum +// static MetricCalculator metricCalcWaitSum + /* unit definitions */ static char *muKiloBytes = "Kilobytes"; static char *muPercent = "Percent"; +static char *muMicroSeconds = "MicroSeconds"; static char *muMilliSeconds = "MilliSeconds"; static char *muSeconds = "Seconds"; static char *muNA = "N/A"; @@ -295,7 +305,31 @@ metricCalcDef[14].mcCalc = metricCalcVirtualSystemState; metricCalcDef[14].mcUnits = muNA; - *mcnum = 15; + metricCalcDef[15].mcVersion = MD_VERSION; + metricCalcDef[15].mcName = "CPUUsedTimeCounter"; + metricCalcDef[15].mcId = mr(pluginname, metricCalcDef[15].mcName); + metricCalcDef[15].mcMetricType = + MD_PERIODIC | MD_RETRIEVED | MD_POINT; + metricCalcDef[15].mcChangeType = MD_COUNTER; + metricCalcDef[15].mcIsContinuous = MD_TRUE; + metricCalcDef[15].mcCalculable = MD_NONSUMMABLE; + metricCalcDef[15].mcDataType = MD_UINT64; + metricCalcDef[15].mcCalc = metricCalcSchedulerStats; + metricCalcDef[15].mcUnits = muMicroSeconds; + + metricCalcDef[16].mcVersion = MD_VERSION; + metricCalcDef[16].mcName = "CPUReadyTimeCounter"; + metricCalcDef[16].mcId = mr(pluginname, metricCalcDef[16].mcName); + metricCalcDef[16].mcMetricType = + MD_PERIODIC | MD_RETRIEVED | MD_POINT; + metricCalcDef[16].mcChangeType = MD_COUNTER; + metricCalcDef[16].mcIsContinuous = MD_TRUE; + metricCalcDef[16].mcCalculable = MD_NONSUMMABLE; + metricCalcDef[16].mcDataType = MD_UINT64; + metricCalcDef[16].mcCalc = metricCalcSchedulerStats; + metricCalcDef[16].mcUnits = muMicroSeconds; + + *mcnum = 17; *mc = metricCalcDef; return 0; } @@ -637,5 +671,26 @@ } /* ---------------------------------------------------------------------------*/ +/* Scheduler Statistics */ +/* ---------------------------------------------------------------------------*/ + +size_t metricCalcSchedulerStats(MetricValue * mv, + int mnum, void *v, size_t vlen) +{ +#ifdef DEBUG + fprintf(stderr, "Raw Scheduler Statistics\n"); +#endif + + /* plain copy */ + if (mv && (vlen >= mv->mvDataLength) && (mnum == 1) ) { + memcpy(v, mv->mvData, mv->mvDataLength); + *(unsigned long long *) v = ntohll(*(unsigned long long *) v); + return mv->mvDataLength; + } + + return -1; +} + +/* ---------------------------------------------------------------------------*/ /* end of repositoryKvm.c */ /* ---------------------------------------------------------------------------*/ Index: metricVirt.h =================================================================== RCS file: /cvsroot/sblim/gather/plugin/metricVirt.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- metricVirt.h 19 Apr 2010 23:58:19 -0000 1.4 +++ metricVirt.h 11 May 2011 01:42:58 -0000 1.5 @@ -48,6 +48,8 @@ float cpu_time[MAX_DOMAINS]; unsigned short vcpus[MAX_DOMAINS]; unsigned char state[MAX_DOMAINS]; + unsigned long long cpu_used[MAX_DOMAINS]; + unsigned long long cpu_ready[MAX_DOMAINS]; } domain_statistics; int connectHypervisor(int type); @@ -58,5 +60,7 @@ MetricRetriever virtMetricRetrInternalMemory; MetricRetriever virtMetricRetrHostFreePhysicalMemory; MetricRetriever virtMetricRetrVirtualSystemState; +MetricRetriever virtMetricRetrCPUUsedTimeCounter; +MetricRetriever virtMetricRetrCPUReadyTimeCounter; #endif Index: metricKvm.readme =================================================================== RCS file: /cvsroot/sblim/gather/plugin/metricKvm.readme,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- metricKvm.readme 4 Aug 2010 23:24:36 -0000 1.4 +++ metricKvm.readme 11 May 2011 01:42:58 -0000 1.5 @@ -32,6 +32,8 @@ - PhysicalMemoryAllocatedToVirtualSystemPercentage - HostMemoryPercentage - VirtualSystemState +- CPUUsedTimeCounter +- CPUReadyTimeCounter plus the following metrics which are only intended for internal usage: - _Internal_CPUTime @@ -132,3 +134,22 @@ Sample Interval : 60 sec CIM Data Type : unit32 Units : None + + +CPUUsedTimeCounter +------------------ + +Metric Type : Point +Sample Interval : 60 sec +CIM Data Type : uint64 +Units : MicroSeconds + + +CPUReadyTimeCounter +------------------- + +Metric Type : Point +Sample Interval : 60 sec +CIM Data Type : uint64 +Units : MicroSeconds + Index: metricKvm.c =================================================================== RCS file: /cvsroot/sblim/gather/plugin/metricKvm.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- metricKvm.c 4 Aug 2010 23:24:36 -0000 1.4 +++ metricKvm.c 11 May 2011 01:42:58 -0000 1.5 @@ -45,7 +45,7 @@ #include <ctype.h> /* --- metric callback retrievers to be exported --- */ -static MetricDefinition metricDef[8]; +static MetricDefinition metricDef[10]; /* --- required plugin functions --- */ int _DefinedMetrics(MetricRegisterId * mr, @@ -141,7 +141,23 @@ metricDef[7].mproc = virtMetricRetrVirtualSystemState; metricDef[7].mdeal = free; - *mdnum = 8; + metricDef[8].mdVersion = MD_VERSION; + metricDef[8].mdName = "CPUUsedTimeCounter"; + metricDef[8].mdReposPluginName = "librepositoryKvm.so"; + metricDef[8].mdId = mr(pluginname, metricDef[8].mdName); + metricDef[8].mdSampleInterval = 60; + metricDef[8].mproc = virtMetricRetrCPUUsedTimeCounter; + metricDef[8].mdeal = free; + + metricDef[9].mdVersion = MD_VERSION; + metricDef[9].mdName = "CPUReadyTimeCounter"; + metricDef[9].mdReposPluginName = "librepositoryKvm.so"; + metricDef[9].mdId = mr(pluginname, metricDef[9].mdName); + metricDef[9].mdSampleInterval = 60; + metricDef[9].mproc = virtMetricRetrCPUReadyTimeCounter; + metricDef[9].mdeal = free; + + *mdnum = 10; } else { *mdnum = 0; } |