Hi varnish-dev, Attached is a patch to add custom field ordering to varnishstat. This way you can select (like before) individual fields to be shown using the -f switch, but fields will with patch also be displayed in the order you specify.
Any comments are appreciated. Regards, Martin Blix Grydeland -- Martin Blix Grydeland Varnish Software AS
diff --git a/bin/varnishstat/Makefile.am b/bin/varnishstat/Makefile.am index f6b9d49..7f30b79 100644 --- a/bin/varnishstat/Makefile.am +++ b/bin/varnishstat/Makefile.am @@ -10,7 +10,8 @@ varnishstat_SOURCES = \ varnishstat.h \ \ varnishstat.c \ - varnishstat_curses.c + varnishstat_curses.c \ + varnishstat_util.c varnishstat_LDADD = \ $(top_builddir)/lib/libvarnishcompat/libvarnishcompat.la \ diff --git a/bin/varnishstat/varnishstat.c b/bin/varnishstat/varnishstat.c index 139b64a..475832c 100644 --- a/bin/varnishstat/varnishstat.c +++ b/bin/varnishstat/varnishstat.c @@ -1,10 +1,12 @@ /*- * Copyright (c) 2006 Verdens Gang AS * Copyright (c) 2006-2010 Linpro AS + * Copyright (c) 2010 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp <[email protected]> * Author: Dag-Erling Smørgrav <[email protected]> + * Author: Martin Blix Grydeland <[email protected]> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -45,12 +47,16 @@ SVNID("$Id$") #include <unistd.h> #include "libvarnish.h" +#include "vqueue.h" +#include "miniobj.h" #include "vsc.h" #include "varnishapi.h" #include "varnishstat.h" /*--------------------------------------------------------------------*/ +struct stat stat; + static int do_xml_cb(void *priv, const struct vsc_point * const pt) { @@ -95,28 +101,27 @@ struct once_priv { }; static int -do_once_cb(void *priv, const struct vsc_point * const pt) +do_once_cb(void *priv, const struct stat_value * const sv) { struct once_priv *op; uint64_t val; int i; op = priv; - assert(!strcmp(pt->fmt, "uint64_t")); - val = *(const volatile uint64_t*)pt->ptr; + val = sv->val; i = 0; - if (strcmp(pt->class, "")) - i += printf("%s.", pt->class); - if (strcmp(pt->ident, "")) - i += printf("%s.", pt->ident); - i += printf("%s", pt->name); + if (strcmp(sv->class, "")) + i += printf("%s.", sv->class); + if (strcmp(sv->ident, "")) + i += printf("%s.", sv->ident); + i += printf("%s", sv->name); if (i > op->pad) op->pad = i + 1; printf("%*.*s", op->pad - i, op->pad - i, ""); - if (pt->flag == 'a') - printf("%12ju %12.2f %s\n", val, val / op->up, pt->desc); + if (sv->flag == 'a') + printf("%12ju %12.2f %s\n", val, val / op->up, sv->desc); else - printf("%12ju %12s %s\n", val, ". ", pt->desc); + printf("%12ju %12s %s\n", val, ". ", sv->desc); return (0); } @@ -129,7 +134,8 @@ do_once(struct VSM_data *vd, const struct vsc_main *VSC_main) op.up = VSC_main->uptime; op.pad = 18; - (void)VSC_Iter(vd, do_once_cb, &op); + (void)stat_gather(vd); + (void)stat_iter(do_once_cb, &op); } /*--------------------------------------------------------------------*/ @@ -197,10 +203,13 @@ main(int argc, char * const *argv) struct VSM_data *vd; const struct vsc_main *VSC_main; int delay = 1, once = 0, xml = 0; + int opt_f = 0; vd = VSM_New(); VSC_Setup(vd); + VTAILQ_INIT(&stat.so_list); + while ((c = getopt(argc, argv, VSC_ARGS "1f:lVw:x")) != -1) { switch (c) { case '1': @@ -220,6 +229,13 @@ main(int argc, char * const *argv) case 'x': xml = 1; break; + case 'f': + if (parse_f_opt(vd, optarg) < 0) + usage(); + if (VSC_Arg(vd, c, optarg) < 0) + usage(); + opt_f = 1; + break; default: if (VSC_Arg(vd, c, optarg) > 0) break; @@ -230,6 +246,9 @@ main(int argc, char * const *argv) if (VSC_Open(vd, 1)) exit(1); + if (!opt_f) + parse_f_opt(vd, "*"); + VSC_main = VSC_Main(vd); if (xml) diff --git a/bin/varnishstat/varnishstat.h b/bin/varnishstat/varnishstat.h index 594eaa8..f9d3d3c 100644 --- a/bin/varnishstat/varnishstat.h +++ b/bin/varnishstat/varnishstat.h @@ -27,4 +27,46 @@ * */ +#include "vqueue.h" + void do_curses(struct VSM_data *vd, const struct vsc_main *VSC_main, int delay); + +struct stat_value { + unsigned magic; +#define STAT_VALUE_MAGIC 0x62da0fc7 + VTAILQ_ENTRY(stat_value) next; + char *class; + char *ident; + char *name; + char *desc; + char flag; + uint64_t val; + const volatile uint64_t *ptr; +}; + +struct stat_order { + unsigned magic; +#define STAT_ORDER_MAGIC 0xb5f5592e + VTAILQ_ENTRY(stat_order) next; + int flags; +#define STAT_ORDER_CL_WC (1 << 0) +#define STAT_ORDER_ID_WC (1 << 1) +#define STAT_ORDER_NM_WC (1 << 2) + char *class; + char *ident; + char *name; + VTAILQ_HEAD(, stat_value) value_list; +}; + +struct stat { + unsigned magic; +#define STAT_MAGIC 0x38259467 + VTAILQ_HEAD(, stat_order) so_list; +}; +extern struct stat stat; + +typedef int stat_iter_f(void *priv, const struct stat_value * const sv); + +int parse_f_opt(struct VSM_data *vd, const char *optarg); +int stat_gather(struct VSM_data *vd); +int stat_iter(stat_iter_f *func, void *priv); diff --git a/bin/varnishstat/varnishstat_curses.c b/bin/varnishstat/varnishstat_curses.c index d00e0a6..825fd74 100644 --- a/bin/varnishstat/varnishstat_curses.c +++ b/bin/varnishstat/varnishstat_curses.c @@ -70,34 +70,33 @@ struct pt { static VTAILQ_HEAD(, pt) pthead = VTAILQ_HEAD_INITIALIZER(pthead); static int -do_curses_cb(void *priv, const struct vsc_point * const sp) +do_curses_cb(void *priv, const struct stat_value * const sv) { struct pt *pt; char buf[128]; (void)priv; - assert(!strcmp(sp->fmt, "uint64_t")); pt = calloc(sizeof *pt, 1); AN(pt); VTAILQ_INSERT_TAIL(&pthead, pt, next); - pt->ptr = sp->ptr; + pt->ptr = sv->ptr; pt->ref = *pt->ptr; - pt->type = sp->flag; + pt->type = sv->flag; *buf = '\0'; - if (strcmp(sp->class, "")) { - strcat(buf, sp->class); + if (strcmp(sv->class, "")) { + strcat(buf, sv->class); strcat(buf, "."); } - if (strcmp(sp->ident, "")) { - strcat(buf, sp->ident); + if (strcmp(sv->ident, "")) { + strcat(buf, sv->ident); strcat(buf, "."); } - strcat(buf, sp->name); + strcat(buf, sv->name); strcat(buf, " - "); - strcat(buf, sp->desc); + strcat(buf, sv->desc); pt->name = strdup(buf); AN(pt->name); return (0); @@ -114,7 +113,8 @@ prep_pts(struct VSM_data *vd) free(pt); } - (void)VSC_Iter(vd, do_curses_cb, NULL); + (void)stat_gather(vd); + (void)stat_iter(do_curses_cb, NULL); } static void @@ -176,6 +176,9 @@ do_curses(struct VSM_data *vd, const struct vsc_main *VSC_main, break; lact = act; + /* Refresh, needed to update derived values */ + stat_gather(vd); + AZ(gettimeofday(&tv, NULL)); tt = tv.tv_usec * 1e-6 + tv.tv_sec; lt = tt - lt; diff --git a/bin/varnishstat/varnishstat_util.c b/bin/varnishstat/varnishstat_util.c new file mode 100644 index 0000000..ec74c9d --- /dev/null +++ b/bin/varnishstat/varnishstat_util.c @@ -0,0 +1,191 @@ +/*- + * Copyright (c) 2010 Varnish Software AS + * All rights reserved. + * + * Author: Martin Blix Grydeland <[email protected]> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "libvarnish.h" +#include "vqueue.h" +#include "miniobj.h" +#include "vsc.h" +#include "varnishapi.h" +#include "varnishstat.h" + +static inline int +iter_test(const char *s1, const char *s2, int wc) +{ + if (s1 == NULL) + return (0); + if (!wc) + return (strcmp(s1, s2)); + for (; *s1 != '\0' && *s1 == *s2; s1++, s2++) { + continue; + } + return (*s1 != '\0'); +} + +static int +vsc_cb(void *priv, const struct vsc_point * const pt) +{ + uint64_t val; + int found; + struct stat_order *so; + struct stat_value *sv; + + assert(!strcmp(pt->fmt, "uint64_t")); + val = *(const volatile uint64_t*)pt->ptr; + + VTAILQ_FOREACH(so, &stat.so_list, next) { + CHECK_OBJ_NOTNULL(so, STAT_ORDER_MAGIC); + if (iter_test(so->class, pt->class, + so->flags & STAT_ORDER_CL_WC)) + continue; + if (iter_test(so->ident, pt->ident, + so->flags & STAT_ORDER_ID_WC)) + continue; + if (iter_test(so->name, pt->name, + so->flags & STAT_ORDER_NM_WC)) + continue; + found = 0; + VTAILQ_FOREACH(sv, &so->value_list, next) { + CHECK_OBJ_NOTNULL(sv, STAT_VALUE_MAGIC); + if (!strcmp(sv->class, pt->class) && + !strcmp(sv->ident, pt->ident) && + !strcmp(sv->name, pt->name)) { + found = 1; + sv->val = val; + sv->ptr = pt->ptr; + break; + } + } + if (found) + continue; + ALLOC_OBJ(sv, STAT_VALUE_MAGIC); + AN(sv); + REPLACE(sv->class, pt->class); + REPLACE(sv->ident, pt->ident); + REPLACE(sv->name, pt->name); + REPLACE(sv->desc, pt->desc); + sv->flag = pt->flag; + sv->val = val; + sv->ptr = pt->ptr; + VTAILQ_INSERT_TAIL(&so->value_list, sv, next); + } + + return (0); +} + +int +parse_f_opt(struct VSM_data *vd, const char *optarg) { + int i; + char **av, *q, *p; + struct stat_order *so; + + av = ParseArgv(optarg, ARGV_COMMA); + AN(av); + if (av[0] != NULL) { + fprintf(stderr, "Parse error: %s", av[0]); + FreeArgv(av); + return (-1); + } + for (i = 1; av[i] != NULL; i++) { + p = av[i]; + if (*p == '^') + continue; + ALLOC_OBJ(so, STAT_ORDER_MAGIC); + AN(so); + VTAILQ_INIT(&so->value_list); + VTAILQ_INSERT_TAIL(&stat.so_list, so, next); + q = strchr(p, '.'); + if (q != NULL) { + *q++ = '\0'; + if (*p != '\0') + REPLACE(so->class, p); + p = q; + if (*p != '\0') { + q = strchr(p, '.'); + if (q != NULL) { + *q++ = '\0'; + if (*p != '\0') + REPLACE(so->ident, p); + p = q; + } + } + } + if (*p != '\0') + REPLACE(so->name, p); + + /* Check for wildcards */ + if (so->class != NULL) { + q = strchr(so->class, '*'); + if (q != NULL && q[1] == '\0') { + *q = '\0'; + so->flags |= STAT_ORDER_CL_WC; + } + } + if (so->ident != NULL) { + q = strchr(so->ident, '*'); + if (q != NULL && q[1] == '\0') { + *q = '\0'; + so->flags |= STAT_ORDER_ID_WC; + } + } + if (so->name != NULL) { + q = strchr(so->name, '*'); + if (q != NULL && q[1] == '\0') { + *q = '\0'; + so->flags |= STAT_ORDER_NM_WC; + } + } + } + FreeArgv(av); + + return (1); +} + +int +stat_gather(struct VSM_data *vd) +{ + return (VSC_Iter(vd, vsc_cb, NULL)); +} + +int +stat_iter(stat_iter_f *func, void *priv) +{ + struct stat_order *so; + struct stat_value *sv; + + VTAILQ_FOREACH(so, &stat.so_list, next) { + CHECK_OBJ_NOTNULL(so, STAT_ORDER_MAGIC); + VTAILQ_FOREACH(sv, &so->value_list, next) { + CHECK_OBJ_NOTNULL(sv, STAT_VALUE_MAGIC); + (void)func(priv, sv); + } + } +}
_______________________________________________ varnish-dev mailing list [email protected] http://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev
