Skip to content
Permalink
Browse files

Treat multiline VSL queries as if they were OR'ed

The two following queries now become equivalent:

    vut -g request -q '
        # catch varnish errors
        *Error

        # catch backend errors
        BerespStatus >= 500
    '

    vut -g request -q '(*Error) or (BerespStatus >= 500)'

It becomes interesting when we wish to capture transactions for
different scenarios but would like to decompose them cleanly.
Especially when the query of an individual scenario is rather
complex and OR'ing everything manually would become cumbersome.

This diff is better viewed with the --ignore-all-space flag.
  • Loading branch information...
Dridi committed May 17, 2019
1 parent a3ab11e commit c061b8eb3f70017d343dd680a9886188b22890b9
Showing with 147 additions and 11 deletions.
  1. +91 −0 bin/varnishtest/tests/u00014.vtc
  2. +20 −0 doc/sphinx/reference/vsl-query.rst
  3. +36 −11 lib/libvarnishapi/vxp_parse.c
@@ -0,0 +1,91 @@
varnishtest "VSL compound queries"

# This test case compares individual query scenarios to their
# compounded queries counterparts.

server s1 {
rxreq
txresp -status 500

rxreq
txresp -status 503
} -start

varnish v1 -vcl+backend "" -start

client c1 {
txreq
rxresp
expect resp.status == 500

txreq
rxresp
expect resp.status == 503
} -run

# Let's fist create a script to reduce in all the variants below.

shell {
cat >ncsa.sh <<-EOF
#!/bin/sh

varnishncsa -d -n ${v1_name} -F '%s' "\$@" |
tr '\n' ' '
# '
EOF
chmod +x ncsa.sh
}

shell -match "^500 503 $" {
# no query
./ncsa.sh
}

shell -err -expect "Query expression error" {
# empty query
varnishncsa -d -n ${v1_name} -q ''
}

shell -err -expect "Query expression error" {
varnishncsa -d -n ${v1_name} -q '
# empty multiline query
'
}

shell -err -expect "Query expression error" {
varnishncsa -d -n ${v1_name} -q '
* ~ "Incomplete quoted string
'
}

shell -match "^500 $" {
# single query 1
./ncsa.sh -q 'RespStatus == 500'
}

shell -match "^503 $" {
# single query 2
./ncsa.sh -q 'RespStatus == 503'
}

shell -match "^500 503 $" {
# query 1 OR query 2
./ncsa.sh -q '(RespStatus == 500) or (RespStatus == 503)'
}

shell -match "^500 503 $" {
./ncsa.sh -q '
# query 1
RespStatus == 500

# query 2
RespStatus == 503
'
}

shell -match "^500 503 $" {
./ncsa.sh -q '
RespStatus == 500 # query 1
RespStatus == 503 # query 2
'
}
@@ -131,6 +131,26 @@ whose id can be obtained from an ``X-Varnish`` HTTP header, the
default "guru meditation" error page, or ``Begin`` and ``Link`` log
records.

A query must fit on a single line, but it is possible to pass multiple
queries at once, one query per line. Empty lines are ignored, and the
list of queries is treated as if the 'or' operator was used to combine
them.

For example this list of queries::

# catch varnish errors
*Error

# catch backend errors
BerespStatus >= 500

is identical to this query::

(*Error) or (BerespStatus >= 500)

Comments can be used and will be ignored, they start with the ``'#'``
character.

Record selection criteria
-------------------------

@@ -503,15 +503,30 @@ vxp_expr_or(struct vxp *vxp, struct vex **pvex)
/*
* SYNTAX:
* expr:
* expr_or EOI
* expr_or EOI { 'or' expr_or EOI }?
*/

static void
vxp_expr(struct vxp *vxp, struct vex **pvex)
{
vxp_expr_or(vxp, pvex);
struct vex *a = NULL, *or;

if (*pvex == NULL) {
vxp_expr_or(vxp, pvex);
ERRCHK(vxp);
ExpectErr(vxp, EOI);
return;
}

vxp_expr(vxp, &a);
ERRCHK(vxp);
ExpectErr(vxp, EOI);

or = vex_alloc(vxp);
AN(or);
or->tok = T_OR;
or->b = *pvex;
or->a = a;
*pvex = or;
}

/*
@@ -523,17 +538,27 @@ vxp_Parse(struct vxp *vxp)
{
struct vex *vex = NULL;

AZ(vxp->err);
vxp->t = VTAILQ_FIRST(&vxp->tokens);
if (vxp->t == NULL)
return (NULL);

vxp_expr(vxp, &vex);
while (vxp->t != NULL) {
/* Ignore empty queries */
while (vxp->t != NULL && vxp->t->tok == EOI)
vxp->t = VTAILQ_NEXT(vxp->t, list);

if (vxp->t == NULL)
break;

vxp_expr(vxp, &vex);

if (vxp->err) {
if (vex)
vex_Free(&vex);
AZ(vex);
return (NULL);
}

if (vxp->err) {
if (vex)
vex_Free(&vex);
AZ(vex);
return (NULL);
vxp->t = VTAILQ_NEXT(vxp->t, list);
}

return (vex);

0 comments on commit c061b8e

Please sign in to comment.
You can’t perform that action at this time.