Code

Merge branch 'collectd-5.2' into collectd-5.3
authorFlorian Forster <octo@collectd.org>
Thu, 30 May 2013 07:00:09 +0000 (09:00 +0200)
committerFlorian Forster <octo@collectd.org>
Thu, 30 May 2013 07:00:09 +0000 (09:00 +0200)
1  2 
src/collectd.conf.pod
src/configfile.c
src/types.db

diff --combined src/collectd.conf.pod
index af068604f45ff7bacd3d0b411ab5e1f2755370b3,0521779cc17b1640f151e5b68a516741378bbd71..0a2a5f7790de1ca30e5b93aa714d97af5073b3d0
@@@ -1,3 -1,5 +1,5 @@@
+ =encoding UTF-8
  =head1 NAME
  
  collectd.conf - Configuration for the system statistics collection daemon B<collectd>
@@@ -119,29 -121,6 +121,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 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
@@@ -195,14 -174,8 +197,14 @@@ see L<collectd-threshold(5)> for detail
  
  Number of threads to start for reading plugins. The default value is B<5>, but
  you may want to increase this if you have more than five plugins that take a
 -long time to read. Mostly those are plugin that do network-IO. Setting this to
 -a value higher than the number of plugins you've loaded is totally useless.
 +long time to read. Mostly those are plugins that do network-IO. Setting this to
 +a value higher than the number of registered read callbacks is not recommended.
 +
 +=item B<WriteThreads> I<Num>
 +
 +Number of threads to start for dispatching value lists to write plugins. The
 +default value is B<5>, but you may want to increase this if you have more than
 +five plugins that may take relatively long to write to.
  
  =item B<Hostname> I<Name>
  
@@@ -326,72 -299,11 +328,72 @@@ aggregations. The following options ar
  Selects the value lists to be added to this aggregation. B<Type> must be a
  valid data set name, see L<types.db(5)> for details.
  
 +If the string starts with and ends with a slash (C</>), the string is
 +interpreted as a I<regular expression>. The regex flavor used are POSIX
 +extended regular expressions as described in L<regex(7)>. Example usage:
 +
 + Host "/^db[0-9]\\.example\\.com$/"
 +
  =item B<GroupBy> B<Host>|B<Plugin>|B<PluginInstance>|B<TypeInstance>
  
  Group valued by the specified field. The B<GroupBy> option may be repeated to
  group by multiple fields.
  
 +=item B<SetHost> I<Host>
 +
 +=item B<SetPlugin> I<Plugin>
 +
 +=item B<SetPluginInstance> I<PluginInstance>
 +
 +=item B<SetTypeInstance> I<TypeInstance>
 +
 +Sets the appropriate part of the identifier to the provided string.
 +
 +The I<PluginInstance> should include the placeholder C<%{aggregation}> which
 +will be replaced with the aggregation function, e.g. "average". Not including
 +the placeholder will result in duplication warnings and/or messed up values if
 +more than one aggregation function are enabled.
 +
 +The following example calculates the average usage of all "even" CPUs:
 +
 + <Plugin "aggregation">
 +   <Aggregation>
 +     Plugin "cpu"
 +     PluginInstance "/[0,2,4,6,8]$/"
 +     Type "cpu"
 +     
 +     SetPlugin "cpu"
 +     SetPluginInstance "even-%{aggregation}"
 +     
 +     GroupBy "Host"
 +     GroupBy "TypeInstance"
 +     
 +     CalculateAverage true
 +   </Aggregation>
 + </Plugin>
 +
 +This will create the files:
 +
 +=over 4
 +
 +=item
 +
 +foo.example.com/cpu-even-average/cpu-idle
 +
 +=item
 +
 +foo.example.com/cpu-even-average/cpu-system
 +
 +=item
 +
 +foo.example.com/cpu-even-average/cpu-user
 +
 +=item
 +
 +...
 +
 +=back
 +
  =item B<CalculateNum> B<true>|B<false>
  
  =item B<CalculateSum> B<true>|B<false>
