Commit 4cf923ae authored by Dag Erling Smørgrav's avatar Dag Erling Smørgrav

Rewrite to better handle both the curses case and the one-shot case.


git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@1592 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 06071479
...@@ -14,4 +14,4 @@ varnishtop_LDADD = \ ...@@ -14,4 +14,4 @@ varnishtop_LDADD = \
$(top_builddir)/lib/libvarnish/libvarnish.la \ $(top_builddir)/lib/libvarnish/libvarnish.la \
$(top_builddir)/lib/libcompat/libcompat.a \ $(top_builddir)/lib/libcompat/libcompat.a \
$(top_builddir)/lib/libvarnishapi/libvarnishapi.la \ $(top_builddir)/lib/libvarnishapi/libvarnishapi.la \
${CURSES_LIBS} ${CURSES_LIBS} ${PTHREAD_LIBS}
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
.\" .\"
.\" $Id$ .\" $Id$
.\" .\"
.Dd June 15, 2007 .Dd June 28, 2007
.Dt VARNISHTOP 1 .Dt VARNISHTOP 1
.Os .Os
.Sh NAME .Sh NAME
...@@ -71,6 +71,8 @@ The following options are available: ...@@ -71,6 +71,8 @@ The following options are available:
.It Fl 1 .It Fl 1
Instead of presenting of a continuously updated display, print the Instead of presenting of a continuously updated display, print the
statistics once and exit. statistics once and exit.
Implies
.Fl d .
.It Fl b .It Fl b
Include log entries which result from communication with a backend Include log entries which result from communication with a backend
server. server.
...@@ -98,7 +100,7 @@ Normally, ...@@ -98,7 +100,7 @@ Normally,
.Nm .Nm
will only process entries which are written to the log after it will only process entries which are written to the log after it
starts. starts.
.Op Fl f .It Fl f
Sort and group only on the first field of each log entry. Sort and group only on the first field of each log entry.
This is useful when displaying e.g. This is useful when displaying e.g.
.Dv stataddr .Dv stataddr
...@@ -135,6 +137,18 @@ Exclude log entries which match the specified regular expression. ...@@ -135,6 +137,18 @@ Exclude log entries which match the specified regular expression.
.It Fl x Ar tag .It Fl x Ar tag
Exclude log entries with the specified tag. Exclude log entries with the specified tag.
.El .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 .Sh SEE ALSO
.Xr varnishd 1 , .Xr varnishd 1 ,
.Xr varnishhist 1 , .Xr varnishhist 1 ,
...@@ -144,12 +158,10 @@ Exclude log entries with the specified tag. ...@@ -144,12 +158,10 @@ Exclude log entries with the specified tag.
.Sh HISTORY .Sh HISTORY
The The
.Nm .Nm
utility was developed by utility was originally developed by
.An Poul-Henning Kamp Aq phk@phk.freebsd.dk .An Poul-Henning Kamp Aq phk@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@linpro.no .
This manual page was written by This manual page was written by
.An Dag-Erling Sm\(/orgrav Aq des@linpro.no . .An Dag-Erling Sm\(/orgrav Aq des@linpro.no .
.Sh BUGS
The
.Fl 1
option currently does not work very well.
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* All rights reserved. * All rights reserved.
* *
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk> * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
* Author: Dag-Erling Smørgrav <des@linpro.no>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -34,6 +35,8 @@ ...@@ -34,6 +35,8 @@
#include <ctype.h> #include <ctype.h>
#include <curses.h> #include <curses.h>
#include <errno.h> #include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
...@@ -61,20 +64,72 @@ static unsigned ntop; ...@@ -61,20 +64,72 @@ static unsigned ntop;
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static int f_flag = 0;
static void static void
usage(void) accumulate(const unsigned char *p)
{ {
fprintf(stderr, "usage: varnishtop %s [-1V] [-n varnish_name]\n", VSL_USAGE); struct top *tp, *tp2;
exit(1); 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 static void
upd(void) update(void)
{ {
struct top *tp, *tp2; struct top *tp, *tp2;
int l; int l;
double t = 0; double t = 0;
unsigned u = 0;
static time_t last; static time_t last;
time_t now; time_t now;
...@@ -84,12 +139,17 @@ upd(void) ...@@ -84,12 +139,17 @@ upd(void)
last = now; last = now;
erase(); erase();
l = 0; l = 1;
mvprintw(0, 0, "list length %u\n", ntop); mvprintw(0, 0, "%*s", COLS - 1, VSL_Name());
mvprintw(0, 0, "list length %u", ntop);
TAILQ_FOREACH_SAFE(tp, &top_head, list, tp2) { TAILQ_FOREACH_SAFE(tp, &top_head, list, tp2) {
if (++l < LINES) { if (++l < LINES) {
printw("%10.2f %*.*s\n", int len = tp->rec[1];
tp->count, tp->rec[1], tp->rec[1], tp->rec + 4); 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; t = tp->count;
} }
tp->count *= .999; tp->count *= .999;
...@@ -97,35 +157,139 @@ upd(void) ...@@ -97,35 +157,139 @@ upd(void)
TAILQ_REMOVE(&top_head, tp, list); TAILQ_REMOVE(&top_head, tp, list);
free(tp); free(tp);
ntop--; ntop--;
u++;
} }
} }
mvprintw(0, 40, "cleaned %u\n", u);
refresh(); 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 int
main(int argc, char **argv) main(int argc, char **argv)
{ {
int i, c;
unsigned char *p, *q;
struct VSL_data *vd; struct VSL_data *vd;
unsigned u, v;
struct top *tp, *tp2;
int f_flag = 0;
const char *n_arg = NULL; const char *n_arg = NULL;
int i, o, once = 0;
vd = VSL_New(); vd = VSL_New();
while ((c = getopt(argc, argv, VSL_ARGS "1fn:V")) != -1) { while ((o = getopt(argc, argv, VSL_ARGS "1fn:V")) != -1) {
i = VSL_Arg(vd, c, optarg); i = VSL_Arg(vd, o, optarg);
if (i < 0) if (i < 0)
exit (1); exit (1);
if (i > 0) if (i > 0)
continue; continue;
switch (c) { switch (o) {
case '1': case '1':
VSL_NonBlocking(vd, 1); VSL_Arg(vd, 'd', NULL);
once = 1;
break; break;
case 'n': case 'n':
n_arg = optarg; n_arg = optarg;
...@@ -144,64 +308,11 @@ main(int argc, char **argv) ...@@ -144,64 +308,11 @@ main(int argc, char **argv)
if (VSL_OpenLog(vd, n_arg)) if (VSL_OpenLog(vd, n_arg))
exit (1); exit (1);
initscr(); if (once) {
v = 0; VSL_NonBlocking(vd, 1);
while (1) { do_once(vd);
i = VSL_NextLog(vd, &p); } else {
if (i < 0) do_curses(vd);
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);
}
} }
exit(0); exit(0);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment