Merge pull request #1341 from attivio/lxc-top-iops

attach batch mode with -b flag which prints csv output with a timestamp
This commit is contained in:
Christian Brauner 2016-12-06 14:25:32 +01:00 committed by GitHub
commit 862722a2c3

View File

@ -56,6 +56,7 @@ struct stats {
uint64_t cpu_use_user; uint64_t cpu_use_user;
uint64_t cpu_use_sys; uint64_t cpu_use_sys;
uint64_t blkio; uint64_t blkio;
uint64_t blkio_iops;
}; };
struct ct { struct ct {
@ -63,10 +64,11 @@ struct ct {
struct stats *stats; struct stats *stats;
}; };
static int batch = 0;
static int delay_set = 0;
static int delay = 3; static int delay = 3;
static char sort_by = 'n'; static char sort_by = 'n';
static int sort_reverse = 0; static int sort_reverse = 0;
static struct termios oldtios; static struct termios oldtios;
static struct ct *ct = NULL; static struct ct *ct = NULL;
static int ct_alloc_cnt = 0; static int ct_alloc_cnt = 0;
@ -75,9 +77,13 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
{ {
switch (c) { switch (c) {
case 'd': case 'd':
delay_set = 1;
if (lxc_safe_int(arg, &delay) < 0) if (lxc_safe_int(arg, &delay) < 0)
return -1; return -1;
break; break;
case 'b':
batch=1;
break;
case 's': case 's':
sort_by = arg[0]; sort_by = arg[0];
break; break;
@ -90,6 +96,7 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
static const struct option my_longopts[] = { static const struct option my_longopts[] = {
{"delay", required_argument, 0, 'd'}, {"delay", required_argument, 0, 'd'},
{"batch", no_argument, 0, 'b'},
{"sort", required_argument, 0, 's'}, {"sort", required_argument, 0, 's'},
{"reverse", no_argument, 0, 'r'}, {"reverse", no_argument, 0, 'r'},
LXC_COMMON_OPTIONS LXC_COMMON_OPTIONS
@ -104,6 +111,7 @@ lxc-top monitors the state of the active containers\n\
\n\ \n\
Options :\n\ Options :\n\
-d, --delay delay in seconds between refreshes (default: 3.0)\n\ -d, --delay delay in seconds between refreshes (default: 3.0)\n\
-b, --batch output designed to capture to a file\n\
-s, --sort sort by [n,c,b,m] (default: n) where\n\ -s, --sort sort by [n,c,b,m] (default: n) where\n\
n = Name\n\ n = Name\n\
c = CPU use\n\ c = CPU use\n\
@ -273,6 +281,7 @@ static void stats_get(struct lxc_container *c, struct ct *ct, struct stats *tota
ct->stats->cpu_use_user = stat_match_get_int(c, "cpuacct.stat", "user", 1); ct->stats->cpu_use_user = stat_match_get_int(c, "cpuacct.stat", "user", 1);
ct->stats->cpu_use_sys = stat_match_get_int(c, "cpuacct.stat", "system", 1); ct->stats->cpu_use_sys = stat_match_get_int(c, "cpuacct.stat", "system", 1);
ct->stats->blkio = stat_match_get_int(c, "blkio.throttle.io_service_bytes", "Total", 1); ct->stats->blkio = stat_match_get_int(c, "blkio.throttle.io_service_bytes", "Total", 1);
ct->stats->blkio_iops = stat_match_get_int(c, "blkio.throttle.io_serviced", "Total", 1);
if (total) { if (total) {
total->mem_used = total->mem_used + ct->stats->mem_used; total->mem_used = total->mem_used + ct->stats->mem_used;
@ -307,21 +316,39 @@ static void stats_print(const char *name, const struct stats *stats,
char blkio_str[20]; char blkio_str[20];
char mem_used_str[20]; char mem_used_str[20];
char kmem_used_str[20]; char kmem_used_str[20];
struct timeval time_val;
size_humanize(stats->blkio, blkio_str, sizeof(blkio_str)); unsigned long long time_ms;
size_humanize(stats->mem_used, mem_used_str, sizeof(mem_used_str));
if (!batch) {
printf("%-18.18s %12.2f %12.2f %12.2f %14s %10s", size_humanize(stats->blkio, blkio_str, sizeof(blkio_str));
name, size_humanize(stats->mem_used, mem_used_str, sizeof(mem_used_str));
(float)stats->cpu_use_nanos / 1000000000,
(float)stats->cpu_use_sys / USER_HZ, printf("%-18.18s %12.2f %12.2f %12.2f %14s %10s",
(float)stats->cpu_use_user / USER_HZ, name,
blkio_str, (float)stats->cpu_use_nanos / 1000000000,
mem_used_str); (float)stats->cpu_use_sys / USER_HZ,
if (total->kmem_used > 0) { (float)stats->cpu_use_user / USER_HZ,
size_humanize(stats->kmem_used, kmem_used_str, sizeof(kmem_used_str)); blkio_str,
printf(" %10s", kmem_used_str); mem_used_str);
if (total->kmem_used > 0) {
size_humanize(stats->kmem_used, kmem_used_str, sizeof(kmem_used_str));
printf(" %10s", kmem_used_str);
}
} else {
gettimeofday(&time_val, NULL);
time_ms = (unsigned long long) (time_val.tv_sec) * 1000 + (unsigned long long) (time_val.tv_usec) / 1000;
printf("%llu,%s,%lu,%lu,%lu,%lu,%lu,%lu,%lu",
time_ms,
name,
stats->cpu_use_nanos,
stats->cpu_use_sys,
stats->cpu_use_user,
stats->blkio,
stats->blkio_iops,
stats->mem_used,
stats->kmem_used);
} }
} }
static int cmp_name(const void *sct1, const void *sct2) static int cmp_name(const void *sct1, const void *sct2)
@ -430,7 +457,7 @@ int main(int argc, char *argv[])
struct lxc_epoll_descr descr; struct lxc_epoll_descr descr;
int ret, ct_print_cnt; int ret, ct_print_cnt;
char in_char; char in_char;
ret = EXIT_FAILURE; ret = EXIT_FAILURE;
if (lxc_arguments_parse(&my_args, argc, argv)) if (lxc_arguments_parse(&my_args, argc, argv))
goto out; goto out;
@ -458,6 +485,13 @@ int main(int argc, char *argv[])
goto err1; goto err1;
} }
if (batch && !delay_set) {
delay = 300;
}
if (batch) {
printf("time_ms,container,cpu_nanos,cpu_sys_userhz,cpu_user_userhz,blkio_bytes,blkio_iops,mem_used_bytes,kernel_mem_used_bytes\n");
}
for(;;) { for(;;) {
struct lxc_container **active; struct lxc_container **active;
int i, active_cnt; int i, active_cnt;
@ -473,43 +507,51 @@ int main(int argc, char *argv[])
ct_sort(active_cnt); ct_sort(active_cnt);
printf(TERMCLEAR); if (!batch) {
stats_print_header(&total); printf(TERMCLEAR);
stats_print_header(&total);
}
for (i = 0; i < active_cnt && i < ct_print_cnt; i++) { for (i = 0; i < active_cnt && i < ct_print_cnt; i++) {
stats_print(ct[i].c->name, ct[i].stats, &total); stats_print(ct[i].c->name, ct[i].stats, &total);
printf("\n"); printf("\n");
} }
sprintf(total_name, "TOTAL %d of %d", i, active_cnt); if (!batch) {
stats_print(total_name, &total, &total); sprintf(total_name, "TOTAL %d of %d", i, active_cnt);
stats_print(total_name, &total, &total);
}
fflush(stdout); fflush(stdout);
for (i = 0; i < active_cnt; i++) { for (i = 0; i < active_cnt; i++) {
lxc_container_put(ct[i].c); lxc_container_put(ct[i].c);
ct[i].c = NULL; ct[i].c = NULL;
} }
in_char = '\0'; in_char = '\0';
ret = lxc_mainloop(&descr, 1000 * delay); if (!batch) {
if (ret != 0 || in_char == 'q') ret = lxc_mainloop(&descr, 1000 * delay);
break; if (ret != 0 || in_char == 'q')
switch(in_char) { break;
case 'r': switch(in_char) {
sort_reverse ^= 1; case 'r':
break;
case 'n':
case 'c':
case 'b':
case 'm':
case 'k':
if (sort_by == in_char)
sort_reverse ^= 1; sort_reverse ^= 1;
else break;
sort_reverse = 0; case 'n':
sort_by = in_char; case 'c':
case 'b':
case 'm':
case 'k':
if (sort_by == in_char)
sort_reverse ^= 1;
else
sort_reverse = 0;
sort_by = in_char;
}
} else {
sleep(delay);
} }
} }
ret = EXIT_SUCCESS; ret = EXIT_SUCCESS;
err1: err1:
lxc_mainloop_close(&descr); lxc_mainloop_close(&descr);
out: out: