write_kafka: Fix misleading indentation
[collectd.git] / src / varnish.c
index 5de3389..a138d18 100644 (file)
  *   Florian octo Forster <octo at collectd.org>
  **/
 
-/**
- * Current list of what is monitored and what is not monitored (yet)
- * {{{
- * Field name           Description                           Monitored
- * ----------           -----------                           ---------
- * uptime               Child uptime                              N
- * client_conn          Client connections accepted               Y
- * client_drop          Connection dropped, no sess               Y
- * client_req           Client requests received                  Y
- * cache_hit            Cache hits                                Y
- * cache_hitpass        Cache hits for pass                       Y
- * cache_miss           Cache misses                              Y
- * backend_conn         Backend conn. success                     Y
- * backend_unhealthy    Backend conn. not attempted               Y
- * backend_busy         Backend conn. too many                    Y
- * backend_fail         Backend conn. failures                    Y
- * backend_reuse        Backend conn. reuses                      Y
- * backend_toolate      Backend conn. was closed                  Y
- * backend_recycle      Backend conn. recycles                    Y
- * backend_unused       Backend conn. unused                      Y
- * fetch_head           Fetch head                                Y
- * fetch_length         Fetch with Length                         Y
- * fetch_chunked        Fetch chunked                             Y
- * fetch_eof            Fetch EOF                                 Y
- * fetch_bad            Fetch had bad headers                     Y
- * fetch_close          Fetch wanted close                        Y
- * fetch_oldhttp        Fetch pre HTTP/1.1 closed                 Y
- * fetch_zero           Fetch zero len                            Y
- * fetch_failed         Fetch failed                              Y
- * n_sess_mem           N struct sess_mem                         N
- * n_sess               N struct sess                             N
- * n_object             N struct object                           N
- * n_vampireobject      N unresurrected objects                   N
- * n_objectcore         N struct objectcore                       N
- * n_objecthead         N struct objecthead                       N
- * n_smf                N struct smf                              N
- * n_smf_frag           N small free smf                          N
- * n_smf_large          N large free smf                          N
- * n_vbe_conn           N struct vbe_conn                         N
- * n_wrk                N worker threads                          Y
- * n_wrk_create         N worker threads created                  Y
- * n_wrk_failed         N worker threads not created              Y
- * n_wrk_max            N worker threads limited                  Y
- * n_wrk_queue          N queued work requests                    Y
- * n_wrk_overflow       N overflowed work requests                Y
- * n_wrk_drop           N dropped work requests                   Y
- * n_backend            N backends                                N
- * n_expired            N expired objects                         N
- * n_lru_nuked          N LRU nuked objects                       N
- * n_lru_saved          N LRU saved objects                       N
- * n_lru_moved          N LRU moved objects                       N
- * n_deathrow           N objects on deathrow                     N
- * losthdr              HTTP header overflows                     N
- * n_objsendfile        Objects sent with sendfile                N
- * n_objwrite           Objects sent with write                   N
- * n_objoverflow        Objects overflowing workspace             N
- * s_sess               Total Sessions                            Y
- * s_req                Total Requests                            Y
- * s_pipe               Total pipe                                Y
- * s_pass               Total pass                                Y
- * s_fetch              Total fetch                               Y
- * s_hdrbytes           Total header bytes                        Y
- * s_bodybytes          Total body bytes                          Y
- * sess_closed          Session Closed                            N
- * sess_pipeline        Session Pipeline                          N
- * sess_readahead       Session Read Ahead                        N
- * sess_linger          Session Linger                            N
- * sess_herd            Session herd                              N
- * shm_records          SHM records                               Y
- * shm_writes           SHM writes                                Y
- * shm_flushes          SHM flushes due to overflow               Y
- * shm_cont             SHM MTX contention                        Y
- * shm_cycles           SHM cycles through buffer                 Y
- * sm_nreq              allocator requests                        Y
- * sm_nobj              outstanding allocations                   Y
- * sm_balloc            bytes allocated                           Y
- * sm_bfree             bytes free                                Y
- * sma_nreq             SMA allocator requests                    Y
- * sma_nobj             SMA outstanding allocations               Y
- * sma_nbytes           SMA outstanding bytes                     Y
- * sma_balloc           SMA bytes allocated                       Y
- * sma_bfree            SMA bytes free                            Y
- * sms_nreq             SMS allocator requests                    Y
- * sms_nobj             SMS outstanding allocations               Y
- * sms_nbytes           SMS outstanding bytes                     Y
- * sms_balloc           SMS bytes allocated                       Y
- * sms_bfree            SMS bytes freed                           Y
- * backend_req          Backend requests made                     N
- * n_vcl                N vcl total                               N
- * n_vcl_avail          N vcl available                           N
- * n_vcl_discard        N vcl discarded                           N
- * n_purge              N total active purges                     N
- * n_purge_add          N new purges added                        N
- * n_purge_retire       N old purges deleted                      N
- * n_purge_obj_test     N objects tested                          N
- * n_purge_re_test      N regexps tested against                  N
- * n_purge_dups         N duplicate purges removed                N
- * hcb_nolock           HCB Lookups without lock                  Y
- * hcb_lock             HCB Lookups with lock                     Y
- * hcb_insert           HCB Inserts                               Y
- * esi_parse            Objects ESI parsed (unlock)               Y
- * esi_errors           ESI parse errors (unlock)                 Y
- * }}}
- */
 #include "collectd.h"
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
-#include <varnish/varnishapi.h>
+#if HAVE_VARNISH_V4
+#include <vapi/vsm.h>
+#include <vapi/vsc.h>
+typedef struct VSC_C_main c_varnish_stats_t;
+#endif
 
 #if HAVE_VARNISH_V3
