controls which plugins to load. These plugins ultimately define collectd's
behavior.
-The syntax of this config file is similar to the config file of the famos
+The syntax of this config file is similar to the config file of the famous
B<Apache Webserver>. Each line contains either a key-value-pair or a
section-start or -end. Empty lines and everything after the hash-symbol `#' is
ignored. Values are either string, enclosed in double-quotes,
B<false>. String containing of only alphanumeric characters and underscores do
not need to be quoted.
+Plugins are loaded in the order listed in this config file. It is a good idea
+to load any logging plugins first in order to catch messages from plugins
+during configuration.
+
+ The configuration is read and processed in order, i.E<nbsp>e. from top to
+ bottom. So the plugins are loaded in the order listed in this config file. It
+ is a good idea to load any logging plugins first in order to catch messages
+ from plugins during configuration. Also, the C<LoadPlugin> option B<must> occur
+ B<before> the C<E<lt>Plugin ...E<gt>> block.
+
=head1 GLOBAL OPTIONS
=over 4
Loads the plugin I<Plugin>. There must be at least one such line or B<collectd>
will be mostly useless.
+=item B<Include> I<File>
+
+Includes the file I<File> as if it was copy and pasted here. To prevent loops
+and shooting yourself in the foot in interesting ways the nesting is limited to
+a depth of 8E<nbsp>levels, which should be sufficient for most uses.
+
+It is no problem to have a block like C<E<lt>Plugin fooE<gt>> in more than one
+file, but you cannot include files from within blocks.
+
=item B<PIDFile> I<File>
Sets where to write the PID file to. This file is overwritten when it exists
channels, respectively. This, of course, only makes much sense when collectd is
running in foreground- or non-daemon-mode.
+=item B<Timestamp> B<true>|B<false>
+
+Prefix all lines printed by the current time. Defaults to B<true>.
+
=back
=head2 Plugin C<mbmon>
=back
+=head2 Plugin C<memcached>
+
+The C<memcached plugin> connects to a memcached server and queries statistics
+about cache utilization, memory and bandwidth used.
+L<http://www.danga.com/memcached/>
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+Hostname to connect to. Defaults to B<127.0.0.1>.
+
+=item B<Port> I<Port>
+
+TCP-Port to connect to. Defaults to B<11211>.
+
+=back
+
=head2 Plugin C<mysql>
The C<mysql plugin> requires B<mysqlclient> to be installed. It connects to the
=back
+=head2 Plugin C<nginx>
+
+This plugin collects the number of connections and requests handled by the
+C<nginx daemon> (speak: engineE<nbsp>X), a HTTP and mail server/proxy. It
+queries the page provided by the C<ngx_http_stub_status_module> module, which
+isn't compiled by default. Please refer to
+L<http://wiki.codemongers.com/NginxStubStatusModule> for more information on
+how to compile and configure nginx and this module.
+
+The following options are accepted by the C<nginx plugin>:
+
+=over 4
+
+=item B<URL> I<http://host/nginx_status>
+
+Sets the URL of the C<ngx_http_stub_status_module> output.
+
+=item B<User> I<Username>
+
+Optional user name needed for authentication.
+
+=item B<Password> I<Password>
+
+Optional password needed for authentication.
+
+=item B<CACert> I<File>
+
+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.
+
+=back
+
=head2 Plugin C<ntpd>
=over 4
=head2 Plugin C<perl>
-=over 4
-
-=item B<LoadPlugin> I<Plugin>
-
-Loads the Perl plugin I<Plugin>. This does basically the same as B<use> would
-do in a Perl program.
-
-=item B<BaseName> I<Name>
-
-Prepends I<Name>B<::> to all plugin names loaded after this option. This is
-provided for convenience to keep plugin names short.
-
-=item B<IncludeDir> I<Dir>
-
-Adds I<Dir> to the B<@INC> array. This is the same as using the B<-IDir>
-command line option or B<use lib Dir> in the source code.
-
-=back
+This plugin embeds a Perl-interpreter into collectd and provides an interface
+to collectd's plugin system. See L<collectd-perl(5)> for its documentation.
=head2 Plugin C<ping>
=back
+=head2 Plugin C<tcpconns>
+
+The C<tcpconns plugin> counts the number of currently established TCP
+connections based on the local port and/or the remote port. Since there may be
+a lot of connections the default if to count all connections with a local port,
+for which a listening socket is opened. You can use the following options to
+fine-tune the ports you are interested in:
+
+=over 4
+
+=item B<ListeningPorts> I<true>|I<false>
+
+If this option is set to I<true>, statistics for all local ports for which a
+listening socket exists are collected. The default depends on B<LocalPort> and
+B<RemotePort> (see below): If no port at all is specifically selected, the
+default is to collect listening ports. If specific ports (no matter if local or
+remote ports) are selected, this option defaults to I<false>, i.E<nbsp>e. only
+the selected ports will be collected unless this option is set to I<true>
+specifically.
+
+=item B<LocalPort> I<Port>
+
+Count the connections to a specific local port. This can be used to see how
+many connections are handled by a specific daemon, e.E<nbsp>g. the mailserver.
+You have to specify the port in numeric form, so for the mailserver example
+you'd need to set B<25>.
+
+=item B<RemotePort> I<Port>
+
+Count the connections to a specific remote port. This is useful to see how
+much a remote service is used. This is most useful if you want to know how many
+connections a local service has opened to remote services, e.E<nbsp>g. how many
+connections a mail server or news server has to other mail or news servers, or
+how many connections a web proxy holds to web servers. You have to give the
+port in numeric form.
+
+=back
+
=head2 Plugin C<unixsock>
=over 4
L<collectd(1)>,
L<collectd-exec(5)>,
+L<collectd-perl(5)>,
L<collectd-unixsock(5)>,
L<hddtemp(8)>,
L<kstat(3KSTAT)>,
if ((cf_cb = cf_search (type)) == NULL)
{
- WARNING ("Plugin `%s' did not register a callback.", type);
+ WARNING ("Found a configuration for the `%s' plugin, but "
+ "the plugin isn't loaded or didn't register "
+ "a configuration callback.", type);
return (-1);
}
return (0);
}
+#define CF_MAX_DEPTH 8
+static oconfig_item_t *cf_read_file (const char *file, int depth);
+
+static int cf_include_all (oconfig_item_t *root, int depth)
+{
+ int i;
+
+ for (i = 0; i < root->children_num; i++)
+ {
+ oconfig_item_t *new;
+ oconfig_item_t *old;
+
+ /* Ignore all blocks, including `Include' blocks. */
+ if (root->children[i].children_num != 0)
+ continue;
+
+ if (strcasecmp (root->children[i].key, "Include") != 0)
+ continue;
+
+ old = root->children + i;
+
+ if ((old->values_num != 1)
+ || (old->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ ERROR ("configfile: `Include' needs exactly one string argument.");
+ continue;
+ }
+
+ new = cf_read_file (old->values[0].value.string, depth + 1);
+ if (new == NULL)
+ continue;
+
+ /* There are more children now. We need to expand
+ * root->children. */
+ if (new->children_num > 1)
+ {
+ oconfig_item_t *temp;
+
+ DEBUG ("configfile: Resizing root-children from %i to %i elements.",
+ root->children_num,
+ root->children_num + new->children_num - 1);
+
+ temp = (oconfig_item_t *) realloc (root->children,
+ sizeof (oconfig_item_t)
+ * (root->children_num + new->children_num - 1));
+ if (temp == NULL)
+ {
+ ERROR ("configfile: realloc failed.");
+ oconfig_free (new);
+ continue;
+ }
+ root->children = temp;
+ }
+
+ /* Clean up the old include directive while we still have a
+ * valid pointer */
+ DEBUG ("configfile: Cleaning up `old'");
+ /* sfree (old->values[0].value.string); */
+ sfree (old->values);
+
+ /* If there are trailing children and the number of children
+ * changes, we need to move the trailing ones either one to the
+ * front or (new->num - 1) to the back */
+ if (((root->children_num - i) > 1)
+ && (new->children_num != 1))
+ {
+ DEBUG ("configfile: Moving trailing children.");
+ memmove (root->children + i + new->children_num,
+ root->children + i + 1,
+ sizeof (oconfig_item_t)
+ * (root->children_num - (i + 1)));
+ }
+
+ /* Now copy the new children to where the include statement was */
+ if (new->children_num > 0)
+ {
+ DEBUG ("configfile: Copying new children.");
+ memcpy (root->children + i,
+ new->children,
+ sizeof (oconfig_item_t)
+ * new->children_num);
+ }
+
+ /* Adjust the number of children and the position in the list. */
+ root->children_num = root->children_num + new->children_num - 1;
+ i = i + new->children_num - 1;
+
+ /* Clean up the `new' struct. We set `new->children' to NULL so
+ * the stuff we've just copied pointers to isn't freed by
+ * `oconfig_free' */
+ DEBUG ("configfile: Cleaning up `new'");
+ sfree (new->values); /* should be NULL anyway */
+ sfree (new);
+ new = NULL;
+ } /* for (i = 0; i < root->children_num; i++) */
+
+ return (0);
+} /* int cf_include_all */
+
+static oconfig_item_t *cf_read_file (const char *file, int depth)
+{
+ oconfig_item_t *root;
+
+ if (depth >= CF_MAX_DEPTH)
+ {
+ ERROR ("configfile: Not including `%s' because the maximum nesting depth has been reached.",
+ file);
+ return (NULL);
+ }
+
+ root = oconfig_parse_file (file);
+ if (root == NULL)
+ {
+ ERROR ("configfile: Cannot read file `%s'.", file);
+ return (NULL);
+ }
+
+ cf_include_all (root, depth);
+
+ return (root);
+} /* oconfig_item_t *cf_read_file */
+
/*
* Public functions
*/
oconfig_item_t *conf;
int i;
- conf = oconfig_parse_file (filename);
+ conf = cf_read_file (filename, 0 /* depth */);
if (conf == NULL)
{
ERROR ("Unable to read config file %s.", filename);