@@@ -661,12 -573,6 +663,12 @@@ B<apcupsd> can handle it
  
  TCP-Port to connect to. Defaults to B<3551>.
  
 +=item B<ReportSeconds> B<true|false>
 +
 +If set to B<true>, the time reported in the C<timeleft> metric will be
 +converted to seconds. This is the recommended setting. If set to B<false>, the
 +default for backwards compatibility, the time will be reported in minutes.
 +
  =back
  
  =head2 Plugin C<ascent>
@@@ -958,19 -864,6 +960,19 @@@ File that holds one or more SSL certifi
  possibly need this option. What CA certificates come bundled with C<libcurl>
  and are checked by default depends on the distribution you use.
  
 +=item B<Header> I<Header>
 +
 +A HTTP header to add to the request. Multiple headers are added if this option
 +is specified more than once.
 +
 +=item B<Post> I<Body>
 +
 +Specifies that the HTTP operation should be a POST instead of a GET. The
 +complete data to be posted is given as the argument.  This option will usually
 +need to be accompanied by a B<Header> option to set an appropriate
 +C<Content-Type> for the post body (e.g. to
 +C<application/x-www-form-urlencoded>).
 +
  =item B<MeasureResponseTime> B<true>|B<false>
  
  Measure response time for the request. If this setting is enabled, B<Match>
@@@ -1029,15 -922,31 +1031,15 @@@ The following options are valid within 
  Sets the plugin instance to I<Instance>.
  
  =item B<User> I<Name>
 -
 -Username to use if authorization is required to read the page.
 -
  =item B<Password> I<Password>
 -
 -Password to use if authorization is required to read the page.
 -
  =item B<VerifyPeer> B<true>|B<false>
 -
 -Enable or disable peer SSL certificate verification. See
 -L<http://curl.haxx.se/docs/sslcerts.html> for details. Enabled by default.
 -
  =item B<VerifyHost> B<true>|B<false>
 -
 -Enable or disable peer host name verification. If enabled, the plugin checks if
 -the C<Common Name> or a C<Subject Alternate Name> field of the SSL certificate
 -matches the host name provided by the B<URL> option. If this identity check
 -fails, the connection is aborted. Obviously, only works when connecting to a
 -SSL enabled server. Enabled by default.
 -
  =item B<CACert> I<file>
 +=item B<Header> I<Header>
 +=item B<Post> I<Body>
  
 -File that holds one or more SSL certificates. If you want to use HTTPS you will
 -possibly need this option. What CA certificates come bundled with C<libcurl>
 -and are checked by default depends on the distribution you use.
 +These options behave exactly equivalent to the appropriate options of the
 +I<cURL> plugin. Please see there for a detailed description.
  
  =back
  
@@@ -1106,34 -1015,14 +1108,34 @@@ host name setting
  Use I<Instance> as the plugin instance when submitting values. Defaults to an
  empty string (no plugin instance).
  
 +=item B<Namespace> I<Prefix> I<URL>
 +
 +If an XPath expression references namespaces, they must be specified
 +with this option. I<Prefix> is the "namespace prefix" used in the XML document.
 +I<URL> is the "namespace name", an URI reference uniquely identifying the
 +namespace. The option can be repeated to register multiple namespaces.
 +
 +Examples:
 +
 +  Namespace "s" "http://schemas.xmlsoap.org/soap/envelope/"
 +  Namespace "m" "http://www.w3.org/1998/Math/MathML"
 +
  =item B<User> I<User>
 +
  =item B<Password> I<Password>
 +
  =item B<VerifyPeer> B<true>|B<false>
 +
  =item B<VerifyHost> B<true>|B<false>
 +
  =item B<CACert> I<CA Cert File>
  
 +=item B<Header> I<Header>
 +
 +=item B<Post> I<Body>
 +
  These options behave exactly equivalent to the appropriate options of the
 -I<cURL> and I<cURL-JSON> plugins. Please see there for a detailed description.
 +I<cURL plugin>. Please see there for a detailed description.
  
  =item E<lt>B<XPath> I<XPath-expression>E<gt>
  
@@@ -1397,23 -1286,11 +1399,23 @@@ documentation for each driver, somewher
  L<http://libdbi-drivers.sourceforge.net/>. However, the options "host",
  "username", "password", and "dbname" seem to be deE<nbsp>facto standards.
  
 +DBDs can register two types of options: String options and numeric options. The
 +plugin will use the C<dbi_conn_set_option> function when the configuration
 +provides a string and the C<dbi_conn_require_option_numeric> function when the
 +configuration provides a number. So these two lines will actually result in
 +different calls being used:
 +
 +  DriverOption "Port" 1234      # numeric
 +  DriverOption "Port" "1234"    # string
 +
  Unfortunately, drivers are not too keen to report errors when an unknown option
  is passed to them, so invalid settings here may go unnoticed. This is not the
  plugin's fault, it will report errors if it gets them from the libraryE<nbsp>/
  the driver. If a driver complains about an option, the plugin will dump a
 -complete list of all options understood by that driver to the log.
 +complete list of all options understood by that driver to the log. There is no
 +way to programatically find out if an option expects a string or a numeric
 +argument, so you will have to refer to the appropriate DBD's documentation to
 +find this out. Sorry.
  
  =item B<SelectDB> I<Database>
  
@@@ -1428,11 -1305,6 +1430,11 @@@ query needs to be defined I<before> thi
  blocks you want to refer to must be placed above the database block you want to
  refer to them from.
  
 +=item B<Host> I<Hostname>
 +
 +Sets the B<host> field of I<value lists> to I<Hostname> when dispatching
 +values. Defaults to the global hostname setting.
 +
  =back
  
  =head2 Plugin C<df>
@@@ -2547,14 -2419,6 +2549,14 @@@ Required capabilities are documented be
        IgnoreSelectedSnapshot false
      </VolumeUsage>
      
 +    <Quota>
 +      Interval 60
 +    </Quota>
 +    
 +    <Snapvault>
 +      Interval 30
 +    </Snapvault>
 +    
      <System>
        Interval 30
        GetCPULoad     true
        GetDiskOps     true
        GetDiskIO      true
      </System>
 +
 +    <VFiler vfilerA>
 +      Interval 60
 +
 +      SnapVault true
 +      # ...
 +    </VFiler>
     </Host>
   </Plugin>
  
@@@ -2579,27 -2436,7 +2581,27 @@@ The netapp plugin accepts the followin
  =item B<Host> I<Name>
  
  A host block defines one NetApp filer. It will appear in collectd with the name
 -you specify here which does not have to be its real name nor its hostname.
 +you specify here which does not have to be its real name nor its hostname (see
 +the B<Address> option below).
 +
 +=item B<VFiler> I<Name>
 +
 +A B<VFiler> block may only be used inside a host block. It accepts all the
 +same options as the B<Host> block (except for cascaded B<VFiler> blocks) and
 +will execute all NetApp API commands in the context of the specified
 +VFiler(R). It will appear in collectd with the name you specify here which
 +does not have to be its real name. The VFiler name may be specified using the
 +B<VFilerName> option. If this is not specified, it will default to the name
 +you specify here.
 +
 +The VFiler block inherits all connection related settings from the surrounding
 +B<Host> block (which appear before the B<VFiler> block) but they may be
 +overwritten inside the B<VFiler> block.
 +
 +This feature is useful, for example, when using a VFiler as SnapVault target
 +(supported since OnTap 8.1). In that case, the SnapVault statistics are not
 +available in the host filer (vfiler0) but only in the respective VFiler
 +context.
  
  =item B<Protocol> B<httpd>|B<http>
  
