Code

Merge branch 'collectd-5.3'
authorFlorian Forster <octo@collectd.org>
Fri, 12 Jul 2013 16:23:20 +0000 (18:23 +0200)
committerFlorian Forster <octo@collectd.org>
Fri, 12 Jul 2013 16:23:20 +0000 (18:23 +0200)
Conflicts:
src/collectd.conf.pod

1  2 
src/collectd.conf.pod
src/common.c
src/configfile.c
src/types.db
src/varnish.c
src/write_riemann.c

diff --combined src/collectd.conf.pod
index 6ef2822ec68669d61cb4cebe05d4ae45e4deb975,0a2a5f7790de1ca30e5b93aa714d97af5073b3d0..ddf3ac60e12da8699fdcc238674cee63aff75621
@@@ -1,3 -1,5 +1,5 @@@
+ =encoding UTF-8
  =head1 NAME
  
  collectd.conf - Configuration for the system statistics collection daemon B<collectd>
@@@ -68,33 -70,17 +70,33 @@@ directory for the daemon
  
  =item B<LoadPlugin> I<Plugin>
  
 -Loads the plugin I<Plugin>. There must be at least one such line or B<collectd>
 -will be mostly useless.
 +Loads the plugin I<Plugin>. This is required to load plugins, unless the
 +B<AutoLoadPlugin> option is enabled (see below). Without any loaded plugins,
 +I<collectd> will be mostly useless.
  
 -Starting with collectd 4.9, this may also be a block in which further options
 -affecting the behavior of B<LoadPlugin> may be specified. The following
 -options are allowed inside a B<LoadPlugin> block:
 +Only the first B<LoadPlugin> statement or block for a given plugin name has any
 +effect. This is useful when you want to split up the configuration into smaller
 +files and want each file to be "self contained", i.e. it contains a B<Plugin>
 +block I<and> then appropriate B<LoadPlugin> statement. The downside is that if
 +you have multiple conflicting B<LoadPlugin> blocks, e.g. when they specify
 +different intervals, only one of them (the first one encountered) will take
 +effect and all others will be silently ignored.
  
 -  <LoadPlugin perl>
 -    Globals true
 -    Interval 10
 -  </LoadPlugin>
 +B<LoadPlugin> may either be a simple configuration I<statement> or a I<block>
 +with additional options, affecting the behavior of B<LoadPlugin>. A simple
 +statement looks like this:
 +
 + LoadPlugin "cpu"
 +
 +Options inside a B<LoadPlugin> block can override default settings and
 +influence the way plugins are loaded, e.g.:
 +
 + <LoadPlugin perl>
 +   Globals true
 +   Interval 60
 + </LoadPlugin>
 +
 +The following options are valid inside B<LoadPlugin> blocks:
  
  =over 4
  
@@@ -125,20 -111,7 +127,20 @@@ interval, that setting will take preced
  
  =back
  
 -=item B<Include> I<Path>
 +=item B<AutoLoadPlugin> B<false>|B<true>
 +
 +When set to B<false> (the default), each plugin needs to be loaded explicitly,
 +using the B<LoadPlugin> statement documented above. If a
 +B<E<lt>PluginE<nbsp>...E<gt>> block is encountered and no configuration
 +handling callback for this plugin has been registered, a warning is logged and
 +the block is ignored.
 +
 +When set to B<true>, explicit B<LoadPlugin> statements are not required. Each
 +B<E<lt>PluginE<nbsp>...E<gt>> block acts as if it was immediately preceded by a
 +B<LoadPlugin> statement. B<LoadPlugin> statements are still required for
 +plugins that don't provide any configuration, e.g. the I<Load plugin>.
 +
 +=item B<Include> I<Path> [I<pattern>]
  
  If I<Path> points to a file, includes that file. If I<Path> points to a
  directory, recursively includes all files within that directory and its
@@@ -148,15 -121,29 +150,29 @@@ use statements like the following
  
    Include "/etc/collectd.d/*.conf"
  
+ Starting with version 5.3, this may also be a block in which further options
+ affecting the behavior of B<Include> may be specified. The following option is
+ currently allowed:
+   <Include "/etc/collectd.d">
+     Filter "*.conf"
+   </Include>
+ =over 4
+ =item B<Filter> I<pattern>
  If the C<fnmatch> function is available on your system, a shell-like wildcard
  I<pattern> may be specified to filter which files to include. This may be used
  in combination with recursively including a directory to easily be able to
  arbitrarily mix configuration files and other documents (e.g. README files).
- The following statement is similar to the example above but includes all files
+ The given example is similar to the first example above but includes all files
  matching C<*.conf> in any subdirectory of C</etc/collectd.d>:
  
    Include "/etc/collectd.d" "*.conf"
  
+ =back
  If more than one files are included by a single B<Include> option, the files
  will be included in lexicographical order (as defined by the C<strcmp>
  function). Thus, you can e.E<nbsp>g. use numbered prefixes to specify the
@@@ -881,29 -868,6 +897,29 @@@ By default no detailed zone informatio
  
  =back
  
 +=head2 Plugin C<cgroups>
 +
 +This plugin collects the CPU user/system time for each I<cgroup> by reading the
 +F<cpuacct.stat> files in the first cpuacct-mountpoint (typically
 +F</sys/fs/cgroup/cpu.cpuacct> on machines using systemd).
 +
 +=over 4
 +
 +=item B<CGroup> I<Directory>
 +
 +Select I<cgroup> based on the name. Whether only matching I<cgroups> are
 +collected or if they are ignored is controlled by the B<IgnoreSelected> option;
 +see below.
 +
 +=item B<IgnoreSelected> B<true>|B<false>
 +
 +Invert the selection: If set to true, all cgroups I<except> the ones that
 +match any one of the criteria are collected. By default only selected
 +cgroups are collected if a selection is made. If no selection is configured
 +at all, B<all> cgroups are selected.
 +
 +=back
 +
  =head2 Plugin C<cpufreq>
  
  This plugin doesn't have any options. It reads
@@@ -1511,20 -1475,6 +1527,20 @@@ Enable this option if inodes are a scar
  many small files are stored on the disk. This is a usual scenario for mail
  transfer agents and web caches.
  
 +=item B<ValuesAbsolute> B<true>|B<false>
 +
 +Enables or disables reporting of free, used and used disk space in 1K-blocks. 
 +Defaults to true.
 +
 +=item B<ValuesPercentage> B<true>|B<false>
 +
 +Enables or disables reporting of free, used and used disk space in percentage.
 +Defaults to false.
 +
 +This is useful for deploying collectd on the cloud, where machines with
 +different disk size may exist. Then it is more practical to configure thresholds
 +based on relative disk size.
 +
  =back
  
  =head2 Plugin C<disk>
@@@ -2273,7 -2223,7 +2289,7 @@@ interpreted. For a description of matc
  
  =head2 Plugin C<memcached>
  
 -The C<memcached plugin> connects to a memcached server and queries statistics
 +The B<memcached plugin> connects to a memcached server and queries statistics
  about cache utilization, memory and bandwidth used.
  L<http://www.danga.com/memcached/>
  
@@@ -2305,166 -2255,6 +2321,166 @@@ setting is given, the B<Host> and B<Por
  
  =back
  
 +=head2 Plugin C<mic>
 +
 +The B<mic plugin> gathers CPU statistics, memory usage and temperatures from
 +Intel's Many Integrated Core (MIC) systems.
 +
 +B<Synopsis:>
 +
 + <Plugin mic>
 +   ShowCPU true
 +   ShowCPUCores true
 +   ShowMemory true
 +   
 +   ShowTemperatures true
 +   Temperature vddg
 +   Temperature vddq
 +   IgnoreSelectedTemperature true
 +
 +   ShowPower true
 +   Power total0
 +   Power total1
 +   IgnoreSelectedPower true   
 + </Plugin>
 +
 +The following options are valid inside the B<PluginE<nbsp>mic> block:
 +
 +=over 4
 +
 +=item B<ShowCPU> B<true>|B<false>
 +
 +If enabled (the default) a sum of the CPU usage accross all cores is reported.
 +
 +=item B<ShowCPUCores> B<true>|B<false>
 +
 +If enabled (the default) per-core CPU usage is reported.
 +
 +=item B<ShowMemory> B<true>|B<false>
 +
 +If enabled (the default) the physical memory usage of the MIC system is
 +reported.
 +
 +=item B<ShowTemperatures> B<true>|B<false>
 +
 +If enabled (the default) various temperatures of the MIC system are reported.
 +
 +=item B<Temperature> I<Name>
 +
 +This option controls which temperatures are being reported. Whether matching
 +temperatures are being ignored or I<only> matching temperatures are reported
 +depends on the B<IgnoreSelectedTemperature> setting below. By default I<all>
 +temperatures are reported.
 +
 +=item B<IgnoreSelectedTemperature> B<false>|B<true>
 +
 +Controls the behavior of the B<Temperature> setting above. If set to B<false>
 +(the default) only temperatures matching a B<Temperature> option are reported
 +or, if no B<Temperature> option is specified, all temperatures are reported. If
 +set to B<true>, matching temperatures are I<ignored> and all other temperatures
 +are reported.
 +
 +Known temperature names are:
 +
 +=over 4
 +
 +=item die
 +
 +Die of the CPU
 +
 +=item devmem
 +
 +Device Memory
 +
 +=item fin
 +
 +Fan In
 +
 +=item fout
 +
 +Fan Out 
 +
 +=item vccp
 +
 +Voltage ccp
 +
 +=item vddg
 +
 +Voltage ddg
 +
 +=item vddq
 +
 +Voltage ddq
 +
 +=back
 +
 +=item B<ShowPower> B<true>|B<false>
 +
 +If enabled (the default) various temperatures of the MIC system are reported.
 +
 +=item B<Power> I<Name>
 +
 +This option controls which power readings are being reported. Whether matching
 +power readings are being ignored or I<only> matching power readings are reported
 +depends on the B<IgnoreSelectedPower> setting below. By default I<all>
 +power readings are reported.
 +
 +=item B<IgnoreSelectedPower> B<false>|B<true>
 +
 +Controls the behavior of the B<Power> setting above. If set to B<false>
 +(the default) only power readings matching a B<Power> option are reported
 +or, if no B<Power> option is specified, all power readings are reported. If
 +set to B<true>, matching power readings are I<ignored> and all other power readings
 +are reported.
 +
 +Known power names are:
 +
 +=over 4
 +
 +=item total0
 +
 +Total power utilization averaged over Time Window 0 (uWatts). 
 +
 +=item total1
 +
 +Total power utilization averaged over Time Window 0 (uWatts). 
 +
 +=item inst
 +
 +Instantaneous power (uWatts).
 +
 +=item imax
 +
 +Max instantaneous power (uWatts). 
 +
 +=item pcie
 +
 +PCI-E connector power (uWatts). 
 +
 +=item c2x3
 +
 +2x3 connector power (uWatts). 
 +
 +=item c2x4
 +
 +2x4 connector power (uWatts). 
 +
 +=item vccp
 +
 +Core rail (uVolts). 
 +
 +=item vddg
 +
 +Uncore rail (uVolts). 
 +
 +=item vddq
 +
 +Memory subsystem rail (uVolts). 
 +
 +=back
 +
 +=back
 +
  =head2 Plugin C<modbus>
  
  The B<modbus plugin> connects to a Modbus "slave" via Modbus/TCP and reads
