[master] bcd9ef1 Implement -I and -X varnishlog options

Martin Blix Grydeland martin at varnish-cache.org
Thu Jun 13 12:41:24 CEST 2013


commit bcd9ef1e9a961e0d9f2d9d70ef204bf239d60e97
Author: Martin Blix Grydeland <martin at varnish-software.com>
Date:   Wed May 29 11:09:06 2013 +0200

    Implement -I and -X varnishlog options

diff --git a/bin/varnishlog/varnishlog_options.h b/bin/varnishlog/varnishlog_options.h
index 0eb4821..5c09c58 100644
--- a/bin/varnishlog/varnishlog_options.h
+++ b/bin/varnishlog/varnishlog_options.h
@@ -35,6 +35,7 @@ VSL_OPT_d
 VUT_OPT_D
 VSL_OPT_g
 VSL_OPT_i
+VSL_OPT_I
 VSM_OPT_n
 VSM_OPT_N
 VUT_OPT_P
@@ -43,3 +44,4 @@ VSL_OPT_u
 VSL_OPT_v
 VSL_OPT_w
 VSL_OPT_x
+VSL_OPT_X
diff --git a/doc/sphinx/reference/varnishlog.rst b/doc/sphinx/reference/varnishlog.rst
index d7cc290..6c1fd9d 100644
--- a/doc/sphinx/reference/varnishlog.rst
+++ b/doc/sphinx/reference/varnishlog.rst
@@ -49,14 +49,6 @@ The following options are available:
 
 	XXX: Not yet implemented
 
--I [tag:]regex
-
-	Output only records matching this regular expression. If tag
-	is given, limit the regex matching to records of that
-	tag. Multiple -I options may be given.
-
-	XXX: Not yet implemented
-
 -k num
 
 	Only show the first num log transactions (or log records
@@ -78,15 +70,6 @@ The following options are available:
 	XXX: Not yet implemented
 
 
--X [tag:]regex
-
-	Do not output log records matching this regex. If tag is
-	given, limit the regex matching to records of that tag.
-	Multiple -X options may be given.
-
-	XXX: Not yet implemented
-
-
 DESCRIPTION
 ===========
 
diff --git a/include/vapi/vapi_options.h b/include/vapi/vapi_options.h
index 71ef712..a6f316a 100644
--- a/include/vapi/vapi_options.h
+++ b/include/vapi/vapi_options.h
@@ -43,6 +43,10 @@
 
 /* VSL options */
 
+#define VSL_iI_PS							\
+	"If a tag include option is the first of any tag selection"	\
+	" options, all tags are first marked excluded."
+
 #define VSL_OPT_a							\
 	VOPT("a", "[-a]", "Append binary file output",			\
 	    "When writing binary output to a file, append to it rather"	\
@@ -63,10 +67,19 @@
 
 #define VSL_OPT_i							\
 	VOPT("i:", "[-i tag]", "Include tag",				\
-	    "Output only this tag. Multiple -i options may be given."	\
+	    "Include log records of this tag in output. Multiple -i"	\
+	    " options may be given.\n"					\
+	    "\n"							\
+	    VSL_iI_PS							\
+	)
+
+#define VSL_OPT_I							\
+	VOPT("I:", "[-I [tag:]regex]", "Include by regex",		\
+	    "Include by regex matching. Output only records matching"	\
+	    " tag and regular expression. Applies to any tag if tag"	\
+	    " is * or empty.\n"						\
 	    "\n"							\
-	    "If an -i option is the first of any -ix options, all tags"	\
-	    " are disabled before -ix processing."			\
+	    VSL_iI_PS							\
 	)
 
 #define VSL_OPT_r							\
@@ -97,9 +110,13 @@
 
 #define VSL_OPT_x							\
 	VOPT("x:", "[-x tag]", "Exclude tag",				\
-	    "Exclude log records of this tag. Multiple -x options"	\
-	    " may be given.\n"						\
-	    "\n"							\
-	    "If an -x option is the first of any -ix options, all tags"	\
-	    " are enabled for output before -ix processing."		\
+	    "Exclude log records of this tag in output. Multiple -x"	\
+	    " options may be given."					\
+	)
+
+#define VSL_OPT_X							\
+	VOPT("X:", "[-X [tag:]regex]", "Exclude by regex",		\
+	    "Exclude by regex matching. Do not output records matching"	\
+	    " tag and regular expression. Applies to any tag if tag"	\
+	    " is * or empty."						\
 	)
diff --git a/lib/libvarnishapi/vsl.c b/lib/libvarnishapi/vsl.c
index 28d0e44..f263862 100644
--- a/lib/libvarnishapi/vsl.c
+++ b/lib/libvarnishapi/vsl.c
@@ -94,10 +94,27 @@ VSL_New(void)
 
 	vsl->vbm_select = vbit_init(256);
 	vsl->vbm_supress = vbit_init(256);
+	VTAILQ_INIT(&vsl->vslf_select);
+	VTAILQ_INIT(&vsl->vslf_suppress);
 
 	return (vsl);
 }
 
+static void
+vsl_IX_free(vslf_list *list)
+{
+	struct vslf *vslf;
+
+	while (!VTAILQ_EMPTY(list)) {
+		vslf = VTAILQ_FIRST(list);
+		CHECK_OBJ_NOTNULL(vslf, VSLF_MAGIC);
+		VTAILQ_REMOVE(list, vslf, list);
+		AN(vslf->vre);
+		VRE_free(&vslf->vre);
+		AZ(vslf->vre);
+	}
+}
+
 void
 VSL_Delete(struct VSL_data *vsl)
 {
@@ -106,6 +123,8 @@ VSL_Delete(struct VSL_data *vsl)
 
 	vbit_destroy(vsl->vbm_select);
 	vbit_destroy(vsl->vbm_supress);
+	vsl_IX_free(&vsl->vslf_select);
+	vsl_IX_free(&vsl->vslf_suppress);
 	VSL_ResetError(vsl);
 	FREE_OBJ(vsl);
 }
@@ -134,6 +153,29 @@ VSL_ResetError(struct VSL_data *vsl)
 	vsl->diag = NULL;
 }
 