-# include <varnish/vsc.h>
+#include <varnishapi.h>
+#include <vsc.h>
 typedef struct VSC_C_main c_varnish_stats_t;
 #endif
 
 #if HAVE_VARNISH_V2
+#include <varnishapi.h>
 typedef struct varnish_stats c_varnish_stats_t;
 #endif
 
@@ -151,16 +53,34 @@ struct user_config_s {
        _Bool collect_connections;
        _Bool collect_esi;
        _Bool collect_backend;
+#ifdef HAVE_VARNISH_V3
+       _Bool collect_dirdns;
+#endif
        _Bool collect_fetch;
        _Bool collect_hcb;
+       _Bool collect_objects;
+#if HAVE_VARNISH_V2
+       _Bool collect_purge;
+#else
+       _Bool collect_ban;
+#endif
+       _Bool collect_session;
        _Bool collect_shm;
        _Bool collect_sms;
 #if HAVE_VARNISH_V2
        _Bool collect_sm;
        _Bool collect_sma;
 #endif
+       _Bool collect_struct;
        _Bool collect_totals;
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+       _Bool collect_uptime;
+#endif
+       _Bool collect_vcl;
        _Bool collect_workers;
+#if HAVE_VARNISH_V4
+       _Bool collect_vsm;
+#endif
 };
 typedef struct user_config_s user_config_t; /* }}} */
 