@@@ -2643,19 -2480,6 +2645,19 @@@ Mandator
  
  Type: string
  
 +=item B<VFilerName> I<Name>
 +
 +The name of the VFiler in which context to execute API commands. If not
 +specified, the name provided to the B<VFiler> block will be used instead.
 +
 +Optional
 +
 +Type: string
 +
 +Default: name of the B<VFiler> block
 +
 +B<Note:> This option may only be used inside B<VFiler> blocks.
 +
  =item B<Interval> I<Interval>
  
  B<TODO>
@@@ -2986,38 -2810,6 +2988,38 @@@ capacities will be selected anyway
  
  =back
  
 +=head3 The Quota block
 +
 +This will collect (tree) quota statistics (used disk space and number of used
 +files). This mechanism is useful to get usage information for single qtrees.
 +In case the quotas are not used for any other purpose, an entry similar to the
 +following in C</etc/quotas> would be sufficient:
 +
 +  /vol/volA/some_qtree tree - - - - -
 +
 +After adding the entry, issue C<quota on -w volA> on the NetApp filer.
 +
 +=over 4
 +
 +=item B<Interval> I<Seconds>
 +
 +Collect SnapVault(R) statistics every I<Seconds> seconds.
 +
 +=back
 +
 +=head3 The SnapVault block
 +
 +This will collect statistics about the time and traffic of SnapVault(R)
 +transfers.
 +
 +=over 4
 +
 +=item B<Interval> I<Seconds>
 +
 +Collect SnapVault(R) statistics every I<Seconds> seconds.
 +
 +=back
 +
  =head2 Plugin C<netlink>
  
  The C<netlink> plugin uses a netlink socket to query the Linux kernel about
@@@ -4675,16 -4467,6 +4677,16 @@@ Enables or disables the creation of RR
  locally, or B<DataDir> is set to a relative path, this will not work as
  expected. Default is B<true>.
  
 +=item B<CreateFilesAsync> B<false>|B<true>
 +
 +When enabled, new RRD files are enabled asynchronously, using a separate thread
 +that runs in the background. This prevents writes to block, which is a problem
 +especially when many hundreds of files need to be created at once. However,
 +since the purpose of creating the files asynchronously is I<not> to block until
 +the file is available, values before the file is available will be discarded.
 +When disabled (the default) files are created synchronously, blocking for a
 +short while, while the file is being written.
 +
  =item B<StepSize> I<Seconds>
  
  B<Force> the stepsize of newly created RRD-files. Ideally (and per default)
@@@ -4742,18 -4524,8 +4744,18 @@@ can safely ignore these settings
  
  =item B<DataDir> I<Directory>
  
 -Set the directory to store RRD-files under. Per default RRD-files are generated
 -beneath the daemon's working directory, i.E<nbsp>e. the B<BaseDir>.
 +Set the directory to store RRD files under. By default RRD files are generated
 +beneath the daemon's working directory, i.e. the B<BaseDir>.
 +
 +=item B<CreateFilesAsync> B<false>|B<true>
 +
 +When enabled, new RRD files are enabled asynchronously, using a separate thread
 +that runs in the background. This prevents writes to block, which is a problem
 +especially when many hundreds of files need to be created at once. However,
 +since the purpose of creating the files asynchronously is I<not> to block until
 +the file is available, values before the file is available will be discarded.
 +When disabled (the default) files are created synchronously, blocking for a
 +short while, while the file is being written.
  
  =item B<StepSize> I<Seconds>
  
@@@ -4774,7 -4546,7 +4776,7 @@@ a very good reason to do so
  
  The C<rrdtool plugin> calculates the number of PDPs per CDP based on the
  B<StepSize>, this setting and a timespan. This plugin creates RRD-files with
 -three times five RRAs, i. e. five RRAs with the CFs B<MIN>, B<AVERAGE>, and
 +three times five RRAs, i.e. five RRAs with the CFs B<MIN>, B<AVERAGE>, and
  B<MAX>. The five RRAs are optimized for graphs covering one hour, one day, one
  week, one month, and one year.
  
