Plugins currently available:

collectd's plugin architecture

The plugin structure in itself is not very complicated, but it's easy to forget something anyway. I recommend copying a simple plugin (the load-plugin, for example) and start from there. Please note that this document describes the plugin architecture of version 4. The plugin architecture that was used in version 3 is obsolete.

Here's a walk-through or a check-list of things a plugin needs.

Copyright notice

All *.c-files must include a copyright notice and license information. The license must be compatible to collectd's own license, the GPL 2. Unless you have a good reason to split up your plugin into multiple files, please put everything into one .c-file.

Includes / Header files

Usually plugins include the following header-files:

#include "collectd.h"
#include "common.h" /* auxiliary functions */
#include "plugin.h" /* plugin_register_*, plugin_dispatch_values */

Callback functions

The initial step for a plugin is to register one or more callback functions. After the shared object has been loaded, the daemon will call the function void module_register (void) that has to be exported by the plugin. The purpose of this function is to register callback functions with the daemon (and nothing else).

There are the following types of callback functions, that can be registered. Of course, they are all optional.

config-functions

If a plugin needs configuration it must provide a config-function. The function is called once for each config-item found. It is registered using the plugin_register_config function. There's no garuantee that it's called only once for each config-key or that it's called at all.

Prototype

The function needs to have the following prototype:

int my_config (const char *key, const char *value);
Return value

The return-value must be zero upon success, greater than zero if it failed or less than zero if key has an invalid value.

init-functions

The init-function is used to set a plugin up before using it. The init-function is called after the configfile has been read (i. e. all calls to the config-function have been made) and before any calls to the read- and write-functions.

Prototype
int my_init (void);
Return value

The function has to return zero if successfull and non-zero otherwise. If non-zero is returned all functions the plugin registered will be unregistered.

read-functions

This function is called once every step seconds. It's supposed to gather the values from somewhere and eventually call plugin_dispatch_values. Several implementation of this function may exist, but only one may be compiled. Use #defines to decide which function to compile.

Prototype
int my_read (void);
Return value

The function has to return zero if successfull and non-zero otherwise. If non-zero is returned this function will not be called again for some time. The time between the calls of the function is increased exponentially until one day (86400 seconds) is reached. As soon as the function returns zero it will be called every step seconds again.

write-functions

Plugins that implement writing of values to somewhere may register a write-function. When a read-function calls plugin_dispatch_values that value-list will be passed to all write-functions together with a data-set, a description of the values. See below for a description of these data-types. Please note that this function needs to be thread-safe.

Prototype
int my_write (const data_set *ds, const value_list_t *vl);
Return value

As expected: Zero indicates success, non-zero indicates failure.

log-functions

These callbacks are called whenever some plugin (or the daemon itself) want to inform the world about something. Please note that using one of the logging macros, such as ERROR from within these functions will result in an endless loop.

Prototype
void my_log (int loglevel, const char *message);

shutdown-functions

Many plugins wish to clean up after themselves. The shutdown-functions can be used to implement that and terminate threads, close files or similar tasks before exiting.

Prototype
int my_shutdown (void);
Return value

As expected: Zero indicates success, non-zero indicates failure.

The module_register-function

The only function with a fixed name. It's called once after the shared object has been loaded so the plugin can register it's functions with the rest of the plugin architecture. Typically thats one or more calls to plugin_register_*.

Prototype

Please note that this function may not be static and the name may not be changed.

void module_register (void);

Data types

There are two complex data types that plugins may encounter. The first one, value_list_t, is used when passing values from the plugin to the plugin_dispatch_values function from the plugin interface. The second one, data_set_t occurs in the prototype of write-functions and may come up when dynamically loading data-set-definitions. All the following declarations can be found in "plugin.h".

value_list_t

This is the container for values that are passed to the daemon or from the daemon to write-functions. It is defined as follows:

struct value_list_s
{
  /* Array of values. */
  value_t *values;
  int      values_len;
  /* Time when the values were collected. */
  time_t   time;
  /* Identity of the values (without type). */
  char     host[DATA_MAX_NAME_LEN];
  char     plugin[DATA_MAX_NAME_LEN];
  /* These two may be empty: */
  char     plugin_instance[DATA_MAX_NAME_LEN];
  char     type_instance[DATA_MAX_NAME_LEN];
};
typedef struct value_list_s value_list_t;

Please note that the char-arrays have a fixed size of DATA_MAX_NAME_LEN (currently 64). Don't let this buffer overflow! Also, you can use the define VALUE_LIST_INIT to initialize (static) instances of this type. It has proven handy to implement a "submit" function with a static array of type value_t and a static instance of this type.

data_set_t

The data_set_t type is registered once with the daemon and used to know of which type each value_t in a value_list_t is and which minimum/maximum values are allowed. This is, of course, mostly relevant for write-functions which get a structure of this type as the first argument.

struct data_source_s
{
  /* Name of the value/data source */
  char   name[DATA_MAX_NAME_LEN];
  /* DS_TYPE_COUNTER or DS_TYPE_GAUGE */
  int    type;
  /* Minimum/maximum value; NAN means undefined */
  double min;
  double max;
};
typedef struct data_source_s data_source_t;

struct data_set_s
{
  /* Name of the data-set (== type) */
  char           type[DATA_MAX_NAME_LEN];
  /* Array of values/data-sources */
  data_source_t *ds;
  int            ds_num;
};
typedef struct data_set_s data_set_t;

Plugins can register such a data_set_t using plugin_register_data_set. The structure will be copied, i. e. it can be freed in the plugin after registering it. For plugins that simply want to provide a read-function it is recommended to include the data-set-definition in the types.db rather than registering it from within the plugin.

The interface's stability

Please be aware, that the plugin-interface is not considered part of the backwards compatibility of new minor versions, i. e. it may change pretty much at any time. It will certainly change with the next major version.
It's not as if we change the interface with every other release, but if you want to be really sure that your plugin works next year, please send it in. We will then take care of it and adapt the interface should it change.