@@ -215,6 +135,397 @@ static int varnish_submit_derive (const char *plugin_instance, /* {{{ */
        return (varnish_submit (plugin_instance, category, type, type_instance, value));
 } /* }}} int varnish_submit_derive */
 
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+static int varnish_monitor (void *priv, const struct VSC_point * const pt) /* {{{ */
+{
+       uint64_t val;
+       const user_config_t *conf;
+       const char *class;
+       const char *name;
+
+       if (pt == NULL)
+               return (0);
+
+       conf = priv;
+
+#if HAVE_VARNISH_V4
+       class = pt->section->fantom->type;
+       name  = pt->desc->name;
+
+       if (strcmp(class, "MAIN") != 0)
+               return (0);
+
+#elif HAVE_VARNISH_V3
+       class = pt->class;
+       name  = pt->name;
+
+       if (strcmp(class, "") != 0)
+               return (0);
+#endif
+
+       val = *(const volatile uint64_t*) pt->ptr;
+
+       if (conf->collect_cache)
+       {
+               if (strcmp(name, "cache_hit") == 0)
+                       return varnish_submit_derive (conf->instance, "cache", "cache_result", "hit",     val);
+               else if (strcmp(name, "cache_miss") == 0)
+                       return varnish_submit_derive (conf->instance, "cache", "cache_result", "miss",    val);
+               else if (strcmp(name, "cache_hitpass") == 0)
+                       return varnish_submit_derive (conf->instance, "cache", "cache_result", "hitpass", val);
+       }
+
+       if (conf->collect_connections)
+       {
+               if (strcmp(name, "client_conn") == 0)
+                       return varnish_submit_derive (conf->instance, "connections", "connections", "accepted", val);
+               else if (strcmp(name, "client_drop") == 0)
+                       return varnish_submit_derive (conf->instance, "connections", "connections", "dropped" , val);
+               else if (strcmp(name, "client_req") == 0)
+                       return varnish_submit_derive (conf->instance, "connections", "connections", "received", val);
+       }
+
+#ifdef HAVE_VARNISH_V3
+       if (conf->collect_dirdns)
+       {
+               if (strcmp(name, "dir_dns_lookups") == 0)
+                       return varnish_submit_derive (conf->instance, "dirdns", "cache_operation", "lookups",    val);
+               else if (strcmp(name, "dir_dns_failed") == 0)
+                       return varnish_submit_derive (conf->instance, "dirdns", "cache_result",    "failed",     val);
+               else if (strcmp(name, "dir_dns_hit") == 0)
+                       return varnish_submit_derive (conf->instance, "dirdns", "cache_result",    "hits",       val);
+               else if (strcmp(name, "dir_dns_cache_full") == 0)
+                       return varnish_submit_derive (conf->instance, "dirdns", "cache_result",    "cache_full", val);
+       }
+#endif
+
+       if (conf->collect_esi)
+       {
+               if (strcmp(name, "esi_errors") == 0)
+                       return varnish_submit_derive (conf->instance, "esi", "total_operations", "error",   val);
+               else if (strcmp(name, "esi_parse") == 0)
+                       return varnish_submit_derive (conf->instance, "esi", "total_operations", "parsed",  val);
+               else if (strcmp(name, "esi_warnings") == 0)
+                       return varnish_submit_derive (conf->instance, "esi", "total_operations", "warning", val);
+       }
+
+       if (conf->collect_backend)
+       {
+               if (strcmp(name, "backend_conn") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "success",       val);
+               else if (strcmp(name, "backend_unhealthy") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "not-attempted", val);
+               else if (strcmp(name, "backend_busy") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "too-many",      val);
+               else if (strcmp(name, "backend_fail") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "failures",      val);
+               else if (strcmp(name, "backend_reuse") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "reuses",        val);
+               else if (strcmp(name, "backend_toolate") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "was-closed",    val);
+               else if (strcmp(name, "backend_recycle") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "recycled",      val);
+               else if (strcmp(name, "backend_unused") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "unused",        val);
+               else if (strcmp(name, "backend_retry") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "retries",       val);
+               else if (strcmp(name, "backend_req") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "http_requests", "requests",    val);
+               else if (strcmp(name, "n_backend") == 0)
+                       return varnish_submit_gauge  (conf->instance, "backend", "backends", "n_backends",       val);
+       }
+
+       if (conf->collect_fetch)
+       {
+               if (strcmp(name, "fetch_head") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "head",        val);
+               else if (strcmp(name, "fetch_length") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "length",      val);
+               else if (strcmp(name, "fetch_chunked") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "chunked",     val);
+               else if (strcmp(name, "fetch_eof") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "eof",         val);
+               else if (strcmp(name, "fetch_bad") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "bad_headers", val);
+               else if (strcmp(name, "fetch_close") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "close",       val);
+               else if (strcmp(name, "fetch_oldhttp") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "oldhttp",     val);
+               else if (strcmp(name, "fetch_zero") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "zero",        val);
+               else if (strcmp(name, "fetch_failed") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "failed",      val);
+               else if (strcmp(name, "fetch_1xx") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_1xx", val);
+               else if (strcmp(name, "fetch_204") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_204", val);
+               else if (strcmp(name, "fetch_304") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_304", val);
+       }
+
+       if (conf->collect_hcb)
+       {
+               if (strcmp(name, "hcb_nolock") == 0)
+                       return varnish_submit_derive (conf->instance, "hcb", "cache_operation", "lookup_nolock", val);
+               else if (strcmp(name, "hcb_lock") == 0)
+                       return varnish_submit_derive (conf->instance, "hcb", "cache_operation", "lookup_lock",   val);
+               else if (strcmp(name, "hcb_insert") == 0)
+                       return varnish_submit_derive (conf->instance, "hcb", "cache_operation", "insert",        val);
+       }
+
+       if (conf->collect_objects)
+       {
+               if (strcmp(name, "n_expired") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "expired",            val);
+               else if (strcmp(name, "n_lru_nuked") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_nuked",          val);
+               else if (strcmp(name, "n_lru_saved") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_saved",          val);
+               else if (strcmp(name, "n_lru_moved") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_moved",          val);
+               else if (strcmp(name, "n_deathrow") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "deathrow",           val);
+               else if (strcmp(name, "losthdr") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "header_overflow",    val);
+               else if (strcmp(name, "n_obj_purged") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "purged",             val);
+               else if (strcmp(name, "n_objsendfile") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "sent_sendfile",      val);
+               else if (strcmp(name, "n_objwrite") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "sent_write",         val);
+               else if (strcmp(name, "n_objoverflow") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "workspace_overflow", val);
+       }
+
+#if HAVE_VARNISH_V3
+       if (conf->collect_ban)
+       {
+               if (strcmp(name, "n_ban") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "total",          val);
+               else if (strcmp(name, "n_ban_add") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "added",          val);
+               else if (strcmp(name, "n_ban_retire") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "deleted",        val);
+               else if (strcmp(name, "n_ban_obj_test") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "objects_tested", val);
+               else if (strcmp(name, "n_ban_re_test") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "regexps_tested", val);
+               else if (strcmp(name, "n_ban_dups") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "duplicate",      val);
+       }
+#endif
+#if HAVE_VARNISH_V4
+       if (conf->collect_ban)
+       {
+               if (strcmp(name, "bans") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "total",     val);
+               else if (strcmp(name, "bans_added") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "added",     val);
+               else if (strcmp(name, "bans_obj") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "obj",       val);
+               else if (strcmp(name, "bans_req") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "req",       val);
+               else if (strcmp(name, "bans_completed") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "completed", val);
+               else if (strcmp(name, "bans_deleted") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "deleted",   val);
+               else if (strcmp(name, "bans_tested") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "tested",    val);
+               else if (strcmp(name, "bans_dups") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "duplicate", val);
+       }
+#endif
+
+       if (conf->collect_session)
+       {
+               if (strcmp(name, "sess_closed") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "closed",    val);
+               else if (strcmp(name, "sess_pipeline") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "pipeline",  val);
+               else if (strcmp(name, "sess_readahead") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "readahead", val);
+               else if (strcmp(name, "sess_conn") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "accepted",  val);
+               else if (strcmp(name, "sess_drop") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "dropped",   val);
+               else if (strcmp(name, "sess_fail") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "failed",    val);
+               else if (strcmp(name, "sess_pipe_overflow") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "overflow",  val);
+               else if (strcmp(name, "sess_queued") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "queued",    val);
+               else if (strcmp(name, "sess_linger") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "linger",    val);
+               else if (strcmp(name, "sess_herd") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "herd",      val);
+       }
+
+       if (conf->collect_shm)
+       {
+               if (strcmp(name, "shm_records") == 0)
+                       return varnish_submit_derive (conf->instance, "shm", "total_operations", "records",    val);
+               else if (strcmp(name, "shm_writes") == 0)
+                       return varnish_submit_derive (conf->instance, "shm", "total_operations", "writes",     val);
+               else if (strcmp(name, "shm_flushes") == 0)
+                       return varnish_submit_derive (conf->instance, "shm", "total_operations", "flushes",    val);
+               else if (strcmp(name, "shm_cont") == 0)
+                       return varnish_submit_derive (conf->instance, "shm", "total_operations", "contention", val);
+               else if (strcmp(name, "shm_cycles") == 0)
+                       return varnish_submit_derive (conf->instance, "shm", "total_operations", "cycles",     val);
+       }
+
+       if (conf->collect_sms)
+       {
+               if (strcmp(name, "sms_nreq") == 0)
+                       return varnish_submit_derive (conf->instance, "sms", "total_requests", "allocator", val);
+               else if (strcmp(name, "sms_nobj") == 0)
+                       return varnish_submit_gauge (conf->instance,  "sms", "requests", "outstanding",     val);
+               else if (strcmp(name, "sms_nbytes") == 0)
+                       return varnish_submit_gauge (conf->instance,  "sms", "bytes", "outstanding",        val);
+               else if (strcmp(name, "sms_balloc") == 0)
+                       return varnish_submit_derive (conf->instance,  "sms", "total_bytes", "allocated",   val);
+               else if (strcmp(name, "sms_bfree") == 0)
+                       return varnish_submit_derive (conf->instance,  "sms", "total_bytes", "free",        val);
+       }
+
+       if (conf->collect_struct)
+       {
+               if (strcmp(name, "n_sess_mem") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "current_sessions", "sess_mem",  val);
+               else if (strcmp(name, "n_sess") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "current_sessions", "sess",      val);
+               else if (strcmp(name, "n_object") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "object",             val);
+               else if (strcmp(name, "n_vampireobject") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "vampireobject",      val);
+               else if (strcmp(name, "n_objectcore") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "objectcore",         val);
+               else if (strcmp(name, "n_waitinglist") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "waitinglist",        val);
+               else if (strcmp(name, "n_objecthead") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "objecthead",         val);
+               else if (strcmp(name, "n_smf") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "smf",                val);
+               else if (strcmp(name, "n_smf_frag") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "smf_frag",           val);
+               else if (strcmp(name, "n_smf_large") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "smf_large",          val);
+               else if (strcmp(name, "n_vbe_conn") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "vbe_conn",           val);
+       }
+
+       if (conf->collect_totals)
+       {
+               if (strcmp(name, "s_sess") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_sessions", "sessions",  val);
+               else if (strcmp(name, "s_req") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_requests", "requests",  val);
+               else if (strcmp(name, "s_pipe") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_operations", "pipe",    val);
+               else if (strcmp(name, "s_pass") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_operations", "pass",    val);
+               else if (strcmp(name, "s_fetch") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_operations", "fetches", val);
+               else if (strcmp(name, "s_synth") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "synth",        val);
+               else if (strcmp(name, "s_req_hdrbytes") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "req_header",   val);
+               else if (strcmp(name, "s_req_bodybytes") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "req_body",     val);
+               else if (strcmp(name, "s_resp_hdrbytes") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "resp_header",  val);
+               else if (strcmp(name, "s_resp_bodybytes") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "resp_body",    val);
+               else if (strcmp(name, "s_pipe_hdrbytes") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "pipe_header",  val);
+               else if (strcmp(name, "s_pipe_in") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "pipe_in",      val);
+               else if (strcmp(name, "s_pipe_out") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "pipe_out",     val);
+               else if (strcmp(name, "n_purges") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_operations", "purges",  val);
+               else if (strcmp(name, "s_hdrbytes") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "header-bytes", val);
+               else if (strcmp(name, "s_bodybytes") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "body-bytes",   val);
+               else if (strcmp(name, "n_gzip") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_operations", "gzip",    val);
+               else if (strcmp(name, "n_gunzip") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_operations", "gunzip",  val);
+       }
+
+       if (conf->collect_uptime)
+       {
+               if (strcmp(name, "uptime") == 0)
+                       return varnish_submit_gauge (conf->instance, "uptime", "uptime", "client_uptime", val);
+       }
+
+       if (conf->collect_vcl)
+       {
+               if (strcmp(name, "n_vcl") == 0)
+                       return varnish_submit_gauge (conf->instance, "vcl", "vcl", "total_vcl",     val);
+               else if (strcmp(name, "n_vcl_avail") == 0)
+                       return varnish_submit_gauge (conf->instance, "vcl", "vcl", "avail_vcl",     val);
+               else if (strcmp(name, "n_vcl_discard") == 0)
+                       return varnish_submit_gauge (conf->instance, "vcl", "vcl", "discarded_vcl", val);
+               else if (strcmp(name, "vmods") == 0)
+                       return varnish_submit_gauge (conf->instance, "vcl", "objects", "vmod",      val);
+       }
+
+       if (conf->collect_workers)
+       {
+               if (strcmp(name, "threads") == 0)
+                       return varnish_submit_gauge (conf->instance, "workers", "threads", "worker",               val);
+               else if (strcmp(name, "threads_created") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "created",       val);
+               else if (strcmp(name, "threads_failed") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "failed",        val);
+               else if (strcmp(name, "threads_limited") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "limited",       val);
+               else if (strcmp(name, "threads_destroyed") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "dropped",       val);
+               else if (strcmp(name, "thread_queue_len") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "queue_length",  "threads",       val);
+               else if (strcmp(name, "n_wrk") == 0)
+                       return varnish_submit_gauge (conf->instance, "workers", "threads", "worker",               val);
+               else if (strcmp(name, "n_wrk_create") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "created",       val);
+               else if (strcmp(name, "n_wrk_failed") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "failed",        val);
+               else if (strcmp(name, "n_wrk_max") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "limited",       val);
+               else if (strcmp(name, "n_wrk_drop") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "dropped",       val);
+               else if (strcmp(name, "n_wrk_queue") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_requests", "queued",       val);
+               else if (strcmp(name, "n_wrk_overflow") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_requests", "overflowed",   val);
+               else if (strcmp(name, "n_wrk_queued") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_requests", "queued",       val);
+               else if (strcmp(name, "n_wrk_lqueue") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_requests", "queue_length", val);
+       }
+
+#if HAVE_VARNISH_V4
+       if (conf->collect_vsm)
+       {
+               if (strcmp(name, "vsm_free") == 0)
+                       return varnish_submit_gauge (conf->instance, "vsm", "bytes", "free",              val);
+               else if (strcmp(name, "vsm_used") == 0)
+                       return varnish_submit_gauge (conf->instance, "vsm", "bytes", "used",              val);
+               else if (strcmp(name, "vsm_cooling") == 0)
+                       return varnish_submit_gauge (conf->instance, "vsm", "bytes", "cooling",           val);
+               else if (strcmp(name, "vsm_overflow") == 0)
+                       return varnish_submit_gauge (conf->instance, "vsm", "bytes", "overflow",          val);
+               else if (strcmp(name, "vsm_overflowed") == 0)
+                       return varnish_submit_derive (conf->instance, "vsm", "total_bytes", "overflowed", val);
+       }
+#endif
+
+       return (0);
+
+} /* }}} static int varnish_monitor */
+#else /* if HAVE_VARNISH_V2 */
 static void varnish_monitor (const user_config_t *conf, /* {{{ */
                const c_varnish_stats_t *stats)
 {
@@ -241,11 +552,9 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
        if (conf->collect_esi)
        {
                /* ESI parse errors (unlock)   */
-               varnish_submit_derive (conf->instance, "esi", "total_operations", "error",  stats->esi_errors);
-#if HAVE_VARNISH_V2
+               varnish_submit_derive (conf->instance, "esi", "total_operations", "error",   stats->esi_errors);
                /* Objects ESI parsed (unlock) */
-               varnish_submit_derive (conf->instance, "esi", "total_operations", "parsed", stats->esi_parse);
-#endif
+               varnish_submit_derive (conf->instance, "esi", "total_operations", "parsed",  stats->esi_parse);
        }
 
        if (conf->collect_backend)
@@ -264,10 +573,12 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance, "backend", "connections", "was-closed"   , stats->backend_toolate);
                /* Backend conn. recycles      */
                varnish_submit_derive (conf->instance, "backend", "connections", "recycled"     , stats->backend_recycle);
-#if HAVE_VARNISH_V2
                /* Backend conn. unused        */
                varnish_submit_derive (conf->instance, "backend", "connections", "unused"       , stats->backend_unused);
-#endif
+               /* Backend requests mades      */
+               varnish_submit_derive (conf->instance, "backend", "http_requests", "requests"   , stats->backend_req);
+               /* N backends                  */
+               varnish_submit_gauge  (conf->instance, "backend", "backends", "n_backends"      , stats->n_backend);
        }
 
        if (conf->collect_fetch)
@@ -302,6 +613,58 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance, "hcb", "cache_operation", "insert",        stats->hcb_insert);
        }
 
+       if (conf->collect_objects)
+       {
+               /* N expired objects             */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "expired",            stats->n_expired);
+               /* N LRU nuked objects           */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_nuked",          stats->n_lru_nuked);
+               /* N LRU saved objects           */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_saved",          stats->n_lru_saved);
+               /* N LRU moved objects           */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_moved",          stats->n_lru_moved);
+               /* N objects on deathrow         */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "deathrow",           stats->n_deathrow);
+               /* HTTP header overflows         */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "header_overflow",    stats->losthdr);
+               /* Objects sent with sendfile    */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "sent_sendfile",      stats->n_objsendfile);
+               /* Objects sent with write       */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "sent_write",         stats->n_objwrite);
+               /* Objects overflowing workspace */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "workspace_overflow", stats->n_objoverflow);
+       }
+
+       if (conf->collect_purge)
+       {
+               /* N total active purges      */
+               varnish_submit_derive (conf->instance, "purge", "total_operations", "total",            stats->n_purge);
+               /* N new purges added         */
+               varnish_submit_derive (conf->instance, "purge", "total_operations", "added",            stats->n_purge_add);
+               /* N old purges deleted       */
+               varnish_submit_derive (conf->instance, "purge", "total_operations", "deleted",          stats->n_purge_retire);
+               /* N objects tested           */
+               varnish_submit_derive (conf->instance, "purge", "total_operations", "objects_tested",   stats->n_purge_obj_test);
+               /* N regexps tested against   */
+               varnish_submit_derive (conf->instance, "purge", "total_operations", "regexps_tested",   stats->n_purge_re_test);
+               /* N duplicate purges removed */
+               varnish_submit_derive (conf->instance, "purge", "total_operations", "duplicate",        stats->n_purge_dups);
+       }
+
+       if (conf->collect_session)
+       {
+               /* Session Closed     */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "closed",    stats->sess_closed);
+               /* Session Pipeline   */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "pipeline",  stats->sess_pipeline);
+               /* Session Read Ahead */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "readahead", stats->sess_readahead);
+               /* Session Linger     */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "linger",    stats->sess_linger);
+               /* Session herd       */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "herd",      stats->sess_herd);
+       }
+
        if (conf->collect_shm)
        {
                /* SHM records                 */
@@ -316,7 +679,6 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance, "shm", "total_operations", "cycles"    , stats->shm_cycles);
        }
 
-#if HAVE_VARNISH_V2
        if (conf->collect_sm)
        {
                /* allocator requests */
@@ -342,7 +704,6 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                /* SMA bytes free */
                varnish_submit_derive (conf->instance,  "sma", "total_bytes", "free" ,     stats->sma_bfree);
        }
-#endif
 
        if (conf->collect_sms)
        {
@@ -358,6 +719,26 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance,  "sms", "total_bytes", "free",        stats->sms_bfree);
        }
 
+       if (conf->collect_struct)
+       {
+               /* N struct sess_mem       */
+               varnish_submit_gauge (conf->instance, "struct", "current_sessions", "sess_mem",  stats->n_sess_mem);
+               /* N struct sess           */
+               varnish_submit_gauge (conf->instance, "struct", "current_sessions", "sess",      stats->n_sess);
+               /* N struct object         */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "object",             stats->n_object);
+               /* N struct objecthead     */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "objecthead",         stats->n_objecthead);
+               /* N struct smf            */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "smf",                stats->n_smf);
+               /* N small free smf         */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "smf_frag",           stats->n_smf_frag);
+               /* N large free smf         */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "smf_large",          stats->n_smf_large);
+               /* N struct vbe_conn        */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "vbe_conn",           stats->n_vbe_conn);
+       }
+
        if (conf->collect_totals)
        {
                /* Total Sessions */
@@ -376,6 +757,16 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance, "totals", "total_bytes", "body-bytes",   stats->s_bodybytes);
        }
 
+       if (conf->collect_vcl)
+       {
+               /* N vcl total     */
+               varnish_submit_gauge (conf->instance, "vcl", "vcl", "total_vcl",     stats->n_vcl);
+               /* N vcl available */
+               varnish_submit_gauge (conf->instance, "vcl", "vcl", "avail_vcl",     stats->n_vcl_avail);
+               /* N vcl discarded */
+               varnish_submit_gauge (conf->instance, "vcl", "vcl", "discarded_vcl", stats->n_vcl_discard);
+       }
+
        if (conf->collect_workers)
        {
                /* worker threads */
@@ -387,17 +778,17 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                /* worker threads limited */
                varnish_submit_derive (conf->instance, "workers", "total_threads", "limited",     stats->n_wrk_max);
                /* dropped work requests */
-               varnish_submit_derive (conf->instance, "workers", "total_requests", "dropped",    stats->n_wrk_drop);
-#ifdef HAVE_VARNISH_V2
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "dropped",     stats->n_wrk_drop);
                /* queued work requests */
                varnish_submit_derive (conf->instance, "workers", "total_requests", "queued",     stats->n_wrk_queue);
                /* overflowed work requests */
                varnish_submit_derive (conf->instance, "workers", "total_requests", "overflowed", stats->n_wrk_overflow);