@@@ -5170,97 -4942,6 +5172,97 @@@ This optional setting sets the type ins
  
  =back
  
 +=head2 Plugin C<tail_csv>
 +
 +The I<tail_csv plugin> reads files in the CSV format, e.g. the statistics file
 +written by I<Snort>.
 +
 +B<Synopsis:>
 +
 + <Plugin "tail_csv">
 +   <Metric "snort-dropped">
 +       Type "percent"
 +       Instance "dropped"
 +       Index 1
 +   </Metric>
 +   <File "/var/log/snort/snort.stats">
 +       Instance "snort-eth0"
 +       Interval 600
 +       Collect "snort-dropped"
 +   </File>
 + </Plugin>
 +
 +The configuration consists of one or more B<Metric> blocks that define an index
 +into the line of the CSV file and how this value is mapped to I<collectd's>
 +internal representation. These are followed by one or more B<Instance> blocks
 +which configure which file to read, in which interval and which metrics to
 +extract.
 +
 +=over 4
 +
 +=item E<lt>B<Metric> I<Name>E<gt>
 +
 +The B<Metric> block configures a new metric to be extracted from the statistics
 +file and how it is mapped on I<collectd's> data model. The string I<Name> is
 +only used inside the B<Instance> blocks to refer to this block, so you can use
 +one B<Metric> block for multiple CSV files.
 +
 +=over 4
 +
 +=item B<Type> I<Type>
 +
 +Configures which I<Type> to use when dispatching this metric. Types are defined
 +in the L<types.db(5)> file, see the appropriate manual page for more
 +information on specifying types. Only types with a single I<data source> are
 +supported by the I<tail_csv plugin>. The information whether the value is an
 +absolute value (i.e. a C<GAUGE>) or a rate (i.e. a C<DERIVE>) is taken from the
 +I<Type's> definition.
 +
 +=item B<Instance> I<TypeInstance>
 +
 +If set, I<TypeInstance> is used to populate the type instance field of the
 +created value lists. Otherwise, no type instance is used.
 +
 +=item B<ValueFrom> I<Index>
 +
 +Configure to read the value from the field with the zero-based index I<Index>.
 +If the value is parsed as signed integer, unsigned integer or double depends on
 +the B<Type> setting, see above.
 +
 +=back
 +
 +=item E<lt>B<File> I<Path>E<gt>
 +
 +Each B<File> block represents one CSV file to read. There must be at least one
 +I<File> block but there can be multiple if you have multiple CSV files.
 +
 +=over 4
 +
 +=item B<Instance> I<PluginInstance>
 +
 +Sets the I<plugin instance> used when dispatching the values.
 +
 +=item B<Collect> I<Metric>
 +
 +Specifies which I<Metric> to collect. This option must be specified at least
 +once, and you can use this option multiple times to specify more than one
 +metric to be extracted from this statistic file.
 +
 +=item B<Interval> I<Seconds>
 +
 +Configures the interval in which to read values from this instance / file.
 +Defaults to the plugin's default interval.
 +
 +=item B<TimeFrom> I<Index>
 +
 +Rather than using the local time when dispatching a value, read the timestamp
 +from the field with the zero-based index I<Index>. The value is interpreted as
 +seconds since epoch. The value is parsed as a double and may be factional.
 +
 +=back
 +
 +=back
 +
  =head2 Plugin C<teamspeak2>
  
  The C<teamspeak2 plugin> connects to the query port of a teamspeak2 server and
@@@ -5489,7 -5170,33 +5491,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
  
@@@ -5594,16 -5301,13 +5622,16 @@@ minimize the number of network packets
  Synopsis:
  
   <Plugin write_graphite>
 -   <Carbon>
 +   <Node "example">
       Host "localhost"
       Port "2003"
       Prefix "collectd"
 -   </Carbon>
 +   </Node>
   </Plugin>
  
 +The configuration consists of one or more E<lt>B<Node>E<nbsp>I<Name>E<gt>
 +blocks. Inside the B<Node> blocks, the following options are recognized:
 +
  =over 4
  
  =item B<Host> I<Address>
