r1592 - trunk/varnish-cache/bin/varnishtop

des at projects.linpro.no des at projects.linpro.no
Thu Jun 28 15:34:44 CEST 2007


Author: des
Date: 2007-06-28 15:34:44 +0200 (Thu, 28 Jun 2007)
New Revision: 1592

Modified:
   trunk/varnish-cache/bin/varnishtop/Makefile.am
   trunk/varnish-cache/bin/varnishtop/varnishtop.1
   trunk/varnish-cache/bin/varnishtop/varnishtop.c
Log:
Rewrite to better handle both the curses case and the one-shot case.


Modified: trunk/varnish-cache/bin/varnishtop/Makefile.am
===================================================================
--- trunk/varnish-cache/bin/varnishtop/Makefile.am	2007-06-28 13:33:59 UTC (rev 1591)
+++ trunk/varnish-cache/bin/varnishtop/Makefile.am	2007-06-28 13:34:44 UTC (rev 1592)
@@ -14,4 +14,4 @@
 	$(top_builddir)/lib/libvarnish/libvarnish.la \
 	$(top_builddir)/lib/libcompat/libcompat.a \
 	$(top_builddir)/lib/libvarnishapi/libvarnishapi.la \
-	${CURSES_LIBS}
+	${CURSES_LIBS} ${PTHREAD_LIBS}

Modified: trunk/varnish-cache/bin/varnishtop/varnishtop.1
===================================================================
--- trunk/varnish-cache/bin/varnishtop/varnishtop.1	2007-06-28 13:33:59 UTC (rev 1591)
+++ trunk/varnish-cache/bin/varnishtop/varnishtop.1	2007-06-28 13:34:44 UTC (rev 1592)
@@ -28,7 +28,7 @@
 .\"
 .\" $Id$
 .\"
-.Dd June 15, 2007
+.Dd June 28, 2007
 .Dt VARNISHTOP 1
 .Os
 .Sh NAME
@@ -71,6 +71,8 @@
 .It Fl 1
 Instead of presenting of a continuously updated display, print the
 statistics once and exit.
+Implies
+.Fl d .
 .It Fl b
 Include log entries which result from communication with a backend
 server.
@@ -98,7 +100,7 @@
 .Nm
 will only process entries which are written to the log after it
 starts.
-.Op Fl f
+.It Fl f
 Sort and group only on the first field of each log entry.
 This is useful when displaying e.g.
 .Dv stataddr
@@ -135,6 +137,18 @@
 .It Fl x Ar tag
 Exclude log entries with the specified tag.
 .El
+.Sh EXAMPLES
+The following example displays a continuously updated list of the most
+frequently requested URLs:
+.Bd -literal
+varnishtop -i RxURL
+.Ed
+.Pp
+The following example displays a continuously updated list of the most
+commonly used user agents:
+.Bd -literal
+varnishtop -i RxHeader -C -I \\^User-Agent
+.Ed
 .Sh SEE ALSO
 .Xr varnishd 1 ,
 .Xr varnishhist 1 ,
@@ -144,12 +158,10 @@
 .Sh HISTORY
 The
 .Nm
-utility was developed by
+utility was originally developed by
 .An Poul-Henning Kamp Aq phk at phk.freebsd.dk
