[experimental-ims] 98a29cb Implement support for custom output and profiles in varnishhist
Geoff Simmons
geoff at varnish-cache.org
Mon Jan 9 21:52:29 CET 2012
commit 98a29cbc3e345f008a3c169e522992445a95365d
Author: Tollef Fog Heen <tfheen at varnish-software.com>
Date: Fri Nov 4 12:00:47 2011 +0100
Implement support for custom output and profiles in varnishhist
Drop varnishsizes, since it's pointless now (you can get the same
functionality with varnishhist -p size)
diff --git a/bin/Makefile.am b/bin/Makefile.am
index 7bdddbb..9906c5e 100644
--- a/bin/Makefile.am
+++ b/bin/Makefile.am
@@ -3,5 +3,5 @@
SUBDIRS = varnishadm varnishd varnishlog varnishncsa varnishreplay varnishtest
if HAVE_CURSES
-SUBDIRS += varnishhist varnishstat varnishtop varnishsizes
+SUBDIRS += varnishhist varnishstat varnishtop
endif
diff --git a/bin/varnishhist/varnishhist.c b/bin/varnishhist/varnishhist.c
index 72bc84b..692eb81 100644
--- a/bin/varnishhist/varnishhist.c
+++ b/bin/varnishhist/varnishhist.c
@@ -52,11 +52,12 @@
#include "vcs.h"
#define HIST_N 2000 /* how far back we remember */
-#define HIST_LOW -6 /* low end of log range */
-#define HIST_HIGH 3 /* high end of log range */
-#define HIST_RANGE (HIST_HIGH - HIST_LOW)
#define HIST_RES 100 /* bucket resolution */
-#define HIST_BUCKETS (HIST_RANGE * HIST_RES)
+
+static int hist_low;
+static int hist_high;
+static int hist_range;
+static int hist_buckets;
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
@@ -64,10 +65,13 @@ static int delay = 1;
static unsigned rr_hist[HIST_N];
static unsigned nhist;
static unsigned next_hist;
-static unsigned bucket_miss[HIST_BUCKETS];
-static unsigned bucket_hit[HIST_BUCKETS];
+static unsigned *bucket_miss;
+static unsigned *bucket_hit;
static unsigned char hh[FD_SETSIZE];
static uint64_t bitmap[FD_SETSIZE];
+static double values[FD_SETSIZE];
+static char *format;
+static int match_tag;
static double log_ten;
@@ -95,11 +99,25 @@ static int scales[] = {
INT_MAX
};
+struct profile {
+ const char *name;
+ enum VSL_tag_e tag;
+ int field;
+ int hist_low;
+ int hist_high;
+} profiles[] = {
+ { .name = "responsetime", .tag = SLT_ReqEnd, .field = 5, .hist_low = -6, .hist_high = 3 },
+ { .name = "size", .tag = SLT_Length, .field = 1, .hist_low = 1, .hist_high = 8 },
+ { 0 }
+};
+
+static struct profile *active_profile;
+
static void
update(struct VSM_data *vd)
{
- int w = COLS / HIST_RANGE;
- int n = w * HIST_RANGE;
+ int w = COLS / hist_range;
+ int n = w * hist_range;
unsigned bm[n], bh[n];
unsigned max;
int i, j, scale;
@@ -107,11 +125,11 @@ update(struct VSM_data *vd)
erase();
/* Draw horizontal axis */
- w = COLS / HIST_RANGE;
- n = w * HIST_RANGE;
+ w = COLS / hist_range;
+ n = w * hist_range;
for (i = 0; i < n; ++i)
(void)mvaddch(LINES - 2, i, '-');
- for (i = 0, j = HIST_LOW; i < HIST_RANGE; ++i, ++j) {
+ for (i = 0, j = hist_low; i < hist_range; ++i, ++j) {
(void)mvaddch(LINES - 2, w * i, '+');
mvprintw(LINES - 1, w * i, "|1e%d", j);
}
@@ -121,8 +139,8 @@ update(struct VSM_data *vd)
/* count our flock */
for (i = 0; i < n; ++i)
bm[i] = bh[i] = 0;
- for (i = 0, max = 1; i < HIST_BUCKETS; ++i) {
- j = i * n / HIST_BUCKETS;
+ for (i = 0, max = 1; i < hist_buckets; ++i) {
+ j = i * n / hist_buckets;
bm[j] += bucket_miss[i];
bh[j] += bucket_hit[i];
if (bm[j] + bh[j] > max)
@@ -151,11 +169,8 @@ static int
h_hist(void *priv, enum VSL_tag_e tag, unsigned fd, unsigned len,
unsigned spec, const char *ptr, uint64_t bm)
{
- double b;
int i, j;
struct VSM_data *vd = priv;
-
- (void)len;
(void)spec;
if (fd >= FD_SETSIZE)
@@ -168,6 +183,15 @@ h_hist(void *priv, enum VSL_tag_e tag, unsigned fd, unsigned len,
hh[fd] = 1;
return (0);
}
+ if (tag == match_tag) {
+ char buf[1024]; /* size? */
+ assert(len < sizeof(buf));
+ memcpy(buf, ptr, len);
+ buf[len] = '\0';
+ i = sscanf(buf, format, &values[fd]);
+ assert(i == 1);
+ }
+
if (tag != SLT_ReqEnd)
return (0);
@@ -177,24 +201,15 @@ h_hist(void *priv, enum VSL_tag_e tag, unsigned fd, unsigned len,
return (0);
}
- /* determine processing time */
-#if 1
- i = sscanf(ptr, "%*d %*f %*f %*f %lf", &b);
-#else
- i = sscanf(ptr, "%*d %*f %*f %lf", &b);
-#endif
- assert(i == 1);
-
/* select bucket */
- i = HIST_RES * (log(b) / log_ten);
- if (i < HIST_LOW * HIST_RES)
- i = HIST_LOW * HIST_RES;
- if (i >= HIST_HIGH * HIST_RES)
- i = HIST_HIGH * HIST_RES - 1;
- i -= HIST_LOW * HIST_RES;
+ i = HIST_RES * (log(values[fd]) / log_ten);
+ if (i < hist_low * HIST_RES)
+ i = hist_low * HIST_RES;
+ if (i >= hist_high * HIST_RES)
+ i = hist_high * HIST_RES - 1;
+ i -= hist_low * HIST_RES;
assert(i >= 0);
- assert(i < HIST_BUCKETS);
-
+ assert(i < hist_buckets);
pthread_mutex_lock(&mtx);
/* phase out old data */
@@ -320,33 +335,94 @@ static void
usage(void)
{
fprintf(stderr, "usage: varnishhist "
- "%s [-n varnish_name] [-V] [-w delay]\n", VSL_USAGE);
+ "%s [-p profile] [-f field_num] [-R max] [-r min] [-V] [-w delay]\n", VSL_USAGE);
exit(1);
}
int
main(int argc, char **argv)
{
- int o;
+ int o, i;
struct VSM_data *vd;
+ const char *profile = "responsetime";
+ int fnum = -1;
+ hist_low = -1;
+ hist_high = -1;
+ match_tag = -1;
vd = VSM_New();
VSL_Setup(vd);
- while ((o = getopt(argc, argv, VSL_ARGS "Vw:")) != -1) {
+ while ((o = getopt(argc, argv, VSL_ARGS "Vw:r:R:f:p:")) != -1) {
switch (o) {
case 'V':
VCS_Message("varnishhist");
exit(0);
+ case 'i':
+ match_tag = VSL_Name2Tag(optarg, -1);
+ if (match_tag < 0) {
+ fprintf(stderr, "No such tag %s\n", optarg);
+ exit(1);
+ }
+ break;
case 'w':
delay = atoi(optarg);
break;
+ case 'f':
+ fnum = atoi(optarg);
+ break;
+ case 'R':
+ hist_high = atoi(optarg);
+ break;
+ case 'r':
+ hist_low = atoi(optarg);
+ break;
+ case 'p':
+ profile = optarg;
+ break;
default:
if (VSL_Arg(vd, o, optarg) > 0)
break;
usage();
}
}
+ if (profile) {
+ for (active_profile = profiles; active_profile->name; active_profile++) {
+ if (strcmp(active_profile->name, profile) == 0) {
+ break;
+ }
+ }
+ }
+ if (! active_profile->name) {
+ fprintf(stderr, "No such profile %s\n", profile);
+ exit(1);
+ }
+ if (match_tag < 0) {
+ match_tag = active_profile->tag;
+ }
+
+ if (fnum < 0) {
+ fnum = active_profile->field;
+ }
+
+ if (hist_low < 0) {
+ hist_low = active_profile->hist_low;
+ }
+
+ if (hist_high < 0) {
+ hist_high = active_profile->hist_high;
+ }
+
+ hist_range = hist_high - hist_low;
+ hist_buckets = hist_range * HIST_RES;
+ bucket_hit = calloc(sizeof bucket_hit, hist_buckets);
+ bucket_miss = calloc(sizeof bucket_miss, hist_buckets);
+
+ format = malloc(4 * fnum);
+ for (i = 0; i < fnum-1; i++) {
+ strcpy(format + 4*i, "%*s ");
+ }
+ strcpy(format + 4*(fnum-1), "%lf");
if (VSL_Open(vd, 1))
exit(1);
diff --git a/bin/varnishsizes/Makefile.am b/bin/varnishsizes/Makefile.am
deleted file mode 100644
index 8029741..0000000
--- a/bin/varnishsizes/Makefile.am
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-
-INCLUDES = -I$(top_srcdir)/include
-
-bin_PROGRAMS = varnishsizes
-
-dist_man_MANS = varnishsizes.1
-
-varnishsizes_SOURCES = varnishsizes.c \
- $(top_builddir)/lib/libvarnish/vas.c \
- $(top_builddir)/lib/libvarnish/version.c
-
-varnishsizes_LDADD = \
- $(top_builddir)/lib/libvarnishcompat/libvarnishcompat.la \
- $(top_builddir)/lib/libvarnishapi/libvarnishapi.la \
- -lm \
- ${CURSES_LIBS} ${PTHREAD_LIBS}
-
-varnishsizes.1: $(top_srcdir)/doc/sphinx/reference/varnishsizes.rst
-if HAVE_RST2MAN
- ${RST2MAN} $? $@
-else
- @echo "========================================"
- @echo "You need rst2man installed to make dist"
- @echo "========================================"
- @false
-endif
diff --git a/bin/varnishsizes/varnishsizes.c b/bin/varnishsizes/varnishsizes.c
deleted file mode 100644
index ce68a9d..0000000
--- a/bin/varnishsizes/varnishsizes.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2010 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- * Author: Dag-Erling Smørgrav <des at des.no>
- *
- * 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.
- *
- * Log tailer for Varnish
- */
-
-#include "config.h"
-
-#include <sys/types.h>
-
-#include <curses.h>
-#include <errno.h>
-#include <limits.h>
-#include <math.h>
-#include <pthread.h>
-#include <regex.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "vapi/vsl.h"
-#include "vapi/vsm.h"
-#include "vas.h"
-#include "vcs.h"
-
-#define HIST_N 2000 /* how far back we remember */
-#define HIST_LOW 1 /* low end of log range */
-#define HIST_HIGH 8 /* high end of log range */
-#define HIST_RANGE (HIST_HIGH - HIST_LOW)
-#define HIST_RES 100 /* bucket resolution */
-#define HIST_BUCKETS (HIST_RANGE * HIST_RES)
-
-static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
-
-static int delay = 1;
-static unsigned rr_hist[HIST_N];
-static unsigned nhist;
-static unsigned next_hist;
-static unsigned bucket_miss[HIST_BUCKETS];
-static unsigned bucket_hit[HIST_BUCKETS];
-static unsigned char hh[FD_SETSIZE];
-static uint64_t bitmap[FD_SETSIZE];
-
-static double log_ten;
-
-static int scales[] = {
- 1,
- 2,
- 3,
- 4,
- 5,
- 10,
- 15,
- 20,
- 25,
- 50,
- 100,
- 250,
- 500,
- 1000,
- 2500,
- 5000,
- 10000,
- 25000,
- 50000,
- 100000,
- INT_MAX
-};
-
-static void
-update(struct VSM_data *vd)
-{
- int w = COLS / HIST_RANGE;
- int n = w * HIST_RANGE;
- unsigned bm[n], bh[n];
- unsigned max;
- int i, j, scale;
-
- erase();
-
- /* Draw horizontal axis */
- w = COLS / HIST_RANGE;
- n = w * HIST_RANGE;
- for (i = 0; i < n; ++i)
- (void)mvaddch(LINES - 2, i, '-');
- for (i = 0, j = HIST_LOW; i < HIST_RANGE; ++i, ++j) {
- (void)mvaddch(LINES - 2, w * i, '+');
- mvprintw(LINES - 1, w * i, "|1e%d", j);
- }
-
- mvprintw(0, 0, "%*s", COLS - 1, VSM_Name(vd));
-
- /* count our flock */
- for (i = 0; i < n; ++i)
- bm[i] = bh[i] = 0;
- for (i = 0, max = 1; i < HIST_BUCKETS; ++i) {
- j = i * n / HIST_BUCKETS;
- bm[j] += bucket_miss[i];
- bh[j] += bucket_hit[i];
- if (bm[j] + bh[j] > max)
- max = bm[j] + bh[j];
- }
-
- /* scale */
- for (i = 0; max / scales[i] > LINES - 3; ++i)
- /* nothing */ ;
- scale = scales[i];
-
- mvprintw(0, 0, "1:%d, n = %d", scale, nhist);
-
- /* show them */
- for (i = 0; i < n; ++i) {
- for (j = 0; j < bm[i] / scale; ++j)
- (void)mvaddch(LINES - 3 - j, i, '#');
- for (; j < (bm[i] + bh[i]) / scale; ++j)
- (void)mvaddch(LINES - 3 - j, i, '|');
- }
-
- refresh();
-}
-
-static int
-h_hist(void *priv, enum VSL_tag_e tag, unsigned fd, unsigned len,
- unsigned spec, const char *ptr, uint64_t bm)
-{
- double b;
- int i, j, tmp;
- struct VSM_data *vd = priv;
-
- (void)len;
- (void)spec;
-
- if (fd >= FD_SETSIZE)
- /* oops */
- return (0);
-
- bitmap[fd] |= bm;
-
- if (tag == SLT_Hit) {
- hh[fd] = 1;
- return (0);
- }
- if (tag != SLT_Length)
- return (0);
-
- if (!VSL_Matched(vd, bitmap[fd])) {
- bitmap[fd] = 0;
- hh[fd] = 0;
- return (0);
- }
-
- /* determine processing time */
- i = sscanf(ptr, "%d", &tmp);
- assert(i == 1);
-
- /* Typically 304s and tend to throw the scaling off */
- if (tmp == 0)
- return 0;
-
- b = tmp;
- /* select bucket */
- i = HIST_RES * (log(b) / log_ten);
- if (i < HIST_LOW * HIST_RES)
- i = HIST_LOW * HIST_RES;
- if (i >= HIST_HIGH * HIST_RES)
- i = HIST_HIGH * HIST_RES - 1;
- i -= HIST_LOW * HIST_RES;
- assert(i >= 0);
- assert(i < HIST_BUCKETS);
-
- pthread_mutex_lock(&mtx);
-
- /* phase out old data */
- if (nhist == HIST_N) {
- j = rr_hist[next_hist];
- if (j < 0) {
- assert(bucket_miss[-j] > 0);
- bucket_miss[-j]--;
- } else {
- assert(bucket_hit[j] > 0);
- bucket_hit[j]--;
- }
- } else {
- ++nhist;
- }
-
- /* phase in new data */
- if (hh[fd] || i == 0) {
- bucket_hit[i]++;
- rr_hist[next_hist] = i;
- } else {
- bucket_miss[i]++;
- rr_hist[next_hist] = -i;
- }
- if (++next_hist == HIST_N) {
- next_hist = 0;
- }
- hh[fd] = 0;
- bitmap[fd] = 0;
-
- pthread_mutex_unlock(&mtx);
-
- return (0);
-}
-
-static void *
-accumulate_thread(void *arg)
-{
- struct VSM_data *vd = arg;
- int i;
-
- for (;;) {
- i = VSL_Dispatch(vd, h_hist, vd);
- if (i < 0)
- break;
- if (i == 0)
- usleep(50000);
- }
- return (arg);
-}
-
-static void
-do_curses(struct VSM_data *vd)
-{
- pthread_t thr;
- int ch;
-
- if (pthread_create(&thr, NULL, accumulate_thread, vd) != 0) {
- fprintf(stderr, "pthread_create(): %s\n", strerror(errno));
- exit(1);
- }
-
- initscr();
- raw();
- noecho();
- nonl();
- intrflush(stdscr, FALSE);
- curs_set(0);
- erase();
- for (;;) {
- pthread_mutex_lock(&mtx);
- update(vd);
- pthread_mutex_unlock(&mtx);
-
- timeout(delay * 1000);
- switch ((ch = getch())) {
- case ERR:
- break;
-#ifdef KEY_RESIZE
- case KEY_RESIZE:
- erase();
- break;
-#endif
- case '\014': /* Ctrl-L */
- case '\024': /* Ctrl-T */
- redrawwin(stdscr);
- refresh();
- break;
- case '\003': /* Ctrl-C */
- raise(SIGINT);
- break;
- case '\032': /* Ctrl-Z */
- endwin();
- raise(SIGTSTP);
- break;
- case '\021': /* Ctrl-Q */
- case 'Q':
- case 'q':
- endwin();
- return;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- delay = 1 << (ch - '0');
- break;
- default:
- beep();
- break;
- }
- }
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-usage(void)
-{
- fprintf(stderr, "usage: varnishsizes "
- "%s [-n varnish_name] [-V] [-w delay]\n", VSL_USAGE);
- exit(1);
-}
-
-int
-main(int argc, char **argv)
-{
- int o;
- struct VSM_data *vd;
-
- vd = VSM_New();
- VSL_Setup(vd);
-
- while ((o = getopt(argc, argv, VSL_ARGS "Vw:")) != -1) {
- switch (o) {
- case 'V':
- VCS_Message("varnishsizes");
- exit(0);
- case 'w':
- delay = atoi(optarg);
- break;
- default:
- if (VSL_Arg(vd, o, optarg) > 0)
- break;
- usage();
- }
- }
-
- if (VSL_Open(vd, 1))
- exit(1);
-
- log_ten = log(10.0);
-
- do_curses(vd);
- exit(0);
-}
More information about the varnish-commit
mailing list