@@@ -5693,16 -5397,6 +5721,16 @@@ If set to B<true> (the default), conver
  B<false> counter values are stored as is, i.e. as an increasing integer
  number.
  
 +=item B<Database> I<Database>
 +
 +=item B<User> I<User>
 +
 +=item B<Password> I<Password>
 +
 +Sets the information used when authenticating to a I<MongoDB> database. The
 +fields are optional (in which case no authentication is attempted), but if you
 +want to use authentication all three fields must be set.
 +
  =back
  
  =head2 Plugin C<write_http>
@@@ -5769,77 -5463,6 +5797,77 @@@ number
  
  =back
  
 +=head2 Plugin C<write_riemann>
 +
 +The I<write_riemann plugin> will send values to I<Riemann>, a powerfull stream
 +aggregation and monitoring system. The plugin sends I<Protobuf> encoded data to
 +I<Riemann> using UDP packets.
 +
 +Synopsis:
 +
 + <Plugin "write_riemann">
 +   <Node "example">
 +     Host "localhost"
 +     Port "5555"
 +     Protocol UDP
 +     StoreRates true
 +     AlwaysAppendDS false
 +     Delay 10
 +   </Node>
 +   Tag "foobar"
 + </Plugin>
 +
 +The following options are understood by the I<write_riemann plugin>:
 +
 +=over 4
 +
 +=item E<lt>B<Node> I<Name>E<gt>
 +
 +The plugin's configuration consists of one or more B<Node> blocks. Each block
 +is given a unique I<Name> and specifies one connection to an instance of
 +I<Riemann>. Indise the B<Node> block, the following per-connection options are
 +understood:
 +
 +=over 4
 +
 +=item B<Host> I<Address>
 +
 +Hostname or address to connect to. Defaults to C<localhost>.
 +
 +=item B<Port> I<Service>
 +
 +Service name or port number to connect to. Defaults to C<5555>.
 +
 +=item B<Protocol> B<UDP>|B<TCP>
 +
 +Specify the protocol to use when communicating with I<Riemann>. Defaults to
 +B<UDP>.
 +
 +=item B<StoreRates> B<true>|B<false>
 +
 +If set to B<true> (the default), convert counter values to rates. If set to
 +B<false> counter values are stored as is, i.e. as an increasing integer number.
 +
 +This will be reflected in the C<ds_type> tag: If B<StoreRates> is enabled,
 +converted values will have "rate" appended to the data source type, e.g.
 +C<ds_type:derive:rate>.
 +
 +=item B<AlwaysAppendDS> B<false>|B<true>
 +
 +If set the B<true>, append the name of the I<Data Source> (DS) to the
 +"service", i.e. the field that, together with the "host" field, uniquely
 +identifies a metric in I<Riemann>. If set to B<false> (the default), this is
 +only done when there is more than one DS.
 +
 +=back
 +
 +=item B<Tag> I<String>
 +
 +Add the given string as an additional tag to the metric being sent to
 +I<Riemann>.
 +
 +=back
 +
  =head1 THRESHOLD CONFIGURATION
  
  Starting with version C<4.3.0> collectd has support for B<monitoring>. By that