-#endif
        }
+
 } /* }}} void varnish_monitor */
+#endif
 
-#if HAVE_VARNISH_V3
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
 static int varnish_read (user_data_t *ud) /* {{{ */
 {
        struct VSM_data *vd;
@@ -411,7 +802,9 @@ static int varnish_read (user_data_t *ud) /* {{{ */
        conf = ud->data;
 
        vd = VSM_New();
+#if HAVE_VARNISH_V3
        VSC_Setup(vd);
+#endif
 
        if (conf->instance != NULL)
        {
@@ -420,6 +813,7 @@ static int varnish_read (user_data_t *ud) /* {{{ */
                status = VSM_n_Arg (vd, conf->instance);
                if (status < 0)
                {
+                       VSM_Delete (vd);
                        ERROR ("varnish plugin: VSM_n_Arg (\"%s\") failed "
                                        "with status %i.",
                                        conf->instance, status);
@@ -427,17 +821,37 @@ static int varnish_read (user_data_t *ud) /* {{{ */
                }
        }
 
+#if HAVE_VARNISH_V3
        if (VSC_Open (vd, /* diag = */ 1))
+#else /* if HAVE_VARNISH_V4 */
+       if (VSM_Open (vd))
+#endif
        {
-               ERROR ("varnish plugin: Unable to load statistics.");
+               VSM_Delete (vd);
+               ERROR ("varnish plugin: Unable to open connection.");
 
                return (-1);
        }
 
+#if HAVE_VARNISH_V3
        stats = VSC_Main(vd);
+#else /* if HAVE_VARNISH_V4 */
+       stats = VSC_Main(vd, NULL);
+#endif
+       if (!stats)
+       {
+               VSM_Delete (vd);
+               ERROR ("varnish plugin: Unable to get statistics.");
 
-       varnish_monitor (conf, stats);
-       VSM_Close (vd);
+               return (-1);
+       }
+
+#if HAVE_VARNISH_V3
+       VSC_Iter (vd, varnish_monitor, conf);
+#else /* if HAVE_VARNISH_V4 */
+       VSC_Iter (vd, NULL, varnish_monitor, conf);
+#endif
+       VSM_Delete (vd);
 
        return (0);
 } /* }}} */