@@@ -2472,7 -2262,7 +2488,7 @@@ register values. It supports reading si
  values), large integer values (unsigned 32E<nbsp>bit values) and floating point
  values (two registers interpreted as IEEE floats in big endian notation).
  
 -Synopsis:
 +B<Synopsis:>
  
   <Data "voltage-input-1">
     RegisterBase 0
@@@ -5701,7 -5491,33 +5717,33 @@@ Take the UUID from the given file (defa
  
  =head2 Plugin C<varnish>
  
- The Varnish plugin collects information about Varnish, an HTTP accelerator.
+ The I<varnish plugin> collects information about Varnish, an HTTP accelerator.
+ Synopsis:
+  <Plugin "varnish">
+    <Instance "example">
+      CollectCache       true
+      CollectConnections true
+      CollectBackend     true
+      CollectSHM         true
+      CollectESI         false
+      CollectFetch       false
+      CollectHCB         false
+      CollectSMA         false
+      CollectSMS         false
+      CollectSM          false
+      CollectTotals      false
+      CollectWorkers     false
+    </Instance>
+  </Plugin>
+ The configuration consists of one or more E<lt>B<Instance>E<nbsp>I<Name>E<gt>
+ blocks. I<Name> is the parameter passed to "varnishd -n". If left empty, it
+ will collectd statistics from the default "varnishd" instance (this should work
+ fine in most cases).
+ Inside each E<lt>B<Instance>E<gt> blocks, the following options are recognized:
  
  =over 4
  
@@@ -5723,17 -5539,6 +5765,17 @@@ and closed connections. True by default
  Statistics about the shared memory log, a memory region to store
  log messages which is flushed to disk when full. True by default.
  
 +=item B<CollectBan> B<true>|B<false>
 +
 +Statistics about ban operations, such as number of bans added, retired, and
 +number of objects tested against ban operations. Only available with Varnish
 +3.x. False by default.
 +
 +=item B<CollectDirectorDNS> B<true>|B<false>
 +
 +DNS director lookup cache statistics. Only available with Varnish 3.x. False by
 +default.
 +
  =item B<CollectESI> B<true>|B<false>
  
  Edge Side Includes (ESI) parse statistics. False by default.
@@@ -5747,27 -5552,10 +5789,27 @@@ Statistics about fetches (HTTP request
  Inserts and look-ups in the crit bit tree based hash. Look-ups are
  divided into locked and unlocked look-ups. False by default.
  
 +=item B<CollectObjects> B<true>|B<false>
 +
 +Statistics on cached objects: number of objects expired, nuked (prematurely
 +expired), saved, moved, etc. False by default.
 +
 +=item B<CollectPurge> B<true>|B<false>
 +
 +Statistics about purge operations, such as number of purges added, retired, and
 +number of objects tested against purge operations. Only available with Varnish
 +2.x. False by default.
 +
 +=item B<CollectSession> B<true>|B<false>
 +
 +Client session statistics. Number of past and current sessions, session herd and
 +linger counters, etc. False by default.
 +
  =item B<CollectSMA> B<true>|B<false>
  
 -malloc or umem (umem_alloc(3MALLOC) based) storage statistics.
 -The umem storage component is Solaris specific. False by default.
 +malloc or umem (umem_alloc(3MALLOC) based) storage statistics. The umem storage
 +component is Solaris specific. Only available with Varnish 2.x. False by
 +default.
  
  =item B<CollectSMS> B<true>|B<false>
  
@@@ -5776,28 -5564,13 +5818,28 @@@ component is used internally only. Fals
  
  =item B<CollectSM> B<true>|B<false>
  
 -file (memory mapped file) storage statistics. False by default.
 +file (memory mapped file) storage statistics. Only available with Varnish 2.x.
 +False by default.
 +
 +=item B<CollectStruct> B<true>|B<false>
 +
 +Current varnish internal state statistics. Number of current sessions, objects
 +in cache store, open connections to backends (with Varnish 2.x), etc. False by
 +default.
  
  =item B<CollectTotals> B<true>|B<false>
  
  Collects overview counters, such as the number of sessions created,
  the number of requests and bytes transferred. False by default.
  
 +=item B<CollectUptime> B<true>|B<false>
 +
 +Varnish uptime. False by default.
 +
 +=item B<CollectVCL> B<true>|B<false>
 +
 +Number of total (available + discarded) VCL (config files). False by default.
 +
  =item B<CollectWorkers> B<true>|B<false>
  
  Collect statistics about worker threads. False by default.
@@@ -5842,9 -5615,9 +5884,9 @@@ iptables to feed data for the guest IP
  
  The C<write_graphite> plugin writes data to I<Graphite>, an open-source metrics
  storage and graphing project. The plugin connects to I<Carbon>, the data layer
 -of I<Graphite>, and sends data via the "line based" protocol (per default using
 -portE<nbsp>2003). The data will be sent in blocks of at most 1428 bytes to
 -minimize the number of network packets.
 +of I<Graphite>, via I<TCP> or I<UDP> and sends data via the "line based"
 +protocol (per default using portE<nbsp>2003). The data will be sent in blocks
 +of at most 1428 bytes to minimize the number of network packets.
  
  Synopsis:
  
     <Node "example">
       Host "localhost"
       Port "2003"
 +     Protocol "udp"
 +     LogSendErrors true
       Prefix "collectd"
     </Node>
   </Plugin>
@@@ -5871,17 -5642,6 +5913,17 @@@ Hostname or address to connect to. Defa
  
  Service name or port number to connect to. Defaults to C<2003>.
  
 +=item B<Protocol> I<String>
 +
 +Protocol to use when connecting to I<Graphite>. Defaults to C<tcp>.
 +
 +=item B<LogSendErrors> B<false>|B<true>
 +
 +If set to B<true> (the default), logs errors when sending data to I<Graphite>.
 +If set to B<false>, it will not log the errors. This is especially useful when
 +using Protocol UDP since many times we want to use the "fire-and-forget"
 +approach and logging errors fills syslog with unneeded messages.
 +
  =item B<Prefix> I<String>
  
  When set, I<String> is added in front of the host name. Dots and whitespace are
@@@ -6052,7 -5812,7 +6094,7 @@@ Synopsis
       Protocol UDP
       StoreRates true
       AlwaysAppendDS false
 -     Delay 10
 +     TTLFactor 2.0
     </Node>
     Tag "foobar"
   </Plugin>
@@@ -6099,15 -5859,6 +6141,15 @@@ If set the B<true>, append the name of 
  identifies a metric in I<Riemann>. If set to B<false> (the default), this is
  only done when there is more than one DS.
  
 +=item B<TTLFactor> I<Factor>
 +
 +I<Riemann> events have a I<Time to Live> (TTL) which specifies how long each
 +event is considered active. I<collectd> populates this field based on the
 +metrics interval setting. This setting controls the factor with which the
 +interval is multiplied to set the TTL. The default value is B<2.0>. Unless you
 +know exactly what you're doing, you should only increase this setting from its
 +default value.
 +
  =back
  
  =item B<Tag> I<String>
diff --combined src/common.c
index d963efa556a6f60ce6f71c3472f90e791dc48c4e,c41c4fe629dd14685e543964d9a7c05b7d8f399b..161b4d67fc063d693b1f319e016687cea4ae639d
@@@ -86,47 -86,6 +86,47 @@@ int ssnprintf (char *dest, size_t n, co
        return (ret);
  } /* int ssnprintf */
  
 +char *ssnprintf_alloc (char const *format, ...) /* {{{ */
 +{
 +      char static_buffer[1024] = "";
 +      char *alloc_buffer;
 +      size_t alloc_buffer_size;
 +      int status;
 +      va_list ap;
 +
 +      /* Try printing into the static buffer. In many cases it will be
 +       * sufficiently large and we can simply return a strdup() of this
 +       * buffer. */
 +      va_start (ap, format);
 +      status = vsnprintf (static_buffer, sizeof (static_buffer), format, ap);
 +      va_end (ap);
 +      if (status < 0)
 +              return (NULL);
 +
 +      /* "status" does not include the null byte. */
 +      alloc_buffer_size = (size_t) (status + 1);
 +      if (alloc_buffer_size <= sizeof (static_buffer))
 +              return (strdup (static_buffer));
 +
 +      /* Allocate a buffer large enough to hold the string. */
 +      alloc_buffer = malloc (alloc_buffer_size);
 +      if (alloc_buffer == NULL)
 +              return (NULL);
 +      memset (alloc_buffer, 0, alloc_buffer_size);
 +
 +      /* Print again into this new buffer. */
 +      va_start (ap, format);
 +      status = vsnprintf (alloc_buffer, alloc_buffer_size, format, ap);
 +      va_end (ap);
 +      if (status < 0)
 +      {
 +              sfree (alloc_buffer);
 +              return (NULL);
 +      }
 +
 +      return (alloc_buffer);
 +} /* }}} char *ssnprintf_alloc */
 +
  char *sstrdup (const char *s)
  {
        char *r;
@@@ -721,7 -680,7 +721,7 @@@ long long get_kstat_value (kstat_t *ksp
                retval = (long long) kn->value.ui64; /* XXX: Might overflow! */
        else
                WARNING ("get_kstat_value: Not a numeric value: %s", name);
-                
        return (retval);
  }
  #endif /* HAVE_LIBKSTAT */
@@@ -828,36 -787,43 +828,43 @@@ int format_name (char *ret, int ret_len
                const char *plugin, const char *plugin_instance,
                const char *type, const char *type_instance)
  {
-       int  status;
-       assert (plugin != NULL);
-       assert (type != NULL);
-       if ((plugin_instance == NULL) || (strlen (plugin_instance) == 0))
-       {
-               if ((type_instance == NULL) || (strlen (type_instance) == 0))
-                       status = ssnprintf (ret, ret_len, "%s/%s/%s",
-                                       hostname, plugin, type);
-               else
-                       status = ssnprintf (ret, ret_len, "%s/%s/%s-%s",
-                                       hostname, plugin, type,
-                                       type_instance);
-       }
-       else
-       {
-               if ((type_instance == NULL) || (strlen (type_instance) == 0))
-                       status = ssnprintf (ret, ret_len, "%s/%s-%s/%s",
-                                       hostname, plugin, plugin_instance,
-                                       type);
-               else
-                       status = ssnprintf (ret, ret_len, "%s/%s-%s/%s-%s",
-                                       hostname, plugin, plugin_instance,
-                                       type, type_instance);
-       }
-       if ((status < 1) || (status >= ret_len))
-               return (-1);
-       return (0);
+   char *buffer;
+   size_t buffer_size;
+   buffer = ret;
+   buffer_size = (size_t) ret_len;
+ #define APPEND(str) do {                                               \
+   size_t l = strlen (str);                                             \
+   if (l >= buffer_size)                                                \
+     return (ENOBUFS);                                                  \
+   memcpy (buffer, (str), l);                                           \
+   buffer += l; buffer_size -= l;                                       \
+ } while (0)
+   assert (plugin != NULL);
+   assert (type != NULL);
+   APPEND (hostname);
+   APPEND ("/");
+   APPEND (plugin);
+   if ((plugin_instance != NULL) && (plugin_instance[0] != 0))
+   {
+     APPEND ("-");
+     APPEND (plugin_instance);
+   }
+   APPEND ("/");
+   APPEND (type);
+   if ((type_instance != NULL) && (type_instance[0] != 0))
+   {
+     APPEND ("-");
+     APPEND (type_instance);
+   }
+   assert (buffer_size > 0);
+   buffer[0] = 0;
+ #undef APPEND
+   return (0);
  } /* int format_name */
  
  int format_values (char *ret, size_t ret_len, /* {{{ */
@@@ -1254,25 -1220,18 +1261,25 @@@ int walk_directory (const char *dir, di
        return (0);
  }
  
 -int read_file_contents (const char *filename, char *buf, int bufsize)
 +ssize_t read_file_contents (const char *filename, char *buf, size_t bufsize)
  {
        FILE *fh;
 -      int n;
 +      ssize_t ret;
  
 -      if ((fh = fopen (filename, "r")) == NULL)
 -              return -1;
 +      fh = fopen (filename, "r");
 +      if (fh == NULL)
 +              return (-1);
  
 -      n = fread(buf, 1, bufsize, fh);
 -      fclose(fh);
 +      ret = (ssize_t) fread (buf, 1, bufsize, fh);
 +      if ((ret == 0) && (ferror (fh) != 0))
 +      {
 +              ERROR ("read_file_contents: Reading file \"%s\" failed.",
 +                              filename);
 +              ret = -1;
 +      }
  
 -      return n;
 +      fclose(fh);
 +      return (ret);
  }
  
  counter_t counter_diff (counter_t old_value, counter_t new_value)
diff --combined src/configfile.c
index 876ee23ee71c8c33d2f230170bf94147a6012404,154c041cee2d8b6d01ff4021c723810993c91dac..d6c224fd74966e23f6758ee79be11b75a67e5960
@@@ -110,7 -110,6 +110,7 @@@ static cf_global_option_t cf_global_opt
        {"ReadThreads", NULL, "5"},
        {"WriteThreads", NULL, "5"},
        {"Timeout",     NULL, "2"},
 +      {"AutoLoadPlugin", NULL, "false"},
        {"PreCacheChain",  NULL, "PreCache"},
        {"PostCacheChain", NULL, "PostCache"}
  };
@@@ -278,6 -277,21 +278,6 @@@ static int dispatch_loadplugin (const o
        memset (&ctx, 0, sizeof (ctx));
        ctx.interval = cf_get_default_interval ();
  
 -      /*
 -       * XXX: Magic at work:
 -       *
 -       * Some of the language bindings, for example the Python and Perl
 -       * plugins, need to be able to export symbols to the scripts they run.
 -       * For this to happen, the "Globals" flag needs to be set.
 -       * Unfortunately, this technical detail is hard to explain to the
 -       * average user and she shouldn't have to worry about this, ideally.
 -       * So in order to save everyone's sanity use a different default for a
 -       * handful of special plugins. --octo
 -       */
 -      if ((strcasecmp ("Perl", name) == 0)
 -                      || (strcasecmp ("Python", name) == 0))
 -              flags |= PLUGIN_FLAGS_GLOBAL;
 -
        for (i = 0; i < ci->children_num; ++i) {
                if (strcasecmp("Globals", ci->children[i].key) == 0)
                        cf_util_get_flag (ci->children + i, &flags, PLUGIN_FLAGS_GLOBAL);
@@@ -380,19 -394,6 +380,19 @@@ static int dispatch_block_plugin (oconf
  
        name = ci->values[0].value.string;
  
 +      if (IS_TRUE (global_option_get ("AutoLoadPlugin")))
 +      {
 +              int status;
 +
 +              status = plugin_load (name, /* flags = */ 0);
 +              if (status != 0)
 +              {
 +                      ERROR ("Automatically loading plugin \"%s\" failed "
 +                                      "with status %i.", name, status);
 +                      return (status);
 +              }
 +      }
 +
        /* Check for a complex callback first */
        for (cb = complex_callback_head; cb != NULL; cb = cb->next)
        {
@@@ -586,7 -587,7 +586,7 @@@ static int cf_include_all (oconfig_item
                sfree (pattern);
  
                if (new == NULL)
-                       continue;
+                       return (-1);
  
                /* Now replace the i'th child in `root' with `new'. */
                cf_ci_replace_child (root, new, i);
@@@ -605,6 -606,7 +605,7 @@@ static oconfig_item_t *cf_read_file (co
                const char *pattern, int depth)
  {
        oconfig_item_t *root;
+       int status;
  
        assert (depth < CF_MAX_DEPTH);
  
                return (NULL);
        }
  
-       cf_include_all (root, depth);
+       status = cf_include_all (root, depth);
+       if (status != 0)
+       {
+               oconfig_free (root);
+               return (NULL);
+       }
  
        return (root);
  } /* oconfig_item_t *cf_read_file */
@@@ -829,12 -836,6 +835,6 @@@ static oconfig_item_t *cf_read_generic 
  
        wordfree (&we);
  
-       if (root->children == NULL)
-       {
-               oconfig_free (root);
-               return (NULL);
-       }
        return (root);
  } /* oconfig_item_t *cf_read_generic */
  /* #endif HAVE_WORDEXP_H */
@@@ -1046,6 -1047,12 +1046,12 @@@ int cf_read (char *filename
                ERROR ("Unable to read config file %s.", filename);
                return (-1);
        }
+       else if (conf->children_num == 0)
+       {
+               ERROR ("Configuration file %s is empty.", filename);
+               oconfig_free (conf);
+               return (-1);
+       }
  
        for (i = 0; i < conf->children_num; i++)
        {
diff --combined src/types.db
index 950f6b0d842dd087b9db3e7b012d280da6ec417b,fb443d9e99023e59bc367e2579c6adafe7ce7bb3..4922aa75f06338626e661878fb8d296eecec74e3
@@@ -6,7 -6,6 +6,7 @@@ apache_requests          value:DERIVE:0:
  apache_scoreboard     value:GAUGE:0:65535
  ath_nodes             value:GAUGE:0:65535
  ath_stat              value:DERIVE:0:U
 +backends              value:GAUGE:0:65535
  bitrate                       value:GAUGE:0:4294967295
  bytes                 value:GAUGE:0:U
  cache_eviction                value:DERIVE:0:U
@@@ -89,7 -88,7 +89,7 @@@ ipt_packets           value:DERIVE:0:
  irq                   value:DERIVE:0:U
  latency                       value:GAUGE:0:65535
  links                 value:GAUGE:0:U
- load                  shortterm:GAUGE:0:100, midterm:GAUGE:0:100, longterm:GAUGE:0:100
+ load                  shortterm:GAUGE:0:5000, midterm:GAUGE:0:5000, longterm:GAUGE:0:5000
  md_disks              value:GAUGE:0:U
  memcached_command     value:DERIVE:0:U
  memcached_connections value:GAUGE:0:U
@@@ -111,7 -110,6 +111,7 @@@ node_octets                rx:DERIVE:0:U, tx:DERIVE:0
  node_rssi             value:GAUGE:0:255
  node_stat             value:DERIVE:0:U
  node_tx_rate          value:GAUGE:0:127
 +objects                       value:GAUGE:0:U
  operations            value:DERIVE:0:U
  percent                       value:GAUGE:0:100.1
  pf_counters           value:DERIVE:0:U
@@@ -147,7 -145,6 +147,7 @@@ queue_length               value:GAUGE:0:
  records                       value:GAUGE:0:U
  requests              value:GAUGE:0:U
  response_time         value:GAUGE:0:U
 +response_code         value:GAUGE:0:U
  route_etx             value:GAUGE:0:U
  route_metric          value:GAUGE:0:U
  routes                        value:GAUGE:0:U
@@@ -168,7 -165,6 +168,7 @@@ timeleft           value:GAUGE:0:
  time_offset           value:GAUGE:-1000000:1000000
  total_bytes           value:DERIVE:0:U
  total_connections     value:DERIVE:0:U
 +total_objects         value:DERIVE:0:U
  total_operations      value:DERIVE:0:U
  total_requests                value:DERIVE:0:U
  total_sessions                value:DERIVE:0:U
@@@ -177,7 -173,6 +177,7 @@@ total_time_in_ms   value:DERIVE:0:
  total_values          value:DERIVE:0:U
  uptime                        value:GAUGE:0:4294967295
  users                 value:GAUGE:0:65535
 +vcl                   value:GAUGE:0:65535
  vcpu                  value:GAUGE:0:U
  virt_cpu_total                value:DERIVE:0:U
  virt_vcpu             value:DERIVE:0:U
@@@ -191,7 -186,6 +191,7 @@@ voltage                    value:GAUGE:U:
  vs_memory             value:GAUGE:0:9223372036854775807
  vs_processes          value:GAUGE:0:65535
  vs_threads            value:GAUGE:0:65535
 +
  #
  # Legacy types
  # (required for the v5 upgrade target)
diff --combined src/varnish.c
index f7bca416880648a0e2a7843c8877a466a3149c96,5de3389d862eb41828b5fb73a55f1d5fe2197104..e2ced0e4e20e128184f56330634aa854ae9c21b1
   *   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"
@@@ -47,28 -151,15 +47,28 @@@ 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;
 +      _Bool collect_uptime;
 +      _Bool collect_vcl;
        _Bool collect_workers;
  };
  typedef struct user_config_s user_config_t; /* }}} */
@@@ -147,30 -238,13 +147,30 @@@ static void varnish_monitor (const user
                varnish_submit_derive (conf->instance, "connections", "connections", "received", stats->client_req);
        }
  
 +#ifdef HAVE_VARNISH_V3
 +      if (conf->collect_dirdns)
 +      {
 +              /* DNS director lookups */
 +              varnish_submit_derive (conf->instance, "dirdns", "cache_operation", "lookups",    stats->dir_dns_lookups);
 +              /* DNS director failed lookups */
 +              varnish_submit_derive (conf->instance, "dirdns", "cache_result",    "failed",     stats->dir_dns_failed);
 +              /* DNS director cached lookups hit */
 +              varnish_submit_derive (conf->instance, "dirdns", "cache_result",    "hits",       stats->dir_dns_hit);
 +              /* DNS director full dnscache */
 +              varnish_submit_derive (conf->instance, "dirdns", "cache_result",    "cache_full", stats->dir_dns_cache_full);
 +      }
 +#endif
 +
        if (conf->collect_esi)
        {
                /* ESI parse errors (unlock)   */
 -              varnish_submit_derive (conf->instance, "esi", "total_operations", "error",  stats->esi_errors);
 +              varnish_submit_derive (conf->instance, "esi", "total_operations", "error",   stats->esi_errors);
  #if HAVE_VARNISH_V2
                /* Objects ESI parsed (unlock) */
 -              varnish_submit_derive (conf->instance, "esi", "total_operations", "parsed", stats->esi_parse);
 +              varnish_submit_derive (conf->instance, "esi", "total_operations", "parsed",  stats->esi_parse);
 +#else
 +              /* ESI parse warnings (unlock) */
 +              varnish_submit_derive (conf->instance, "esi", "total_operations", "warning", stats->esi_warnings);
  #endif
        }
  
  #if HAVE_VARNISH_V2
                /* Backend conn. unused        */
                varnish_submit_derive (conf->instance, "backend", "connections", "unused"       , stats->backend_unused);
 +#else
 +              /* Backend conn. retry         */
 +              varnish_submit_derive (conf->instance, "backend", "connections", "retries"      , stats->backend_retry);
  #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)
                varnish_submit_derive (conf->instance, "fetch", "http_requests", "zero"       , stats->fetch_zero);
                /* Fetch failed              */
                varnish_submit_derive (conf->instance, "fetch", "http_requests", "failed"     , stats->fetch_failed);
 +#if HAVE_VARNISH_V3
 +              /* Fetch no body (1xx)       */
 +              varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_1xx", stats->fetch_1xx);
 +              /* Fetch no body (204)       */
 +              varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_204", stats->fetch_204);
 +              /* Fetch no body (304)       */
 +              varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_304", stats->fetch_304);
 +#endif
        }
  
        if (conf->collect_hcb)
                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);
 +#if HAVE_VARNISH_V2
 +              /* N LRU saved objects           */
 +              varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_saved",          stats->n_lru_saved);
 +#endif
 +              /* N LRU moved objects           */
 +              varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_moved",          stats->n_lru_moved);
 +#if HAVE_VARNISH_V2
 +              /* N objects on deathrow         */
 +              varnish_submit_derive (conf->instance, "objects", "total_objects", "deathrow",           stats->n_deathrow);
 +#endif
 +              /* 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 HAVE_VARNISH_V2
 +      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);
 +      }
 +#else
 +      if (conf->collect_ban)
 +      {
 +              /* N total active bans      */
 +              varnish_submit_derive (conf->instance, "ban", "total_operations", "total",          stats->n_ban);
 +              /* N new bans added         */
 +              varnish_submit_derive (conf->instance, "ban", "total_operations", "added",          stats->n_ban_add);
 +              /* N old bans deleted       */
 +              varnish_submit_derive (conf->instance, "ban", "total_operations", "deleted",        stats->n_ban_retire);
 +              /* N objects tested         */
 +              varnish_submit_derive (conf->instance, "ban", "total_operations", "objects_tested", stats->n_ban_obj_test);
 +              /* N regexps tested against */
 +              varnish_submit_derive (conf->instance, "ban", "total_operations", "regexps_tested", stats->n_ban_re_test);
 +              /* N duplicate bans removed */
 +              varnish_submit_derive (conf->instance, "ban", "total_operations", "duplicate",      stats->n_ban_dups);
 +      }
 +#endif
 +
 +      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                 */
                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 unresurrected objects */
 +              varnish_submit_gauge (conf->instance, "struct", "objects", "vampireobject",      stats->n_vampireobject);
 +              /* N struct objectcore     */
 +              varnish_submit_gauge (conf->instance, "struct", "objects", "objectcore",         stats->n_objectcore);
 +              /* N struct objecthead     */
 +              varnish_submit_gauge (conf->instance, "struct", "objects", "objecthead",         stats->n_objecthead);
 +#ifdef HAVE_VARNISH_V2
 +              /* 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);
 +#endif
 +      }
 +
        if (conf->collect_totals)
        {
                /* Total Sessions */
                varnish_submit_derive (conf->instance, "totals", "total_bytes", "body-bytes",   stats->s_bodybytes);
        }
  
 +      if (conf->collect_uptime)
 +      {
 +              /* Client uptime */
 +              varnish_submit_gauge (conf->instance, "uptime", "uptime", "client_uptime", stats->uptime);
 +      }
 +
 +      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 */
                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);
 +#else
 +              /* queued work requests */
 +              varnish_submit_derive (conf->instance, "workers", "total_requests", "queued",       stats->n_wrk_queued);
 +              /* work request queue length */
 +              varnish_submit_derive (conf->instance, "workers", "total_requests", "queue_length", stats->n_wrk_lqueue);
  #endif
        }
  } /* }}} void varnish_monitor */
