diff --git a/.gitignore b/.gitignore index 12120ba..4a0333c 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,6 @@ Makefile.in /src/vcc_if.c /src/vcc_if.h +/src/vmod_statsd.man.rst +/src/vmod_statsd.rst +/vmod_statsd.3 diff --git a/Makefile.am b/Makefile.am index e1dd81e..eb75ddb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,18 +1,26 @@ -ACLOCAL_AMFLAGS = -I m4 +ACLOCAL_AMFLAGS = -I m4 -I ${LIBVARNISHAPI_DATAROOTDIR}/aclocal SUBDIRS = src -EXTRA_DIST = README.rst +DISTCHECK_CONFIGURE_FLAGS = \ + VMOD_DIR='$${libdir}/varnish/vmods' + +EXTRA_DIST = README.rst LICENSE vmod-statsd.spec debian + +doc_DATA = README.rst LICENSE dist_man_MANS = vmod_statsd.3 MAINTAINERCLEANFILES = $(dist_man_MANS) vmod_statsd.3: README.rst + +%.1 %.2 %.3 %.4 %.5 %.6 %.7 %.8 %.9: if HAVE_RST2MAN - ${RST2MAN} README.rst $@ + ${RST2MAN} $< $@ else @echo "========================================" @echo "You need rst2man installed to make dist" @echo "========================================" @false endif + diff --git a/README.rst b/README.rst index 6b40d3e..664edea 100644 --- a/README.rst +++ b/README.rst @@ -31,7 +31,9 @@ SYNOPSIS DESCRIPTION =========== -Varnish Module (vmod) for sending statistics to Statsd. +Varnish 4.x Module (vmod) for sending statistics to Statsd. + +See https://github.com/jib/libvmod-statsd/tree/master for Varnish 3.x version. See https://github.com/etsy/statsd for documentation on Statsd. @@ -190,11 +192,7 @@ Usage:: ./autogen.sh # Execute configure script - ./configure VARNISHSRC=DIR [VMODDIR=DIR] - -`VARNISHSRC` is the directory of the Varnish source tree for which to -compile your vmod. Both the `VARNISHSRC` and `VARNISHSRC/include` -will be added to the include search paths for your module. + ./configure Optionally you can also set the vmod install directory by adding `VMODDIR=DIR` (defaults to the pkg-config discovered directory from your diff --git a/autogen.sh b/autogen.sh index 9a12ef5..55f7894 100755 --- a/autogen.sh +++ b/autogen.sh @@ -35,9 +35,18 @@ else esac fi +# check for varnishapi.m4 in custom paths +dataroot=$(pkg-config --variable=datarootdir varnishapi 2>/dev/null) +if [ -z "$dataroot" ] ; then + cat >&2 <<'EOF' +Package varnishapi was not found in the pkg-config search path. +Perhaps you should add the directory containing `varnishapi.pc' +to the PKG_CONFIG_PATH environment variable +EOF + exit 1 +fi set -ex - -aclocal -I m4 +aclocal -I m4 -I ${dataroot}/aclocal $LIBTOOLIZE --copy --force autoheader automake --add-missing --copy --foreign diff --git a/configure.ac b/configure.ac index 7d43f70..6d4e3b7 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,8 @@ AC_PREREQ(2.59) -AC_COPYRIGHT([Copyright (c) 2011 Varnish Software AS]) +AC_COPYRIGHT([Copyright (c) 2011-2015 Varnish Software AS]) AC_INIT([libvmod-statsd], [trunk]) AC_CONFIG_MACRO_DIR([m4]) +m4_ifndef([VARNISH_VMOD_INCLUDES], AC_MSG_ERROR([Need varnish.m4 -- see README.rst])) AC_CONFIG_SRCDIR(src/vmod_statsd.vcc) AM_CONFIG_HEADER(config.h) @@ -29,43 +30,43 @@ if test "x$RST2MAN" = "xno"; then fi AM_CONDITIONAL(HAVE_RST2MAN, [test "x$RST2MAN" != "xno"]) -# Check for pkg-config -PKG_PROG_PKG_CONFIG - # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS([sys/stdlib.h]) -# Check for python -AC_CHECK_PROGS(PYTHON, [python3 python3.1 python3.2 python2.7 python2.6 python2.5 python2 python], [AC_MSG_ERROR([Python is needed to build this vmod, please install python.])]) +# backwards compat with older pkg-config +# - pull in AC_DEFUN from pkg.m4 +m4_ifndef([PKG_CHECK_VAR], [ +# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# ------------------------------------------- +# Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl -# Varnish source tree -AC_ARG_VAR([VARNISHSRC], [path to Varnish source tree (mandatory)]) -if test "x$VARNISHSRC" = x; then - AC_MSG_ERROR([No Varnish source tree specified]) -fi -VARNISHSRC=`cd $VARNISHSRC && pwd` -AC_CHECK_FILE([$VARNISHSRC/include/varnishapi.h], - [], - [AC_MSG_FAILURE(["$VARNISHSRC" is not a Varnish source directory])] -) -AM_CONDITIONAL(HAVE_VARNISHSRC, [test -n $VARNISHSRC]) +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])# PKG_CHECK_VAR +]) -# Check that varnishtest is built in the varnish source directory -AC_CHECK_FILE([$VARNISHSRC/bin/varnishtest/varnishtest], - [], - [AC_MSG_FAILURE([Can't find "$VARNISHSRC/bin/varnishtest/varnishtest". Please build your varnish source directory])] -) +PKG_CHECK_MODULES([libvarnishapi], [varnishapi]) +PKG_CHECK_VAR([LIBVARNISHAPI_DATAROOTDIR], [varnishapi], [datarootdir]) +PKG_CHECK_VAR([LIBVARNISHAPI_BINDIR], [varnishapi], [bindir]) +PKG_CHECK_VAR([LIBVARNISHAPI_SBINDIR], [varnishapi], [sbindir]) +AC_SUBST([LIBVARNISHAPI_DATAROOTDIR]) -# vmod installation dir -AC_ARG_VAR([VMODDIR], [vmod installation directory @<:@LIBDIR/varnish/vmods@:>@]) -if test "x$VMODDIR" = x; then - VMODDIR=`pkg-config --variable=vmoddir varnishapi` - if test "x$VMODDIR" = x; then - AC_MSG_FAILURE([Can't determine vmod installation directory]) - fi -fi -AM_CONDITIONAL(HAVE_VMODDIR, [test -n $VMODDIR]) +# Varnish include files tree +VARNISH_VMOD_INCLUDES +VARNISH_VMOD_DIR +VARNISH_VMODTOOL + +AC_PATH_PROG([VARNISHTEST], [varnishtest], [], + [$LIBVARNISHAPI_BINDIR:$LIBVARNISHAPI_SBINDIR:$PATH]) +AC_PATH_PROG([VARNISHD], [varnishd], [], + [$LIBVARNISHAPI_SBINDIR:$LIBVARNISHAPI_BINDIR:$PATH]) AC_CONFIG_FILES([ Makefile diff --git a/src/Makefile.am b/src/Makefile.am index 32a5f77..74e226a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,23 +1,6 @@ -# if VARNISHSRC is defined on the command-line, use that. Otherwise, build -# this the same as the modules that come with varnish (i.e. we're building -# within the varnish src dir itself, and $(top_srcdir) is the varnish source). -# -if HAVE_VARNISHSRC -SRC = $(VARNISHSRC) -DIR_PREFIX = / -else -SRC = $(top_srcdir) -DIR_PREFIX = lib/libvmod-statsd/ -endif - -INCLUDES = -I$(SRC)/include -I$(SRC) - -if HAVE_VMODDIR -vmoddir = $(VMODDIR) -else -vmoddir = $(pkglibdir)/vmods -endif +AM_CPPFLAGS = @VMOD_INCLUDES@ +vmoddir = @VMOD_DIR@ vmod_LTLIBRARIES = libvmod_statsd.la libvmod_statsd_la_LDFLAGS = -module -export-dynamic -avoid-version @@ -27,14 +10,14 @@ libvmod_statsd_la_SOURCES = \ vcc_if.h \ vmod_statsd.c -vcc_if.c vcc_if.h: $(SRC)/lib/libvmod_std/vmod.py $(top_srcdir)/$(DIR_PREFIX)src/vmod_statsd.vcc - @PYTHON@ $(SRC)/lib/libvmod_std/vmod.py $(top_srcdir)/$(DIR_PREFIX)src/vmod_statsd.vcc +vcc_if.c vcc_if.h: @VMODTOOL@ $(top_srcdir)/$(DIR_PREFIX)src/vmod_statsd.vcc + @VMODTOOL@ $(top_srcdir)/$(DIR_PREFIX)src/vmod_statsd.vcc -VMOD_TESTS = tests/*.vtc +VMOD_TESTS = $(top_srcdir)/src/tests/*.vtc .PHONY: $(VMOD_TESTS) -tests/*.vtc: - $(SRC)/bin/varnishtest/varnishtest -Dvarnishd=$(SRC)/bin/varnishd/varnishd -Dvmod_topbuild=$(abs_top_builddir) $@ +$(top_srcdir)/src/tests/*.vtc: + @VARNISHTEST@ -Dvarnishd=@VARNISHD@ -Dvmod_topbuild=$(abs_top_builddir) $@ check: $(VMOD_TESTS) @@ -42,4 +25,7 @@ EXTRA_DIST = \ vmod_statsd.vcc \ $(VMOD_TESTS) -CLEANFILES = $(builddir)/vcc_if.c $(builddir)/vcc_if.h +CLEANFILES = $(builddir)/vcc_if.c $(builddir)/vcc_if.h \ + $(builddir)/vmod_statsd.man.rst \ + $(builddir)/vmod_statsd.rst \ + $(builddir)/../vmod_statsd.3 diff --git a/src/tests/test02.vtc b/src/tests/test02.vtc new file mode 100644 index 0000000..b344028 --- /dev/null +++ b/src/tests/test02.vtc @@ -0,0 +1,46 @@ +varnishtest "Test sending stats" + +server s1 { + rxreq + txresp +} -start + +# XXX I don't know how to test reception of UDP packets from varnish, +# so for now, these tests just make sure that the process doesn't crash, +# hang, or do anything else bad + +varnish v1 -vcl+backend { + import statsd from "${vmod_topbuild}/src/.libs/libvmod_statsd.so"; + + sub vcl_init { + statsd.server("localhost", "1"); # nothing listens on UDP port 1 right? + statsd.prefix("prefix"); + statsd.suffix("suffix"); + } + + sub vcl_deliver { + statsd.incr( "incr" ); + statsd.gauge( "gauge", 1234567890 ); + statsd.timing( "timing", 1234567890 ); + statsd.counter( "counter", 1234567890 ); + + # So we know we got to at least here. + set resp.http.hello = "Hello, World"; + } + +} -start + +logexpect l1 -v v1 { + expect * * VCL_Log "vmod-statsd: Sent 20 of 20 bytes " + expect * * VCL_Log "Could not write stat 'prefixgaugesuffix:1234567890|g'" +} -start + +client c1 { + txreq -url "/" + rxresp + expect resp.http.hello == "Hello, World" +} + +client c1 -run + +logexpect l1 -wait diff --git a/src/vmod_statsd.c b/src/vmod_statsd.c index bff5101..9b0f515 100644 --- a/src/vmod_statsd.c +++ b/src/vmod_statsd.c @@ -2,8 +2,18 @@ #include #include -#include "vrt.h" -#include "bin/varnishd/cache.h" +#include +#include + +#ifndef VRT_H_INCLUDED +#include +#endif + +#ifndef VDEF_H_INCLUDED +#include +#endif + + #include "vcc_if.h" @@ -17,13 +27,6 @@ #define BUF_SIZE 500 -//#define DEBUG 1 - -#ifdef DEBUG // To print diagnostics to the error log -#define _DEBUG 1 // enable through gcc -DDEBUG -#else -#define _DEBUG 0 -#endif typedef struct statsdConfig { char *host; // statsd host @@ -53,7 +56,6 @@ _strip_newline( char *line ) { *pos = '\0'; } - //_DEBUG && fprintf( stderr, "vmod-statsd: stripping new lines. New string: %s\n", line ); return line; @@ -67,20 +69,21 @@ static void free_function(void *priv) { config_t *cfg = priv; if( cfg->socket > 0 ) { - _DEBUG && fprintf( stderr, "vmod-statsd: free: Closing socket with FD %d\n", cfg->socket ); int close_ret = close( cfg->socket ); if( close_ret != 0 ) { int close_error = errno; - _DEBUG && fprintf( stderr, "vmod-statsd: free: Error closing socket: %s (errno %d)\n", - strerror(close_error), close_error ); + //VSLb(ctx->vsl, SLT_VCL_Log, "vmod-statsd: free: Error closing socket: %s (errno %d)\n", + // strerror(close_error), close_error ); } cfg->socket = 0; - _DEBUG && fprintf( stderr, "vmod-statsd: free: Socket closed/reset\n" ); } } int -init_function(struct vmod_priv *priv, const struct VCL_conf *conf) { +init_function(const struct vrt_ctx *ctx, struct vmod_priv *priv, enum vcl_event_e e) { + + if (e != VCL_EVENT_LOAD) + return (0); // ****************************** // Configuration defaults @@ -94,7 +97,7 @@ init_function(struct vmod_priv *priv, const struct VCL_conf *conf) { cfg->suffix = ""; cfg->socket = 0; - _DEBUG && fprintf( stderr, "vmod-statsd: init: configuration initialized\n" ); + //VSLb(ctx->vsl, SLT_VCL_Log,"vmod-statsd: init: configuration intitialized"); // ****************************** // Store the config @@ -107,23 +110,23 @@ init_function(struct vmod_priv *priv, const struct VCL_conf *conf) { } /** The following may ONLY be called from VCL_init **/ -void -vmod_prefix( struct sess *sp, struct vmod_priv *priv, const char *prefix ) { +VCL_VOID +vmod_prefix( const struct vrt_ctx *ctx, struct vmod_priv *priv, const char *prefix ) { config_t *cfg = priv->priv; cfg->prefix = _strip_newline( strdup( prefix ) ); } /** The following may ONLY be called from VCL_init **/ -void -vmod_suffix( struct sess *sp, struct vmod_priv *priv, const char *suffix ) { +VCL_VOID +vmod_suffix( const struct vrt_ctx *ctx, struct vmod_priv *priv, const char *suffix ) { config_t *cfg = priv->priv; cfg->suffix = _strip_newline( strdup( suffix ) ); } /** The following may ONLY be called from VCL_init **/ -void -vmod_server( struct sess *sp, struct vmod_priv *priv, const char *host, const char *port ) { +VCL_VOID +vmod_server( const struct vrt_ctx *ctx, struct vmod_priv *priv, VCL_STRING host, VCL_STRING port ) { // ****************************** // Configuration @@ -140,7 +143,7 @@ vmod_server( struct sess *sp, struct vmod_priv *priv, const char *host, const ch // ****************************** int -_connect_to_statsd( struct vmod_priv *priv ) { +_connect_to_statsd( struct vmod_priv *priv , const struct vrt_ctx * ctx) { config_t *cfg = priv->priv; // Grab 2 structs for the connection @@ -149,7 +152,8 @@ _connect_to_statsd( struct vmod_priv *priv ) { hints = malloc(sizeof(struct addrinfo)); if (hints == NULL) { - fprintf( stderr, "vmod-statsd: malloc failed for hints addrinfo struct\n" ); + fprintf( stderr, "" ); + VSLb(ctx->vsl, SLT_VCL_Log,"vmod-statsd: malloc failed for hints addrinfo struct"); return -1; } @@ -165,20 +169,17 @@ _connect_to_statsd( struct vmod_priv *priv ) { hints->ai_protocol = IPPROTO_UDP; hints->ai_flags = 0; - _DEBUG && fprintf( stderr, "vmod-statsd: socket hints compiled\n" ); // using getaddrinfo lets us use a hostname, rather than an // ip address. int err; if( (err = getaddrinfo( cfg->host, cfg->port, hints, &statsd )) != 0 ) { - fprintf( stderr, "vmod-statsd: getaddrinfo on %s:%s failed: %s\n", - cfg->host, cfg->port, gai_strerror(err) ); + VSLb(ctx->vsl, SLT_VCL_Log,"vmod-statsd: getaddrinfo on %s:%s failed: %s", cfg->host, cfg->port, gai_strerror(err)); freeaddrinfo( hints ); return -1; } - _DEBUG && fprintf( stderr, "vmod-statsd: getaddrinfo completed\n" ); // ****************************** // Store the open connection @@ -191,18 +192,17 @@ _connect_to_statsd( struct vmod_priv *priv ) { statsd->ai_protocol ); if( cfg->socket == -1 ) { - _DEBUG && fprintf( stderr, "vmod-statsd: socket creation failed\n" ); + VSLb(ctx->vsl, SLT_VCL_Log,"vmod-statsd: socket creation failed"); close( cfg->socket ); freeaddrinfo( statsd ); freeaddrinfo( hints ); return -1; } - _DEBUG && fprintf( stderr, "vmod-statsd: socket opened: %d\n", cfg->socket ); // connection failed.. for some reason... if( connect( cfg->socket, statsd->ai_addr, statsd->ai_addrlen ) == -1 ) { - _DEBUG && fprintf( stderr, "vmod-statsd: socket connection failed\n" ); + VSLb(ctx->vsl, SLT_VCL_Log,"vmod-statsd: socket conection failed"); close( cfg->socket ); freeaddrinfo( statsd ); @@ -210,36 +210,30 @@ _connect_to_statsd( struct vmod_priv *priv ) { return -1; } - _DEBUG && fprintf( stderr, "vmod-statsd: socket connected\n" ); // now that we have an outgoing socket, we don't need this // anymore. freeaddrinfo( statsd ); freeaddrinfo( hints ); - _DEBUG && fprintf( stderr, "vmod-statsd: statsd server: %s:%s (fd: %d)\n", - cfg->host, cfg->port, cfg->socket ); + VSLb(ctx->vsl, SLT_VCL_Log,"vmod-statsd: statsd server: %s:%s (fd: %d)", cfg->host, cfg->port, cfg->socket ); return cfg->socket; } int -_send_to_statsd( struct vmod_priv *priv, const char *key, const char *val ) { - _DEBUG && fprintf( stderr, "vmod-statsd: pre config\n" ); - +_send_to_statsd( struct vmod_priv *priv, const char *key, const char *val, const struct vrt_ctx *ctx) { config_t *cfg = priv->priv; - _DEBUG && fprintf( stderr, "vmod-statsd: post config\n" ); // If you are using some empty key, bail - this can happen if you use // say: statsd.incr( req.http.x-does-not-exist ). Rather than getting // and empty string, we get a null pointer. if( key == NULL || val == NULL ) { - _DEBUG && fprintf( stderr, "vmod-statsd: Key or value is NULL pointer - ignoring\n" ); + VSLb( ctx->vsl, SLT_VCL_Log, "vmod-statsd: Key or value is NULL pointer - ignoring" ); return -1; } - _DEBUG && fprintf( stderr, "vmod-statsd: pre stat composition\n" ); // Enough room for the key/val plus prefix/suffix plus newline plus a null byte. char stat[ strlen(key) + strlen(val) + @@ -250,7 +244,6 @@ _send_to_statsd( struct vmod_priv *priv, const char *key, const char *val ) { strncat( stat, cfg->suffix, strlen(cfg->suffix) + 1 ); strncat( stat, val, strlen(val) + 1 ); - _DEBUG && fprintf( stderr, "vmod-statsd: post stat composition: %s\n", stat ); // Newer versions of statsd allow multiple metrics in a single packet, delimited // by newlines. That unfortunately means that if we end our message with a new @@ -260,21 +253,19 @@ _send_to_statsd( struct vmod_priv *priv, const char *key, const char *val ) { // modern statsds. //strncat( stat, "\n", 1 ); - //_DEBUG && fprintf( stderr, "vmod-statsd: send: %s:%s %s\n", cfg->host, cfg->port, stat ); + //VSLb(ctx->vsl, SLT_VCL_Log, "vmod-statsd: send: %s:%s %s\n", cfg->host, cfg->port, stat ); // ****************************** // Sanity checks // ****************************** - _DEBUG && fprintf( stderr, "vmod-statsd: pre stat length\n" ); int len = strlen( stat ); - _DEBUG && fprintf( stderr, "vmod-statsd: stat length: %d\n", len ); // +1 for the null byte if( len + 1 >= BUF_SIZE ) { - _DEBUG && fprintf( stderr, "vmod-statsd: Message length %d > max length %d - ignoring\n", + VSLb( ctx->vsl, SLT_VCL_Log, "vmod-statsd: Message length %d > max length %d - ignoring", len, BUF_SIZE ); return -1; } @@ -283,41 +274,39 @@ _send_to_statsd( struct vmod_priv *priv, const char *key, const char *val ) { // Send the packet // ****************************** - _DEBUG && fprintf( stderr, "vmod-statsd: Checking for existing socket (%d)\n", cfg->socket ); // we may not have connected yet - in that case, do it now - int sock = cfg->socket > 0 ? cfg->socket : _connect_to_statsd( priv ); + int sock = cfg->socket > 0 ? cfg->socket : _connect_to_statsd( priv, ctx ); // If we didn't get a socket, don't bother trying to send if( sock == -1 ) { - _DEBUG && fprintf( stderr, "vmod-statsd: Could not get socket for %s\n", stat ); + VSLb( ctx->vsl, SLT_VCL_Log, "vmod-statsd: Could not get socket for %s", stat ); return -1; } // Send the stat int sent = write( sock, stat, len ); - _DEBUG && fprintf( stderr, "vmod-statsd: Sent %d of %d bytes to FD %d\n", sent, len, sock ); + VSLb(ctx->vsl, SLT_VCL_Log, "vmod-statsd: Sent %d of %d bytes to FD %d", sent, len, sock ); // An error occurred - unset the socket so that the next write may try again if( sent != len ) { int write_error = errno; - _DEBUG && fprintf( stderr, "vmod-statsd: Could not write stat '%s': %s (errno %d)\n", + VSLb(ctx->vsl, SLT_VCL_Log, "vmod-statsd: Could not write stat '%s': %s (errno %d)", stat, strerror(write_error), write_error ); // if the write_error is not due to a bad file descriptor, try to close the socket first if( write_error != 9 ) { - _DEBUG && fprintf( stderr, "vmod-statsd: Closing socket with FD: %d\n", sock ); int close_ret_val = close( sock ); if( close_ret_val != 0 ) { int close_error = errno; - _DEBUG && fprintf( stderr, "vmod-statsd: Error closing socket: %s (errno %d)\n", + VSLb(ctx->vsl, SLT_VCL_Log, "vmod-statsd: Error closing socket: %s (errno %d)", strerror(close_error), close_error ); } } // reset the socket cfg->socket = 0; - _DEBUG && fprintf( stderr, "vmod-statsd: Socket closed/reset\n" ); + VSLb(ctx->vsl, SLT_VCL_Log, "vmod-statsd: Socket closed/reset" ); return -1; } @@ -326,17 +315,17 @@ _send_to_statsd( struct vmod_priv *priv, const char *key, const char *val ) { } -void -vmod_incr( struct sess *sp, struct vmod_priv *priv, const char *key ) { - _DEBUG && fprintf( stderr, "vmod-statsd: incr: %s\n", key ); +VCL_VOID +vmod_incr( const struct vrt_ctx *ctx, struct vmod_priv *priv, VCL_STRING key ) { + VSLb(ctx->vsl, SLT_VCL_Log, "vmod-statsd: incr: %s", key ); // Incremenet is straight forward - just add the count + type - _send_to_statsd( priv, key, ":1|c" ); + _send_to_statsd( priv, key, ":1|c" , ctx); } -void -vmod_timing( struct sess *sp, struct vmod_priv *priv, const char *key, int num ) { - _DEBUG && fprintf( stderr, "vmod-statsd: timing: %s = %d\n", key, num ); +VCL_VOID +vmod_timing( const struct vrt_ctx *ctx, struct vmod_priv *priv, const char *key, VCL_INT num ) { + VSLb(ctx->vsl, SLT_VCL_Log, "vmod-statsd: timing: %s = %d", key, num ); // Get the buffer ready. 10 for the maximum lenghth of an int and +5 for metadata char val[ 15 ]; @@ -344,12 +333,12 @@ vmod_timing( struct sess *sp, struct vmod_priv *priv, const char *key, int num ) // looks like glork:320|ms snprintf( val, sizeof(val), ":%d|ms", num ); - _send_to_statsd( priv, key, val ); + _send_to_statsd( priv, key, val , ctx); } -void -vmod_counter( struct sess *sp, struct vmod_priv *priv, const char *key, int num ) { - _DEBUG && fprintf( stderr, "vmod-statsd: counter: %s = %d\n", key, num ); +VCL_VOID +vmod_counter( const struct vrt_ctx *ctx, struct vmod_priv *priv, const char *key, VCL_INT num ) { + VSLb(ctx->vsl, SLT_VCL_Log, "vmod-statsd: counter: %s = %d", key, num ); // Get the buffer ready. 10 for the maximum lenghth of an int and +5 for metadata char val[ 15 ]; @@ -357,12 +346,12 @@ vmod_counter( struct sess *sp, struct vmod_priv *priv, const char *key, int num // looks like: gorets:42|c snprintf( val, sizeof(val), ":%d|c", num ); - _send_to_statsd( priv, key, val ); + _send_to_statsd( priv, key, val , ctx); } -void -vmod_gauge( struct sess *sp, struct vmod_priv *priv, const char *key, int num ) { - _DEBUG && fprintf( stderr, "vmod-statsd: gauge: %s = %d\n", key, num ); +VCL_VOID +vmod_gauge( const struct vrt_ctx *ctx, struct vmod_priv *priv, const char *key, VCL_INT num ) { + VSLb(ctx->vsl, SLT_VCL_Log, "vmod-statsd: gauge: %s = %d", key, num ); // Get the buffer ready. 10 for the maximum lenghth of an int and +5 for metadata char val[ 15 ]; @@ -370,30 +359,6 @@ vmod_gauge( struct sess *sp, struct vmod_priv *priv, const char *key, int num ) // looks like: gaugor:333|g snprintf( val, sizeof(val), ":%d|g", num ); - _send_to_statsd( priv, key, val ); + _send_to_statsd( priv, key, val, ctx ); } - -// const char * -// vmod_hello(struct sess *sp, const char *name) -// { -// char *p; -// unsigned u, v; -// -// u = WS_Reserve(sp->wrk->ws, 0); /* Reserve some work space */ -// p = sp->wrk->ws->f; /* Front of workspace area */ -// v = snprintf(p, u, "Hello, %s", name); -// v++; -// if (v > u) { -// /* No space, reset and leave */ -// WS_Release(sp->wrk->ws, 0); -// return (NULL); -// } -// /* Update work space with what we've used */ -// WS_Release(sp->wrk->ws, v); -// return (p); -// } - -// _DEBUG && fprintf( stderr, "vmod-statsd: Open: %.9f Req: %.9f Res: %.9f End: %.9f\n", -// sp->t_open, sp->t_req, sp->t_resp, sp->t_end ); - diff --git a/src/vmod_statsd.vcc b/src/vmod_statsd.vcc index 7d5a787..0a1d73f 100644 --- a/src/vmod_statsd.vcc +++ b/src/vmod_statsd.vcc @@ -1,9 +1,9 @@ -Module statsd -Init init_function -Function VOID server( PRIV_VCL, STRING, STRING ) -Function VOID prefix( PRIV_VCL, STRING ) -Function VOID suffix( PRIV_VCL, STRING ) -Function VOID incr( PRIV_VCL, STRING ) -Function VOID gauge( PRIV_VCL, STRING, INT ) -Function VOID timing( PRIV_VCL, STRING, INT ) -Function VOID counter( PRIV_VCL, STRING, INT ) +$Module statsd 3 StatsD Client +$Event init_function +$Function VOID server( PRIV_VCL, STRING, STRING ) +$Function VOID prefix( PRIV_VCL, STRING ) +$Function VOID suffix( PRIV_VCL, STRING ) +$Function VOID incr( PRIV_VCL, STRING ) +$Function VOID gauge( PRIV_VCL, STRING, INT ) +$Function VOID timing( PRIV_VCL, STRING, INT ) +$Function VOID counter( PRIV_VCL, STRING, INT ) diff --git a/vmod-statsd.spec b/vmod-statsd.spec new file mode 100644 index 0000000..b50ff8e --- /dev/null +++ b/vmod-statsd.spec @@ -0,0 +1,41 @@ +Summary: Varnish module for sending statistics to statsd. +Name: vmod-statsd +Version: 0.1 +Release: 1%{?dist} +License: BSD +Group: System Environment/Daemons +Source0: libvmod-statsd.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +Requires: varnish >= 4.0.2 +BuildRequires: make +BuildRequires: python-docutils +BuildRequires: varnish >= 4.0.2 +BuildRequires: varnish-libs-devel >= 4.0.2 + +%description +Example VMOD + +%prep +%setup -n libvmod-statsd-trunk + +%build +%configure --prefix=/usr/ +%{__make} %{?_smp_mflags} +%{__make} %{?_smp_mflags} check + +%install +[ %{buildroot} != "/" ] && %{__rm} -rf %{buildroot} +%{__make} install DESTDIR=%{buildroot} + +%clean +[ %{buildroot} != "/" ] && %{__rm} -rf %{buildroot} + +%files +%defattr(-,root,root,-) +%{_libdir}/varnis*/vmods/ +%doc /usr/share/doc/lib%{name}/* +%{_mandir}/man?/* + +%changelog +* Tue Nov 14 2012 Lasse Karstensen - 0.1-0.20121114 +- Initial version.