@@ -486,16 +900,35 @@ static int varnish_config_apply_default (user_config_t *conf) /* {{{ */
        conf->collect_backend     = 1;
        conf->collect_cache       = 1;
        conf->collect_connections = 1;
+#ifdef HAVE_VARNISH_V3
+       conf->collect_dirdns      = 0;
+#endif
        conf->collect_esi         = 0;
        conf->collect_fetch       = 0;
        conf->collect_hcb         = 0;
+       conf->collect_objects     = 0;
+#if HAVE_VARNISH_V2
+       conf->collect_purge       = 0;
+#else
+       conf->collect_ban         = 0;
+#endif
+       conf->collect_session     = 0;
        conf->collect_shm         = 1;
 #if HAVE_VARNISH_V2
        conf->collect_sm          = 0;
        conf->collect_sma         = 0;
 #endif
        conf->collect_sms         = 0;
+       conf->collect_struct      = 0;
        conf->collect_totals      = 0;
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+       conf->collect_uptime      = 0;
+#endif
+       conf->collect_vcl         = 0;
+       conf->collect_workers     = 0;
+#if HAVE_VARNISH_V4
+       conf->collect_vsm         = 0;
+#endif
 
        return (0);
 } /* }}} int varnish_config_apply_default */
@@ -567,6 +1000,7 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
        {
                WARNING ("Varnish plugin: \"Instance\" blocks accept only "
                                "one argument.");
+               sfree (conf);
                return (EINVAL);
        }
 
