Commit 0532b16c authored by Dag Erling Smørgrav's avatar Dag Erling Smørgrav

Clone varnishncsa off of varnishlog. Anders will hack on it to produce

NCSA-style (common / combined) logs.

git-svn-id: http://www.varnish-cache.org/svn/trunk@570 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 02c596a3
# $Id$
SUBDIRS = varnishd varnishlog varnishstat varnishtester varnishtop
SUBDIRS = varnishd varnishlog varnishncsa varnishstat varnishtester varnishtop
# $Id$
INCLUDES = -I$(top_srcdir)/include
bin_PROGRAMS = varnishncsa
man_MANS = varnishncsa.1
varnishncsa_SOURCES = varnishncsa.c
varnishncsa_LDADD = \
$(top_builddir)/lib/libvarnishapi/libvarnishapi.la \
$(top_builddir)/lib/libsbuf/libsbuf.a
.\"
.\" $Id$
.\"
.Dd July 11, 2006
.Dt VARNISHNCSA 1
.Os
.Sh NAME
.Nm varnishncsa
.Nd Generate NCSA common / combined logs
.Sh SYNOPSIS
.Nm
.Op Fl C
.Op Fl b
.Op Fl c
.Op Fl o
.Op Fl I Ar regex
.Op Fl X Ar regex
.Op Fl i Ar tag
.Op Fl r Ar file
.Op Fl w Ar file
.Op Fl x Ar tag
.Sh DESCRIPTION
The
.Nm
utility reads and presents
.Xr varnishd 1
shared memory logs.
.Pp
The following options are available:
.Bl -tag -width Fl
.It Fl C
Ignore case when matching regular expressions.
.It Fl b
Include log entries which result from communication with a backend
server.
If neither
.Fl b
nor
.Fl c
is specified,
.Nm
acts as if they both were.
.It Fl c
Include log entries which result from communication with a client.
If neither
.Fl b
nor
.Fl c
is specified,
.Nm
acts as if they both were.
.It Fl o
Group log entries by request ID.
.It Fl I Ar regex
Include log entries which match the specified regular expression.
If neither
.Fl I
nor
.Fl i
is specified, all log entries are included.
.It Fl X Ar regex
Exclude log entries which match the specified regular expression.
.It Fl i Ar tag
Include log entries with the specified tag.
If neither
.Fl I
nor
.Fl i
is specified, all log entries are included.
.It Fl r Ar file
Read log entries from
.Ar file
instead of shared memory.
.It Fl w Ar file
Write log entries to
.Ar file
instead of displaying them.
.It Fl x Ar tag
Exclude log entries with the specified tag.
.El
.Sh TAGS
The following log entry tags are currently defined:
.\" keep in sync with include/shmlog_tags.h
.\" XXX add descriptions
.Bl -tag -width 16
.It Dv Backend
.It Dv BackendClose
.It Dv BackendOpen
.It Dv BackendReuse
.It Dv BackendXID
.It Dv BldHdr
.It Dv CLI
.It Dv ClientAddr
.It Dv Debug
.It Dv Error
.It Dv ExpBan
.It Dv ExpKill
.It Dv ExpPick
.It Dv Header
.It Dv Hit
.It Dv HttpError
.It Dv Length
.It Dv LostHeader
.It Dv Protocol
.It Dv Request
.It Dv Response
.It Dv SessionClose
.It Dv SessionOpen
.It Dv SessionReuse
.It Dv Status
.It Dv URL
.It Dv VCL_call
.It Dv VCL_return
.It Dv VCL_trace
.It Dv WorkThread
.It Dv XID
.El
.Sh SEE ALSO
.Xr varnishd 1 ,
.Xr varnishstat 1
.Sh HISTORY
The
.Nm
utility was developed by
.An Poul-Henning Kamp Aq phk@freebsd.dk
in cooperation with Verdens Gang AS and Linpro AS.
/*
* $Id$
*
* Log tailer for Varnish
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sbuf.h>
#include <vis.h>
#include "shmlog.h"
#include "varnishapi.h"
static char *
vis_it(unsigned char *p)
{
static char visbuf[255*4 + 3 + 1];
strcpy(visbuf, " [");
strvisx(visbuf + 2, p + 4, p[1],
VIS_OCTAL | VIS_TAB | VIS_NL);
strcat(visbuf, "]");
return (visbuf);
}
/* Ordering-----------------------------------------------------------*/
static struct sbuf *ob[65536];
static int hc[65536];
static int xrf[65536];
static void
clean_order(void)
{
unsigned u;
for (u = 0; u < 65536; u++) {
if (ob[u] == NULL)
continue;
sbuf_finish(ob[u]);
if (sbuf_len(ob[u]))
printf("%s\n", sbuf_data(ob[u]));
sbuf_clear(ob[u]);
}
}
static void
order(unsigned char *p, int h_opt)
{
unsigned u, v;
u = (p[2] << 8) | p[3];
if (ob[u] == NULL) {
ob[u] = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
assert(ob[u] != NULL);
}
v = 0;
switch (p[0]) {
case SLT_VCL_call:
sbuf_printf(ob[u], "%02x %3d %4d %-12s",
p[0], p[1], u, VSL_tags[p[0]]);
if (p[1] > 0) {
sbuf_cat(ob[u], " <");
sbuf_bcat(ob[u], p + 4, p[1]);
}
if (h_opt && p[1] == 3 && !memcmp(p + 4, "hit", 3))
hc[u]++;
break;
case SLT_VCL_trace:
if (p[1] > 0) {
sbuf_cat(ob[u], " ");
sbuf_bcat(ob[u], p + 4, p[1]);
}
break;
case SLT_VCL_return:
if (p[1] > 0) {
sbuf_cat(ob[u], " ");
sbuf_bcat(ob[u], p + 4, p[1]);
sbuf_cat(ob[u], ">\n");
}
if (h_opt && p[1] == 7 && !memcmp(p + 4, "deliver", 7))
hc[u]++;
if (h_opt && p[1] == 6 && !memcmp(p + 4, "insert", 6)) {
if (hc[xrf[u]] == 1) {
hc[u] += 2;
hc[xrf[u]] = 4;
}
}
break;
case SLT_Debug:
if (p[1] == 0)
break;
if (!h_opt)
;
else if (p[1] > 4 && !memcmp(p + 4, "TTD:", 4))
break;
sbuf_printf(ob[u], "%02x %3d %4d %-12s",
p[0], p[1], u, VSL_tags[p[0]]);
if (p[1] > 0)
sbuf_cat(ob[u], vis_it(p));
sbuf_cat(ob[u], "\n");
break;
case SLT_HttpError:
if (!h_opt)
v = 1;
else if (p[1] == 16 && !memcmp(p + 4, "Received nothing", 16))
;
else if (p[1] == 17 && !memcmp(p + 4, "Received errno 54", 17))
;
else
v = 1;
break;
case SLT_SessionClose:
if (!h_opt)
v = 1;
else if (p[1] == 10 && !memcmp(p + 4, "no request", 10))
;
else if (p[1] == 7 && !memcmp(p + 4, "timeout", 7))
;
else
v = 1;
break;
case SLT_Request:
if (h_opt && p[1] == 3 && !memcmp(p + 4, "GET", 3))
hc[u]++;
if (h_opt && p[1] == 4 && !memcmp(p + 4, "HEAD", 4))
hc[u]++;
v = 1;
break;
case SLT_Backend:
xrf[u] = atoi(p + 4);
v = 1;
break;
case SLT_Status:
if (h_opt && p[1] == 3 && !memcmp(p + 4, "200", 3))
hc[u]++;
v = 1;
break;
default:
v = 1;
break;
}
if (v) {
sbuf_printf(ob[u], "%02x %3d %4d %-12s",
p[0], p[1], u, VSL_tags[p[0]]);
if (p[1] > 0) {
sbuf_cat(ob[u], " <");
sbuf_bcat(ob[u], p + 4, p[1]);
sbuf_cat(ob[u], ">");
}
sbuf_cat(ob[u], "\n");
}
if (u == 0) {
sbuf_finish(ob[u]);
printf("%s", sbuf_data(ob[u]));
sbuf_clear(ob[u]);
return;
}
switch (p[0]) {
case SLT_SessionClose:
case SLT_SessionReuse:
case SLT_BackendClose:
case SLT_BackendReuse:
sbuf_finish(ob[u]);
if ((hc[u] != 4 || h_opt == 0) && sbuf_len(ob[u]) > 1)
printf("%s\n", sbuf_data(ob[u]));
sbuf_clear(ob[u]);
hc[u] = 0;
xrf[u] = 0;
break;
default:
break;
}
}
/*--------------------------------------------------------------------*/
static void
Usage(void)
{
fprintf(stderr, "Usage: varnishncsa [-o] [-w file] [-r file]\n");
exit(2);
}
int
main(int argc, char **argv)
{
int i, c;
unsigned u, v;
unsigned char *p;
int o_flag = 0;
char *w_opt = NULL;
FILE *wfile = NULL;
int h_opt = 0;
struct VSL_data *vd;
vd = VSL_New();
while ((c = getopt(argc, argv, VSL_ARGS "how:")) != -1) {
i = VSL_Arg(vd, c, optarg);
if (i < 0)
exit (1);
if (i > 0)
continue;
switch (c) {
case 'h':
h_opt = 1;
break;
case 'o':
o_flag = 1;
break;
case 'w':
w_opt = optarg;
break;
default:
Usage();
}
}
if (VSL_OpenLog(vd))
exit (1);
if (o_flag && w_opt != NULL)
Usage();
if (w_opt != NULL) {
wfile = fopen(w_opt, "w");
if (wfile == NULL) {
perror(w_opt);
exit (1);
}
}
u = 0;
v = 0;
while (1) {
i = VSL_NextLog(vd, &p);
if (i < 0)
break;
if (i == 0) {
if (w_opt == NULL) {
if (o_flag && ++v == 100)
clean_order();
fflush(stdout);
} else if (++v == 100) {
fflush(wfile);
printf("\nFlushed\n");
}
usleep(50000);
continue;
}
v = 0;
if (wfile != NULL) {
i = fwrite(p, 4 + p[1], 1, wfile);
if (i != 1)
perror(w_opt);
u++;
if (!(u % 1000)) {
printf("%u\r", u);
fflush(stdout);
}
continue;
}
if (o_flag) {
order(p, h_opt);
continue;
}
u = (p[2] << 8) | p[3];
printf("%02x %3d %4d %-12s",
p[0], p[1], u, VSL_tags[p[0]]);
if (p[1] > 0) {
if (p[0] != SLT_Debug) {
printf(" <");
fwrite(p + 4, p[1], 1, stdout);
printf(">");
} else {
fputs(vis_it(p), stdout);
}
}
printf("\n");
}
if (o_flag)
clean_order();
return (0);
}
......@@ -69,6 +69,7 @@ AC_CONFIG_FILES([
bin/Makefile
bin/varnishd/Makefile
bin/varnishlog/Makefile
bin/varnishncsa/Makefile
bin/varnishstat/Makefile
bin/varnishtester/Makefile
bin/varnishtop/Makefile
......
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