[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