Commit 09087a93 authored by Geoff Simmons's avatar Geoff Simmons

The parser allows the XID field, obsolete since Varnish 3, to be left out.

The "legacy" syntax is still tolerated, so a number after "track" is
skipped over. Also add a regression test in which the new syntax is
used, the old regression test is retained as a legacy test.
parent db58f598
Pipeline #143 skipped
...@@ -9,8 +9,8 @@ Tracking Log Reader demon ...@@ -9,8 +9,8 @@ Tracking Log Reader demon
------------------------- -------------------------
:Author: Geoffrey Simmons :Author: Geoffrey Simmons
:Date: 2017-03-16 :Date: 2017-03-17
:Version: 4.1 :Version: trunk
:Manual section: 3 :Manual section: 3
SYNOPSIS SYNOPSIS
...@@ -35,31 +35,32 @@ system, such as ActiveMQ or Kafka. ...@@ -35,31 +35,32 @@ system, such as ActiveMQ or Kafka.
in this format by the ``varnishlog`` tool for client request in this format by the ``varnishlog`` tool for client request
transactions:: transactions::
VCL_Log track <XID> <DATA> VCL_Log track <DATA>
* ``XID``: XID (request identifier) assigned by Varnish
* ``DATA``: data to be logged * ``DATA``: data to be logged
The ``VCL_Log`` entries may also specify a sharding key for the The ``VCL_Log`` entries may also specify a sharding key for the
message brokers, in this format:: message brokers, in this format::
VCL_Log track <XID> key <KEY> VCL_Log track key <KEY>
* ``KEY``: the sharding key * ``KEY``: the sharding key
``VCL_Log`` entries result from use of the ``log()`` function provided ``VCL_Log`` entries result from use of the ``log()`` function provided
by the standard vmod ``std`` distributed with Varnish. The ``log()`` by the standard vmod ``std`` distributed with Varnish. The ``log()``
call must include the prefix ``track``, the XID and the data to be call must include the prefix ``track`` and the data to be logged, or a
logged, or a sharding key. These log entries can be created with VCL sharding key. Note that DATA entries cannot begin with the word "key"
code such as:: followed by a space; these will be interpreted as KEY entries.
These log entries can be created with VCL code such as::
import std; import std;
sub vcl_recv { sub vcl_recv {
/* ... */ /* ... */
std.log("track " + req.xid + " url=" + req.url); std.log("track url=" + req.url);
std.log("track " + req.xid + " http_Host=" + req.http.Host); std.log("track http_Host=" + req.http.Host);
std.log("track " + req.xid + " key " + req.http.X-Key); std.log("track key " + req.http.X-Key);
/* ... */ /* ... */
} }
...@@ -107,9 +108,9 @@ to the data displayed with this ``varnishlog`` command:: ...@@ -107,9 +108,9 @@ to the data displayed with this ``varnishlog`` command::
Thus the VCL example shown above may result in log entries such as:: Thus the VCL example shown above may result in log entries such as::
* << Request >> 591570 * << Request >> 591570
- VCL_Log track 591570 url=/index.html - VCL_Log track url=/index.html
- VCL_Log track 591570 http_Host=foo.bar.org - VCL_Log track http_Host=foo.bar.org
- VCL_Log track 591570 key 12345678 - VCL_Log track key 12345678
- Timestamp Resp: 1430835449.167329 0.000681 0.000352 - Timestamp Resp: 1430835449.167329 0.000681 0.000352
In this case, ``trackrdrd`` sends this data to message brokers, with In this case, ``trackrdrd`` sends this data to message brokers, with
......
...@@ -348,11 +348,12 @@ get_chunk(dataentry *entry) ...@@ -348,11 +348,12 @@ get_chunk(dataentry *entry)
} }
static unsigned static unsigned
append(dataentry *entry, enum VSL_tag_e tag, unsigned xid, char *data, append(dataentry *entry, enum VSL_tag_e tag, unsigned xid, const char *data,
int datalen) int datalen)
{ {
chunk_t *chunk; chunk_t *chunk;
char *null, *p; char *null;
const char *p;
unsigned chunks_added = 0; unsigned chunks_added = 0;
int n; int n;
...@@ -411,7 +412,7 @@ append(dataentry *entry, enum VSL_tag_e tag, unsigned xid, char *data, ...@@ -411,7 +412,7 @@ append(dataentry *entry, enum VSL_tag_e tag, unsigned xid, char *data,
} }
static inline void static inline void
addkey(dataentry *entry, enum VSL_tag_e tag, unsigned xid, char *key, addkey(dataentry *entry, enum VSL_tag_e tag, unsigned xid, const char *key,
int keylen) int keylen)
{ {
CHECK_OBJ_NOTNULL(entry, DATA_MAGIC); CHECK_OBJ_NOTNULL(entry, DATA_MAGIC);
...@@ -516,7 +517,7 @@ dispatch(struct VSL_data *vsl, struct VSL_transaction * const pt[], void *priv) ...@@ -516,7 +517,7 @@ dispatch(struct VSL_data *vsl, struct VSL_transaction * const pt[], void *priv)
switch (VSL_TAG(t->c->rec.ptr)) { switch (VSL_TAG(t->c->rec.ptr)) {
int datalen; int datalen;
char *data; const char *data;
vcl_log_t data_type; vcl_log_t data_type;
struct timeval reqend_t; struct timeval reqend_t;
......
...@@ -58,18 +58,23 @@ parse_UnsignedDec(const char *str, int len, unsigned *num) ...@@ -58,18 +58,23 @@ parse_UnsignedDec(const char *str, int len, unsigned *num)
len is length from that char to end of data len is length from that char to end of data
*/ */
int int
Parse_VCL_Log(const char *ptr, int len, char **data, int *datalen, Parse_VCL_Log(const char *ptr, int len, const char **data, int *datalen,
vcl_log_t *type) vcl_log_t *type)
{ {
const char *c = ptr;
*type = VCL_LOG_DATA; *type = VCL_LOG_DATA;
char *blank = memchr(ptr, ' ', len); while (isdigit(*c))
if (blank == NULL) c++;
return EINVAL; if (*c == ' ' && (c - ptr + 1 < len))
if (strncmp(blank + 1, "key ", 4) == 0) { c++;
blank += 4; else
c = ptr;
if (strncmp(c, "key ", 4) == 0) {
c += 4;
*type = VCL_LOG_KEY; *type = VCL_LOG_KEY;
} }
*data = blank + 1; *data = c;
*datalen = ptr + len - *data; *datalen = ptr + len - *data;
return(0); return(0);
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# The regression test reads from a binary dump of the Varnish SHM log # The regression test reads from a binary dump of the Varnish SHM log
# obtained from: # obtained from:
# #
# $ varnishlog -B -w varnish.binlog # $ varnishlog -w varnish.binlog
# #
# The regression runs trackrdrd, reading from the binary dump and # The regression runs trackrdrd, reading from the binary dump and
# logging to stdout in debug mode, and obtains a cksum from stdout. It # logging to stdout in debug mode, and obtains a cksum from stdout. It
...@@ -17,38 +17,54 @@ echo '... testing messages & log output at debug level against known checksums' ...@@ -17,38 +17,54 @@ echo '... testing messages & log output at debug level against known checksums'
LOG=mq_log.log LOG=mq_log.log
MSG=mq_test.log MSG=mq_test.log
rm -f $LOG $MSG #
# $1 the binary log to read
# $2 the log with Worker entries filtered out
# $3 the log filtered for Worker entries
# $4 output of the file mq implementation
#
function regress {
rm -f $LOG $MSG
../trackrdrd -D -f varnish.binlog -l $LOG -d -c test.conf ../trackrdrd -D -f $1 -l $LOG -d -c test.conf
# Check ckums of the log with and without logs from the worker thread, # Check ckums of the log with and without logs from the worker thread,
# since these are written asynchronously. # since these are written asynchronously.
# the first sed removes the version/revision from the "initializing" line # the first sed removes the version/revision from the "initializing" line
# the second sed removes the user under which the child process runs # the second sed removes the user under which the child process runs
# "Not running as root" filtered so that the test is independent of # "Not running as root" filtered so that the test is independent of
# the user running it # the user running it
CKSUM=$( grep -v 'Worker 1' $LOG | sed -e 's/\(initializing\) \(.*\)/\1/' | sed -e 's/\(Running as\) \([a-zA-Z0-9]*\)$/\1/' | grep -v 'Not running as root' | cksum) CKSUM=$( grep -v 'Worker 1' $LOG | sed -e 's/\(initializing\) \(.*\)/\1/' | sed -e 's/\(Running as\) \([a-zA-Z0-9]*\)$/\1/' | grep -v 'Not running as root' | cksum)
if [ "$CKSUM" != '3352465725 375518' ]; then if [ "$CKSUM" != "$2" ]; then
echo "ERROR: Regression test incorrect reader log cksum: $CKSUM" echo "ERROR: Regression test incorrect reader log cksum: $CKSUM"
exit 1 exit 1
fi fi
# Now check the logs from the worker thread # Now check the logs from the worker thread
# Filter the 'returned to free list' messages, since these may be different # Filter the 'returned to free list' messages, since these may be different
# in different runs. # in different runs.
# Also filter the version/revision from the "connected" line. # Also filter the version/revision from the "connected" line.
CKSUM=$( grep 'Worker 1' $LOG | egrep -v 'returned [0-9]+ [^ ]+ to free list' | sed -e 's/\(connected\) \(.*\)/\1/' | cksum) CKSUM=$( grep 'Worker 1' $LOG | egrep -v 'returned [0-9]+ [^ ]+ to free list' | sed -e 's/\(connected\) \(.*\)/\1/' | cksum)
if [ "$CKSUM" != '3908916621 57319' ]; then if [ "$CKSUM" != "$3" ]; then
echo "ERROR: Regression test incorrect worker log cksum: $CKSUM" echo "ERROR: Regression test incorrect worker log cksum: $CKSUM"
exit 1 exit 1
fi fi
# Check the messages and keys # Check the messages and keys
CKSUM=$(cksum $MSG) CKSUM=$(cksum $MSG)
if [ "$CKSUM" != "1139478852 48689 $MSG" ]; then if [ "$CKSUM" != "$4 $MSG" ]; then
echo "ERROR: Regression test incorrect output cksum: $CKSUM" echo "ERROR: Regression test incorrect output cksum: $CKSUM"
exit 1 exit 1
fi fi
}
echo '... standard VCL_Log syntax'
regress 'varnish.binlog' '4116554635 333344' '1274763305 56045' \
'1485621276 46141'
echo '... legacy VCL_Log syntax'
regress 'varnish.legacy.binlog' '3787836061 375539' '3908916621 57319' \
'1139478852 48689'
exit 0 exit 0
...@@ -46,12 +46,21 @@ static char ...@@ -46,12 +46,21 @@ static char
*test_vcl_log(void) *test_vcl_log(void)
{ {
int err, len; int err, len;
char *data; const char *data;
vcl_log_t type; vcl_log_t type;
printf("... testing Parse_VCL_Log\n"); printf("... testing Parse_VCL_Log\n");
#define VCLLOG "1253687608 url=%2Frdrtestapp%2F" #define VCLLOG_LEGACY "1253687608 url=%2Frdrtestapp%2F"
err = Parse_VCL_Log(VCLLOG_LEGACY, strlen(VCLLOG_LEGACY), &data, &len,
&type);
VMASSERT(err == 0, "VCL_Log %s: %s", VCLLOG_LEGACY, strerror(err));
MASSERT(len == 20);
MASSERT(type == VCL_LOG_DATA);
VMASSERT(strncmp(data, "url=%2Frdrtestapp%2F", 20) == 0,
"VCL_Log %s: returned data=[%.*s]", VCLLOG_LEGACY, len, data);
#define VCLLOG "url=%2Frdrtestapp%2F"
err = Parse_VCL_Log(VCLLOG, strlen(VCLLOG), &data, &len, &type); err = Parse_VCL_Log(VCLLOG, strlen(VCLLOG), &data, &len, &type);
VMASSERT(err == 0, "VCL_Log %s: %s", VCLLOG, strerror(err)); VMASSERT(err == 0, "VCL_Log %s: %s", VCLLOG, strerror(err));
MASSERT(len == 20); MASSERT(len == 20);
...@@ -60,12 +69,26 @@ static char ...@@ -60,12 +69,26 @@ static char
"VCL_Log %s: returned data=[%.*s]", VCLLOG, len, data); "VCL_Log %s: returned data=[%.*s]", VCLLOG, len, data);
err = Parse_VCL_Log("foo", 3, &data, &len, &type); err = Parse_VCL_Log("foo", 3, &data, &len, &type);
VMASSERT(err == EINVAL, "VCL_Log foo: expected EINVAL, got %d", err); VMASSERT(err == 0, "VCL_Log foo: %s", strerror(err));
MASSERT(len == 3);
MASSERT(type == VCL_LOG_DATA);
VMASSERT(strncmp(data, "foo", 3) == 0,
"VCL_Log foo: returned data=[%.*s]", len, data);
#define VCLLOG_INVALID "foo url=%2Frdrtestapp%2F" #define VCLLOG_SPACE "foo url=%2Frdrtestapp%2F"
err = Parse_VCL_Log(VCLLOG_INVALID, 3, &data, &len, &type); err = Parse_VCL_Log(VCLLOG_SPACE, 3, &data, &len, &type);
VMASSERT(err == EINVAL, "VCL_Log %s: expected EINVAL, got %d", VMASSERT(err == 0, "VCL_Log %s: %s", VCLLOG_SPACE, strerror(err));
VCLLOG_INVALID, err); MASSERT(len == 3);
MASSERT(type == VCL_LOG_DATA);
VMASSERT(strncmp(data, "foo", 3) == 0,
"VCL_Log %s: returned data=[%.*s]", VCLLOG_SPACE, len, data);
err = Parse_VCL_Log(VCLLOG_SPACE, strlen(VCLLOG_SPACE), &data, &len, &type);
VMASSERT(err == 0, "VCL_Log foo: %s", strerror(err));
MASSERT(len == strlen(VCLLOG_SPACE));
MASSERT(type == VCL_LOG_DATA);
VMASSERT(strncmp(data, VCLLOG_SPACE, strlen(VCLLOG_SPACE)) == 0,
"VCL_Log %s: returned data=[%.*s]", VCLLOG_SPACE, len, data);
/* 1024 chars */ /* 1024 chars */
#define LONG_STRING \ #define LONG_STRING \
...@@ -85,15 +108,32 @@ static char ...@@ -85,15 +108,32 @@ static char
"1234567890123456789012345678901234567890123456789012345678901234" \ "1234567890123456789012345678901234567890123456789012345678901234" \
"1234567890123456789012345678901234567890123456789012345678901234" \ "1234567890123456789012345678901234567890123456789012345678901234" \
"1234567890123456789012345678901234567890123456789012345678901234" "1234567890123456789012345678901234567890123456789012345678901234"
#define VCLLOG_LONG "1253687608 foo=" LONG_STRING #define VCLLOG_LONG_LEGACY "1253687608 foo=" LONG_STRING
err = Parse_VCL_Log(VCLLOG_LONG, 1039, &data, &len, &type); err = Parse_VCL_Log(VCLLOG_LONG_LEGACY, 1039, &data, &len, &type);
VMASSERT(err == 0, "VCL_Log legacy long string: %s", strerror(err));
MASSERT(len == 1028);
MASSERT(type == VCL_LOG_DATA);
VMASSERT(strncmp(data, "foo=" LONG_STRING, 1028) == 0,
"VCL_Log legacy long string: returned data=[%.*s]", len, data);
#define VCLLOG_LONG "foo=" LONG_STRING
err = Parse_VCL_Log(VCLLOG_LONG, strlen(VCLLOG_LONG), &data, &len, &type);
VMASSERT(err == 0, "VCL_Log long string: %s", strerror(err)); VMASSERT(err == 0, "VCL_Log long string: %s", strerror(err));
MASSERT(len == 1028); MASSERT(len == 1028);
MASSERT(type == VCL_LOG_DATA); MASSERT(type == VCL_LOG_DATA);
VMASSERT(strncmp(data, "foo=" LONG_STRING, 1028) == 0, VMASSERT(strncmp(data, "foo=" LONG_STRING, 1028) == 0,
"VCL_Log long string: returned data=[%.*s]", len, data); "VCL_Log long string: returned data=[%.*s]", len, data);
#define VCLKEY "1253687608 key foobarbazquux" #define VCLKEY_LEGACY "1253687608 key foobarbazquux"
err = Parse_VCL_Log(VCLKEY_LEGACY, strlen(VCLKEY_LEGACY), &data, &len,
&type);
VMASSERT(err == 0, "VCL_Log %s: %s", VCLKEY_LEGACY, strerror(err));
MASSERT(len == 13);
MASSERT(type == VCL_LOG_KEY);
VMASSERT(strncmp(data, "foobarbazquux", 13) == 0,
"VCL_Log %s: returned data=[%.*s]", VCLKEY_LEGACY, len, data);
#define VCLKEY "key foobarbazquux"
err = Parse_VCL_Log(VCLKEY, strlen(VCLKEY), &data, &len, &type); err = Parse_VCL_Log(VCLKEY, strlen(VCLKEY), &data, &len, &type);
VMASSERT(err == 0, "VCL_Log %s: %s", VCLKEY, strerror(err)); VMASSERT(err == 0, "VCL_Log %s: %s", VCLKEY, strerror(err));
MASSERT(len == 13); MASSERT(len == 13);
...@@ -101,8 +141,17 @@ static char ...@@ -101,8 +141,17 @@ static char
VMASSERT(strncmp(data, "foobarbazquux", 13) == 0, VMASSERT(strncmp(data, "foobarbazquux", 13) == 0,
"VCL_Log %s: returned data=[%.*s]", VCLKEY, len, data); "VCL_Log %s: returned data=[%.*s]", VCLKEY, len, data);
#define VCLKEY_LONG "1253687608 key " LONG_STRING #define VCLKEY_LONG_LEGACY "1253687608 key " LONG_STRING
err = Parse_VCL_Log(VCLKEY_LONG, 1039, &data, &len, &type); err = Parse_VCL_Log(VCLKEY_LONG_LEGACY, strlen(VCLKEY_LONG_LEGACY), &data,
&len, &type);
VMASSERT(err == 0, "VCL_Log legacy long key: %s", strerror(err));
MASSERT(len == 1024);
MASSERT(type == VCL_LOG_KEY);
VMASSERT(strncmp(data, LONG_STRING, 1024) == 0,
"VCL_Log legacy long key: returned data=[%.*s]", len, data);
#define VCLKEY_LONG "key " LONG_STRING
err = Parse_VCL_Log(VCLKEY_LONG, 1028, &data, &len, &type);
VMASSERT(err == 0, "VCL_Log long key: %s", strerror(err)); VMASSERT(err == 0, "VCL_Log long key: %s", strerror(err));
MASSERT(len == 1024); MASSERT(len == 1024);
MASSERT(type == VCL_LOG_KEY); MASSERT(type == VCL_LOG_KEY);
......
No preview for this file type
...@@ -288,6 +288,6 @@ void MON_StatsUpdate(stats_update_t update, unsigned nchunks, unsigned nbytes); ...@@ -288,6 +288,6 @@ void MON_StatsUpdate(stats_update_t update, unsigned nchunks, unsigned nbytes);
/* Whether a VCL_Log entry contains a data payload or a shard key */ /* Whether a VCL_Log entry contains a data payload or a shard key */
typedef enum { VCL_LOG_DATA, VCL_LOG_KEY } vcl_log_t; typedef enum { VCL_LOG_DATA, VCL_LOG_KEY } vcl_log_t;
int Parse_VCL_Log(const char *ptr, int len, char **data, int *datalen, int Parse_VCL_Log(const char *ptr, int len, const char **data, int *datalen,
vcl_log_t *type); vcl_log_t *type);
int Parse_Timestamp(const char *ptr, int len, struct timeval *t); int Parse_Timestamp(const char *ptr, int len, struct timeval *t);
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