-in cooperation with Verdens Gang AS and Linpro AS.
+in cooperation with Verdens Gang AS and Linpro AS, and later
+substantially rewritten by
+.An Dag-Erling Sm\(/orgrav Aq des at linpro.no .
 This manual page was written by
 .An Dag-Erling Sm\(/orgrav Aq des at linpro.no .
-.Sh BUGS
-The
-.Fl 1
-option currently does not work very well.

Modified: trunk/varnish-cache/bin/varnishtop/varnishtop.c
===================================================================
--- trunk/varnish-cache/bin/varnishtop/varnishtop.c	2007-06-28 13:33:59 UTC (rev 1591)
+++ trunk/varnish-cache/bin/varnishtop/varnishtop.c	2007-06-28 13:34:44 UTC (rev 1592)
@@ -4,6 +4,7 @@
  * All rights reserved.
  *
  * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ * Author: Dag-Erling Smørgrav <des at linpro.no>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,6 +35,8 @@
 #include <ctype.h>
 #include <curses.h>
 #include <errno.h>
+#include <pthread.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -61,20 +64,72 @@
 
 /*--------------------------------------------------------------------*/
 
+static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
+
+static int f_flag = 0;
+
 static void
-usage(void)
+accumulate(const unsigned char *p)
 {
-	fprintf(stderr, "usage: varnishtop %s [-1V] [-n varnish_name]\n", VSL_USAGE);
-	exit(1);
+	struct top *tp, *tp2;
+	const unsigned char *q;
+	unsigned int u;
+	int i;
+
+	// fprintf(stderr, "%*.*s\n", p[1], p[1], p + 4);
+
+	u = 0;
+	q = p + 4;
+	for (i = 0; i < p[1]; i++, q++) {
+		if (f_flag && (*q == ':' || isspace(*q)))
+			break;
+		u += *q;
+	}
+
+	TAILQ_FOREACH(tp, &top_head, list) {
+		if (tp->hash != u)
+			continue;
+		if (tp->rec[0] != p[0])
+			continue;
+		if (tp->clen != q - p)
+			continue;
+		if (memcmp(p + 4, tp->rec + 4, q - (p + 4)))
+			continue;
+		tp->count += 1.0;
+		break;
+	}
+	if (tp == NULL) {
+		ntop++;
+		tp = calloc(sizeof *tp, 1);
+		assert(tp != NULL);
+		tp->hash = u;
+		tp->count = 1.0;
+		tp->clen = q - p;
+		TAILQ_INSERT_TAIL(&top_head, tp, list);
+	}
+	memcpy(tp->rec, p, 4 + p[1]);
+	while (1) {
+		tp2 = TAILQ_PREV(tp, tophead, list);
+		if (tp2 == NULL || tp2->count >= tp->count)
+			break;
+		TAILQ_REMOVE(&top_head, tp2, list);
+		TAILQ_INSERT_AFTER(&top_head, tp, tp2, list);
+	}
+	while (1) {
+		tp2 = TAILQ_NEXT(tp, list);
+		if (tp2 == NULL || tp2->count <= tp->count)
+			break;
+		TAILQ_REMOVE(&top_head, tp2, list);
+		TAILQ_INSERT_BEFORE(tp, tp2, list);
+	}
 }
 
 static void
-upd(void)
+update(void)
 {
 	struct top *tp, *tp2;
 	int l;
 	double t = 0;
-	unsigned u = 0;
 	static time_t last;
 	time_t now;
 
@@ -84,12 +139,17 @@
 	last = now;
 
 	erase();
-	l = 0;
-	mvprintw(0, 0, "list length %u\n", ntop);
+	l = 1;
+	mvprintw(0, 0, "%*s", COLS - 1, VSL_Name());
+	mvprintw(0, 0, "list length %u", ntop);
 	TAILQ_FOREACH_SAFE(tp, &top_head, list, tp2) {
 		if (++l < LINES) {
-			printw("%10.2f %*.*s\n",
-			    tp->count, tp->rec[1], tp->rec[1], tp->rec + 4);
+			int len = tp->rec[1];
+			if (len > COLS - 20)
+				len = COLS - 20;
+			mvprintw(l, 0, "%9.2f %-9.9s %*.*s\n",
+			    tp->count, VSL_tags[tp->rec[0]],
+			    len, len, tp->rec + 4);
 			t = tp->count;
 		}
 		tp->count *= .999;
@@ -97,35 +157,139 @@
 			TAILQ_REMOVE(&top_head, tp, list);
 			free(tp);
 			ntop--;
-			u++;
 		}
 	}
-	mvprintw(0, 40, "cleaned %u\n", u);
 	refresh();
 }
 
+static void *
+accumulate_thread(void *arg)
+{
+	struct VSL_data *vd = arg;
+
+	for (;;) {
+		unsigned char *p;
+		int i;
+
+		i = VSL_NextLog(vd, &p);
+		if (i < 0)
+			break;
+		if (i == 0) {
+			usleep(50000);
+			continue;
+		}
+
+		pthread_mutex_lock(&mtx);
+		accumulate(p);
+		pthread_mutex_unlock(&mtx);
+	}
+	return (arg);
+}
+
+static void
+do_curses(struct VSL_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();
+		pthread_mutex_unlock(&mtx);
+
+		timeout(1000);
+		switch ((ch = getch())) {
+		case ERR:
+			break;
+		case KEY_RESIZE:
+			erase();
+			break;
+		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;
+		default:
+			beep();
+			break;
+		}
+	}
+}
+
+static void
+dump(void)
+{
+	struct top *tp, *tp2;
+	int len;
+
+	TAILQ_FOREACH_SAFE(tp, &top_head, list, tp2) {
+		if (tp->count <= 1.0)
+			break;
+		len = tp->rec[1];
+		printf("%9.2f %*.*s\n", tp->count, len, len, tp->rec + 4);
+	}
+}
+
+static void
+do_once(struct VSL_data *vd)
+{
+	unsigned char *p;
+
+	while (VSL_NextLog(vd, &p) > 0)
+		accumulate(p);
+	dump();
+}
+
+static void
+usage(void)
+{
+	fprintf(stderr, "usage: varnishtop %s [-1fV] [-n varnish_name]\n", VSL_USAGE);
+	exit(1);
+}
+
 int
 main(int argc, char **argv)
 {
-	int i, c;
-	unsigned char *p, *q;
 	struct VSL_data *vd;
-	unsigned u, v;
-	struct top *tp, *tp2;
-	int f_flag = 0;
 	const char *n_arg = NULL;
+	int i, o, once = 0;
 
 	vd = VSL_New();
 
-	while ((c = getopt(argc, argv, VSL_ARGS "1fn:V")) != -1) {
-		i = VSL_Arg(vd, c, optarg);
+	while ((o = getopt(argc, argv, VSL_ARGS "1fn:V")) != -1) {
+		i = VSL_Arg(vd, o, optarg);
 		if (i < 0)
 			exit (1);
 		if (i > 0)
 			continue;
-		switch (c) {
+		switch (o) {
 		case '1':
-			VSL_NonBlocking(vd, 1);
+			VSL_Arg(vd, 'd', NULL);
+			once = 1;
 			break;
 		case 'n':
 			n_arg = optarg;
@@ -144,64 +308,11 @@
 	if (VSL_OpenLog(vd, n_arg))
 		exit (1);
 
-	initscr();
-	v = 0;
-	while (1) {
-		i = VSL_NextLog(vd, &p);
-		if (i < 0)
-			break;
-		if (i == 0) {
-			upd();
-			usleep(50000);
-			continue;
-		}
-		if (++v > 100) {
-			upd();
-			v = 0;
-		}
-		u = 0;
-		q = p + 4;
-		for (i = 0; i < p[1]; i++, q++) {
-			if (f_flag && (*q == ':' || isspace(*q)))
-				break;
-			u += *q;
-		}
-		TAILQ_FOREACH(tp, &top_head, list) {
-			if (tp->hash != u)
-				continue;
-			if (tp->rec[0] != p[0])
-				continue;
-			if (tp->clen != q - p)
-				continue;
-			if (memcmp(p + 4, tp->rec + 4, q - (p + 4)))
-				continue;
-			tp->count += 1.0;
-			break;
-		}
-		if (tp == NULL) {
-			ntop++;
-			tp = calloc(sizeof *tp, 1);
-			assert(tp != NULL);
-			tp->hash = u;
-			tp->count = 1.0;
-			tp->clen = q - p;
-			TAILQ_INSERT_TAIL(&top_head, tp, list);
-		}
-		memcpy(tp->rec, p, 4 + p[1]);
-		while (1) {
-			tp2 = TAILQ_PREV(tp, tophead, list);
-			if (tp2 == NULL || tp2->count >= tp->count)
-				break;
-			TAILQ_REMOVE(&top_head, tp2, list);
-			TAILQ_INSERT_AFTER(&top_head, tp, tp2, list);
-		}
-		while (1) {
-			tp2 = TAILQ_NEXT(tp, list);
-			if (tp2 == NULL || tp2->count <= tp->count)
-				break;
-			TAILQ_REMOVE(&top_head, tp2, list);
-			TAILQ_INSERT_BEFORE(tp, tp2, list);
-		}
+	if (once) {
+		VSL_NonBlocking(vd, 1);
+		do_once(vd);
+	} else {
+		do_curses(vd);
 	}
 	exit(0);
 }




More information about the varnish-commit mailing list