diff --combined src/configfile.c
index ac5e8edcb94f2bfda66c5eefab67dfab3c66e6db,be777c52a02cbb0074c405fa7909ab0a3968c3b9..154c041cee2d8b6d01ff4021c723810993c91dac
  # include <wordexp.h>
  #endif /* HAVE_WORDEXP_H */
  
 +#if HAVE_FNMATCH_H
 +# include <fnmatch.h>
 +#endif /* HAVE_FNMATCH_H */
 +
 +#if HAVE_LIBGEN_H
 +# include <libgen.h>
 +#endif /* HAVE_LIBGEN_H */
 +
  #define ESCAPE_NULL(str) ((str) == NULL ? "(null)" : (str))
  
  /*
@@@ -98,7 -90,7 +98,7 @@@ static cf_value_map_t cf_value_map[] 
        {"PluginDir",  dispatch_value_plugindir},
        {"LoadPlugin", dispatch_loadplugin}
  };
 -static int cf_value_map_num = STATIC_ARRAY_LEN (cf_value_map);
 +static int cf_value_map_num = STATIC_ARRAY_SIZE (cf_value_map);
  
  static cf_global_option_t cf_global_options[] =
  {
        {"FQDNLookup",  NULL, "true"},
        {"Interval",    NULL, NULL},
        {"ReadThreads", NULL, "5"},
 +      {"WriteThreads", NULL, "5"},
        {"Timeout",     NULL, "2"},
        {"PreCacheChain",  NULL, "PreCache"},
        {"PostCacheChain", NULL, "PostCache"}
  };
 -static int cf_global_options_num = STATIC_ARRAY_LEN (cf_global_options);
 +static int cf_global_options_num = STATIC_ARRAY_SIZE (cf_global_options);
  
  static int cf_default_typesdb = 1;
  
@@@ -544,8 -535,7 +544,8 @@@ static int cf_ci_append_children (oconf
  } /* int cf_ci_append_children */
  
  #define CF_MAX_DEPTH 8
 -static oconfig_item_t *cf_read_generic (const char *path, int depth);
 +static oconfig_item_t *cf_read_generic (const char *path,
 +              const char *pattern, int depth);
  
  static int cf_include_all (oconfig_item_t *root, int depth)
  {
                oconfig_item_t *new;
                oconfig_item_t *old;
  
 -              /* Ignore all blocks, including `Include' blocks. */
 -              if (root->children[i].children_num != 0)
 -                      continue;
 +              char *pattern = NULL;
 +
 +              int j;
  
                if (strcasecmp (root->children[i].key, "Include") != 0)
                        continue;
                        continue;
                }
  
 -              new = cf_read_generic (old->values[0].value.string, depth + 1);
 +              for (j = 0; j < old->children_num; ++j)
 +              {
 +                      oconfig_item_t *child = old->children + j;
 +
 +                      if (strcasecmp (child->key, "Filter") == 0)
 +                              cf_util_get_string (child, &pattern);
 +                      else
 +                              ERROR ("configfile: Option `%s' not allowed in <Include> block.",
 +                                              child->key);
 +              }
 +
 +              new = cf_read_generic (old->values[0].value.string, pattern, depth + 1);
 +              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);
        return (0);
  } /* int cf_include_all */
  
 -static oconfig_item_t *cf_read_file (const char *file, int depth)
 +static oconfig_item_t *cf_read_file (const char *file,
 +              const char *pattern, int depth)
  {
        oconfig_item_t *root;
+       int status;
  
        assert (depth < CF_MAX_DEPTH);
  
 +      if (pattern != NULL) {
 +#if HAVE_FNMATCH_H && HAVE_LIBGEN_H
 +              char *tmp = sstrdup (file);
 +              char *filename = basename (tmp);
 +
 +              if ((filename != NULL) && (fnmatch (pattern, filename, 0) != 0)) {
 +                      DEBUG ("configfile: Not including `%s' because it "
 +                                      "does not match pattern `%s'.",
 +                                      filename, pattern);
 +                      free (tmp);
 +                      return (NULL);
 +              }
 +
 +              free (tmp);
 +#else
 +              ERROR ("configfile: Cannot apply pattern filter '%s' "
 +                              "to file '%s': functions basename() and / or "
 +                              "fnmatch() not available.", pattern, file);
 +#endif /* HAVE_FNMATCH_H && HAVE_LIBGEN_H */
 +      }
 +
        root = oconfig_parse_file (file);
        if (root == NULL)
        {
                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 */
@@@ -647,8 -608,7 +653,8 @@@ static int cf_compare_string (const voi
        return strcmp (*(const char **) p1, *(const char **) p2);
  }
  
 -static oconfig_item_t *cf_read_dir (const char *dir, int depth)
 +static oconfig_item_t *cf_read_dir (const char *dir,
 +              const char *pattern, int depth)
  {
        oconfig_item_t *root = NULL;
        DIR *dh;
                oconfig_item_t *temp;
                char *name = filenames[i];
  
 -              temp = cf_read_generic (name, depth);
 +              temp = cf_read_generic (name, pattern, depth);
                if (temp == NULL)
                {
                        /* An error should already have been reported. */
   * simpler function is used which does not do any such expansion.
   */
  #if HAVE_WORDEXP_H
 -static oconfig_item_t *cf_read_generic (const char *path, int depth)
 +static oconfig_item_t *cf_read_generic (const char *path,
 +              const char *pattern, int depth)
  {
        oconfig_item_t *root = NULL;
        int status;
                }
  
                if (S_ISREG (statbuf.st_mode))
 -                      temp = cf_read_file (path_ptr, depth);
 +                      temp = cf_read_file (path_ptr, pattern, depth);
                else if (S_ISDIR (statbuf.st_mode))
 -                      temp = cf_read_dir (path_ptr, depth);
 +                      temp = cf_read_dir (path_ptr, pattern, depth);
                else
                {
                        WARNING ("configfile: %s is neither a file nor a "
  
        wordfree (&we);
  
-       if (root->children == NULL)
-       {
-               oconfig_free (root);
-               return (NULL);
-       }
        return (root);
  } /* oconfig_item_t *cf_read_generic */
  /* #endif HAVE_WORDEXP_H */
  
  #else /* if !HAVE_WORDEXP_H */
 -static oconfig_item_t *cf_read_generic (const char *path, int depth)
 +static oconfig_item_t *cf_read_generic (const char *path,
 +              const char *pattern, int depth)
  {
        struct stat statbuf;
        int status;
        }
  
        if (S_ISREG (statbuf.st_mode))
 -              return (cf_read_file (path, depth));
 +              return (cf_read_file (path, pattern, depth));
        else if (S_ISDIR (statbuf.st_mode))
 -              return (cf_read_dir (path, depth));
 +              return (cf_read_dir (path, pattern, depth));
  
        ERROR ("configfile: %s is neither a file nor a directory.", path);
        return (NULL);
@@@ -1041,12 -993,18 +1041,18 @@@ int cf_read (char *filename
        oconfig_item_t *conf;
        int i;
  
 -      conf = cf_read_generic (filename, 0 /* depth */);
 +      conf = cf_read_generic (filename, /* pattern = */ NULL, /* depth = */ 0);
        if (conf == NULL)
        {
                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 3358f5df59e82c4b1b3a55b7c74239159f804edf,2a1ebb33a1758913c1f3f12ba0cda90423eda1dd..fb443d9e99023e59bc367e2579c6adafe7ce7bb3
@@@ -52,7 -52,6 +52,7 @@@ dns_response          value:DERIVE:0:
  dns_transfer          value:DERIVE:0:U
  dns_update            value:DERIVE:0:U
  dns_zops              value:DERIVE:0:U
 +duration              seconds:GAUGE:0:U
  email_check           value:GAUGE:0:U
  email_count           value:GAUGE:0:U
  email_size            value:GAUGE:0:U
@@@ -77,9 -76,7 +77,9 @@@ if_multicast          value:DERIVE:0:
  if_octets             rx:DERIVE:0:U, tx:DERIVE:0:U
  if_packets            rx:DERIVE:0:U, tx:DERIVE:0:U
  if_rx_errors          value:DERIVE:0:U
 +if_rx_octets          value:DERIVE:0:U
  if_tx_errors          value:DERIVE:0:U
 +if_tx_octets          value:DERIVE:0:U
  invocations           value:DERIVE:0:U
  io_octets             rx:DERIVE:0:U, tx:DERIVE:0:U
  io_packets            rx:DERIVE:0:U, tx:DERIVE:0:U
@@@ -88,7 -85,7 +88,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