+static int
+vsl_match_IX(struct VSL_data *vsl, vslf_list *list, const struct VSL_cursor *c)
+{
+	enum VSL_tag_e tag;
+	const char *cdata;
+	int len;
+	const struct vslf *vslf;
+
+	(void)vsl;
+	tag = VSL_TAG(c->rec.ptr);
+	cdata = VSL_CDATA(c->rec.ptr);
+	len = VSL_LEN(c->rec.ptr);
+
+	VTAILQ_FOREACH(vslf, list, list) {
+		CHECK_OBJ_NOTNULL(vslf, VSLF_MAGIC);
+		if (vslf->tag >= 0 && vslf->tag != tag)
+			continue;
+		if (VRE_exec(vslf->vre, cdata, len, 0, 0, NULL, 0, NULL) >= 0)
+			return (1);
+	}
+	return (0);
+}
+
 int
 VSL_Match(struct VSL_data *vsl, const struct VSL_cursor *c)
 {
@@ -145,8 +187,14 @@ VSL_Match(struct VSL_data *vsl, const struct VSL_cursor *c)
 	tag = VSL_TAG(c->rec.ptr);
 	if (tag <= SLT__Bogus || tag >= SLT__Reserved)
 		return (0);
-	if (vbit_test(vsl->vbm_select, tag))
+	if (!VTAILQ_EMPTY(&vsl->vslf_select) &&
+	    vsl_match_IX(vsl, &vsl->vslf_select, c))
+		return (1);
+	else if (vbit_test(vsl->vbm_select, tag))
 		return (1);
+	else if (!VTAILQ_EMPTY(&vsl->vslf_suppress) &&
+	    vsl_match_IX(vsl, &vsl->vslf_suppress, c))
+		return (0);
 	else if (vbit_test(vsl->vbm_supress, tag))
 		return (0);
 
@@ -268,7 +316,9 @@ VSL_PrintTransactions(struct VSL_data *vsl, struct VSL_transaction *pt[],
 	int delim = 0;
 	int verbose;
 
-	(void)vsl;
+	CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
+	if (fo == NULL)
+		fo = stdout;
 	if (pt[0] == NULL)
 		return (0);
 
diff --git a/lib/libvarnishapi/vsl_api.h b/lib/libvarnishapi/vsl_api.h
index 05987a6..989effd 100644
--- a/lib/libvarnishapi/vsl_api.h
+++ b/lib/libvarnishapi/vsl_api.h
@@ -31,6 +31,7 @@
 
 #include "vdef.h"
 #include "vqueue.h"
+#include "vre.h"
 #include "vapi/vsm.h"
 
 #define VSL_FILE_ID			"VSL"
@@ -67,6 +68,17 @@ struct vslc {
 	const struct vslc_tbl		*tbl;
 };
 
+struct vslf {
+	unsigned			magic;
+#define VSLF_MAGIC			0x08650B39
+	VTAILQ_ENTRY(vslf)		list;
+
+	int				tag;
+	vre_t				*vre;
+};
+
+typedef VTAILQ_HEAD(,vslf)		vslf_list;
+
 struct VSL_data {
 	unsigned			magic;
 #undef VSL_MAGIC
@@ -75,12 +87,16 @@ struct VSL_data {
 	struct vsb			*diag;
 
 	unsigned			flags;
-#define F_SEEN_ix			(1 << 0)
+#define F_SEEN_ixIX			(1 << 0)
 
 	/* Bitmaps of -ix selected tags */
 	struct vbitmap			*vbm_select;
 	struct vbitmap			*vbm_supress;
 
+	/* Lists of -IX filters */
+	vslf_list			vslf_select;
+	vslf_list			vslf_suppress;
+
 	int				v_opt;
 };
 
diff --git a/lib/libvarnishapi/vsl_arg.c b/lib/libvarnishapi/vsl_arg.c
index c0c964a..22af6a4 100644
--- a/lib/libvarnishapi/vsl_arg.c
+++ b/lib/libvarnishapi/vsl_arg.c
@@ -120,11 +120,7 @@ vsl_ix_arg(struct VSL_data *vsl, int opt, const char *arg)
 	const char *b, *e;
 
 	CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
-	/* If first option is 'i', set all bits for supression */
-	if (opt == 'i' && !(vsl->flags & F_SEEN_ix))
-		for (i = 0; i < 256; i++)
-			vbit_set(vsl->vbm_supress, i);
-	vsl->flags |= F_SEEN_ix;
+	vsl->flags |= F_SEEN_ixIX;
 
 	for (b = arg; *b; b = e) {
 		while (isspace(*b))
@@ -156,11 +152,80 @@ vsl_ix_arg(struct VSL_data *vsl, int opt, const char *arg)
 	return (1);
 }
 
+static int
+vsl_IX_arg(struct VSL_data *vsl, int opt, const char *arg)
+{
+	int i, l, off;
+	const char *b, *e, *err;
+	vre_t *vre;
+	struct vslf *vslf;
+
+	CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
+	vsl->flags |= F_SEEN_ixIX;
+
+	l = 0;
+	b = arg;
+	e = strchr(b, ':');
+	if (e) {
+		while (isspace(*b))
+			b++;
+		l = e - b;
+		while (l > 0 && isspace(b[l - 1]))
+			l--;
+	}
+	if (l > 0 && strncmp(b, "*", l))
+		i = VSL_Name2Tag(b, l);
+	else
+		i = -3;
+	if (i == -2)
+		return (vsl_diag(vsl,
+			"-%c: \"%*.*s\" matches multiple tags\n",
+			(char)opt, l, l, b));
+	else if (i == -1)
+		return (vsl_diag(vsl,
+			"-%c: Could not match \"%*.*s\" to any tag\n",
+			(char)opt, l, l, b));
+	assert(i >= -3);
+
+	if (e)
+		b = e + 1;
+	vre = VRE_compile(b, 0, &err, &off);
+	if (vre == NULL)
+		return (vsl_diag(vsl, "-%c: Regex error at position %d (%s)\n",
+			(char)opt, off, err));
+
+	ALLOC_OBJ(vslf, VSLF_MAGIC);
+	if (vslf == NULL) {
+		VRE_free(&vre);
+		return (vsl_diag(vsl, "Out of memory"));
+	}
+	vslf->tag = i;
+	vslf->vre = vre;
+
+	if (opt == 'I')
+		VTAILQ_INSERT_TAIL(&vsl->vslf_select, vslf, list);
+	else {
+		assert(opt == 'X');
+		VTAILQ_INSERT_TAIL(&vsl->vslf_suppress, vslf, list);
+	}
+
+	return (1);
+}
+
 int
 VSL_Arg(struct VSL_data *vsl, int opt, const char *arg)
 {
+	int i;
+
+	CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
+	/* If first option is 'i', set all bits for supression */
+	if ((opt == 'i' || opt == 'I') && !(vsl->flags & F_SEEN_ixIX))
+		for (i = 0; i < 256; i++)
+			vbit_set(vsl->vbm_supress, i);
+
 	switch (opt) {
-	case 'i': case'x': return (vsl_ix_arg(vsl, opt, arg));
+	case 'i': case 'x': return (vsl_ix_arg(vsl, opt, arg));
+	case 'I': case 'X': return (vsl_IX_arg(vsl, opt, arg));
 	case 'v': vsl->v_opt = 1; return (1);
 	default:
 		return (0);
diff --git a/lib/libvarnishtools/vut.c b/lib/libvarnishtools/vut.c
index 9682c7d..d3e5abd 100644
--- a/lib/libvarnishtools/vut.c
+++ b/lib/libvarnishtools/vut.c
@@ -106,6 +106,8 @@ VUT_g_Arg(const char *arg)
 int
 VUT_Arg(int opt, const char *arg)
 {
+	int i;
+
 	switch (opt) {
 	case 'a':
 		/* Binary file append */
@@ -148,7 +150,10 @@ VUT_Arg(int opt, const char *arg)
 		return (1);
 	default:
 		AN(VUT.vsl);
-		return (VSL_Arg(VUT.vsl, opt, arg));
+		i = VSL_Arg(VUT.vsl, opt, arg);
+		if (i < 0)
+			VUT_Error(1, "%s", VSL_Error(VUT.vsl));
+		return (i);
 	}
 }
 



More information about the varnish-commit mailing list