@@ -580,12 +1014,27 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
                        cf_util_get_boolean (child, &conf->collect_connections);
                else if (strcasecmp ("CollectESI", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_esi);
+#ifdef HAVE_VARNISH_V3
+               else if (strcasecmp ("CollectDirectorDNS", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_dirdns);
+#endif
                else if (strcasecmp ("CollectBackend", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_backend);
                else if (strcasecmp ("CollectFetch", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_fetch);
                else if (strcasecmp ("CollectHCB", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_hcb);
+               else if (strcasecmp ("CollectObjects", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_objects);
+#if HAVE_VARNISH_V2
+               else if (strcasecmp ("CollectPurge", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_purge);
+#else
+               else if (strcasecmp ("CollectBan", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_ban);
+#endif
+               else if (strcasecmp ("CollectSession", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_session);
                else if (strcasecmp ("CollectSHM", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_shm);
                else if (strcasecmp ("CollectSMS", child->key) == 0)
@@ -596,10 +1045,22 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
                else if (strcasecmp ("CollectSM", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_sm);
 #endif
+               else if (strcasecmp ("CollectStruct", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_struct);
                else if (strcasecmp ("CollectTotals", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_totals);
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+               else if (strcasecmp ("CollectUptime", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_uptime);
+#endif
+               else if (strcasecmp ("CollectVCL", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_vcl);
                else if (strcasecmp ("CollectWorkers", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_workers);
+#if HAVE_VARNISH_V4
+               else if (strcasecmp ("CollectVSM", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_vsm);
+#endif
                else
                {
                        WARNING ("Varnish plugin: Ignoring unknown "
@@ -614,20 +1075,40 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
                        && !conf->collect_connections
                        && !conf->collect_esi
                        && !conf->collect_backend
+#ifdef HAVE_VARNISH_V3
+                       && !conf->collect_dirdns
+#endif
                        && !conf->collect_fetch
                        && !conf->collect_hcb
+                       && !conf->collect_objects
+#if HAVE_VARNISH_V2
+                       && !conf->collect_purge
+#else
+                       && !conf->collect_ban
+#endif
+                       && !conf->collect_session
                        && !conf->collect_shm
                        && !conf->collect_sms
 #if HAVE_VARNISH_V2
                        && !conf->collect_sma
                        && !conf->collect_sm
 #endif
+                       && !conf->collect_struct
                        && !conf->collect_totals
-                       && !conf->collect_workers)
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+                       && !conf->collect_uptime
+#endif
+                       && !conf->collect_vcl
+                       && !conf->collect_workers
+#if HAVE_VARNISH_V4
+                       && !conf->collect_vsm
+#endif
+       )
        {
                WARNING ("Varnish plugin: No metric has been configured for "
                                "instance \"%s\". Disabling this instance.",
                                (conf->instance == NULL) ? "localhost" : conf->instance);
+               sfree (conf);
                return (EINVAL);
        }