@@@ -548,30 -486,16 +548,30 @@@ static int varnish_config_apply_defaul
        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;
 +      conf->collect_uptime      = 0;
 +      conf->collect_vcl         = 0;
 +      conf->collect_workers     = 0;
  
        return (0);
  } /* }}} int varnish_config_apply_default */
@@@ -656,27 -580,12 +656,27 @@@ static int varnish_config_instance (con
                        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)
                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);
 +              else if (strcasecmp ("CollectUptime", child->key) == 0)
 +                      cf_util_get_boolean (child, &conf->collect_uptime);
 +              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);
                else
                {
                        WARNING ("Varnish plugin: Ignoring unknown "
-                                       "configuration option: \"%s\"",
+                                       "configuration option: \"%s\". Did "
+                                       "you forget to add an <Instance /> "
+                                       "block around the configuration?",
                                        child->key);
                }
        }
                        && !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_uptime
 +                      && !conf->collect_vcl
                        && !conf->collect_workers)
        {
                WARNING ("Varnish plugin: No metric has been configured for "
diff --combined src/write_riemann.c
index 3e2ddd75b0d5caec3bbc40b5121b1de20ab819b4,15bb23787c59f7b4f01d543c621a75fee2be42f4..3345d0444a94653a4e3be42a9d9051bfd264e790
@@@ -37,7 -37,6 +37,7 @@@
  
  #define RIEMANN_HOST          "localhost"
  #define RIEMANN_PORT          "5555"
 +#define RIEMANN_TTL_FACTOR      2.0
  
  struct riemann_host {
        char                    *name;
@@@ -50,7 -49,6 +50,7 @@@
        char                    *service;
        _Bool                    use_tcp;
        int                      s;
 +      double                   ttl_factor;
  
        int                      reference_count;
  };
@@@ -60,6 -58,8 +60,8 @@@ static size_t   riemann_tags_num
  
  static void riemann_event_protobuf_free (Event *event) /* {{{ */
  {
+       size_t i;
        if (event == NULL)
                return;
  
        event->tags = NULL;
        event->n_tags = 0;
  
+       for (i = 0; i < event->n_attributes; i++)
+       {
+               sfree (event->attributes[i]->key);
+               sfree (event->attributes[i]->value);
+               sfree (event->attributes[i]);
+       }
+       sfree (event->attributes);
+       event->n_attributes = 0;
        sfree (event);
  } /* }}} void riemann_event_protobuf_free */
  
@@@ -367,7 -376,6 +378,7 @@@ static Event *riemann_value_to_protobu
        Event *event;
        char name_buffer[5 * DATA_MAX_NAME_LEN];
        char service_buffer[6 * DATA_MAX_NAME_LEN];
 +      double ttl;
        int i;
  
        event = malloc (sizeof (*event));
        event->host = strdup (vl->host);
        event->time = CDTIME_T_TO_TIME_T (vl->time);
        event->has_time = 1;
 -      event->ttl = CDTIME_T_TO_TIME_T (2 * vl->interval);
 +
 +      ttl = CDTIME_T_TO_DOUBLE (vl->interval) * host->ttl_factor;
 +      event->ttl = (float) ttl;
        event->has_ttl = 1;
  
        riemann_event_add_attribute (event, "plugin", vl->plugin);
@@@ -602,7 -608,6 +613,7 @@@ riemann_config_node(oconfig_item_t *ci
        host->store_rates = 1;
        host->always_append_ds = 0;
        host->use_tcp = 0;
 +      host->ttl_factor = RIEMANN_TTL_FACTOR;
  
        status = cf_util_get_string (ci, &host->name);
        if (status != 0) {
                                        &host->always_append_ds);
                        if (status != 0)
                                break;
 +              } else if (strcasecmp ("TTLFactor", child->key) == 0) {
 +                      double tmp = NAN;
 +                      status = cf_util_get_double (child, &tmp);
 +                      if (status != 0)
 +                              break;
 +                      if (tmp >= 2.0) {
 +                              host->ttl_factor = tmp;
 +                      } else if (tmp >= 1.0) {
 +                              NOTICE ("write_riemann plugin: The configured "
 +                                              "TTLFactor is very small "
 +                                              "(%.1f). A value of 2.0 or "
 +                                              "greater is recommended.",
 +                                              tmp);
 +                              host->ttl_factor = tmp;
 +                      } else if (tmp > 0.0) {
 +                              WARNING ("write_riemann plugin: The configured "
 +                                              "TTLFactor is too small to be "
 +                                              "useful (%.1f). I'll use it "
 +                                              "since the user knows best, "
 +                                              "but under protest.",
 +                                              tmp);
 +                              host->ttl_factor = tmp;
 +                      } else { /* zero, negative and NAN */
 +                              ERROR ("write_riemann plugin: The configured "
 +                                              "TTLFactor is invalid (%.1f).",
 +                                              tmp);
 +                      }
                } else {
                        WARNING("write_riemann plugin: ignoring unknown config "
                                "option: \"%s\"", child->key);