[collectd] Questions about coding standards & writing plugins

Florian Forster octo at verplant.org
Fri Nov 2 15:00:39 CET 2007

Hey Rich,

On Fri, Nov 02, 2007 at 01:08:01PM +0000, Richard W.M. Jones wrote:
> (1) You say 'Only reentrant- and threadsafe functions may be used'.
>     The problem is that libvirt functions aren't reentrant, so I
>     guess, if this is a real concern, then I'll need to put locking
>     around them.

that's not that big a problem: Your `read' function isn't called several
times in parallel, so there's at most on thread in there at a time.
Since the plugin is probably the only part of collectd to ever call
libvirt functions they don't need to be reentrant safe. (That is, as
long as no other part of the daemon or another plugin accesses those
functions, which is very unlikely).

> Do you have locking functions?

If you need them, use `pthread_mutex_lock' and `..._unlock'.

> Is collectd really threaded, because if my plugin can be called from
> different threads then I'm going to need to think harder about the
> implementation.

Yes, collectd has a bunch of `read' threads and your `read' function is
called from one of those threads. As long as you don't use any
thread-local storage that's not a problem though.

> (2) Many of the stats that can be collected through libvirt are of the
>     "counting up from zero" variety, eg. number of disk blocks
>     processed by a guest since the guest was booted.  My reading of
>     plugins such as 'interface.c' seems to indicate that collectd can
>     handle such stats natively, so that I don't need to subtract the
>     earlier reading and divide by time passed.

Right, collectd or librrd do that for you. What you need to do is fill
the `value_list_t' structure and pass that to `plugin_dispatch_values'.

There are two basic data types: `counter_t' for counter values and
`gauge_t' for ``gauge'' values, i. e. values that can go up and down as
they like, e. g. temperature.
Those two data types are combined in a union named `value_t'.
value_t.counter is of type counter_t while value_t.gauge is of type
The value_list_t structure has an pointer to one or more value_t values.
The each value is either of type `counter' or `gauge', but so far the
daemon doesn't know which one it is. This is later determined using the
`type' argument passed to `plugin_dispatch_values'.
The `host', `plugin', `plugin_instance' and `type_instance' members,
together with the `type' argument passed to `plugin_dispatch_values',
are used to identify the dataset:
- host: Name of the host this data applies to (if you can get that from
  libvirt). Set it to `hostname_g' (a global variable) if you can't get
  the hostname of the virtualized host from libvirt or if the data
  applies to the mother-system.
- plugin: Should be set to `libvirt' or `virt' or however you named your
- plugin_instance: Should probably be empty.
- type_instance: Used to differentiate between statistics of the same
  `type', e. g. if you have multiple network interfaces you can set this
  to `eth0', `eth1', .. to tell one data set from the other.
The `type' (which is not part of this struct, but closely related) is
used to tell the daemon the `layout' of your data, i. e. which position
in the `value' array is of which type (counter or gauge). These `type's
are defined in the `types.db' file. The entries are very similar to the
definitions from RRDTool:
- First there's a name,
- then a type (in our case COUNTER or GAUGE)
- followed by a min and a max value.
If you have a second ``data source'' (i. e. a second value in the
`values' member) the second block is separated by a comma.

The other members of `value_list_t' are straight forward (I hope):
- interval: Interval in which data is collected. Set it to `interval_g'
  (a global variable).
- time: Time at which this data was collected. Set it to `time (NULL)'.
- values_len: Number of values in the `values' member.

> Do I need to define a type and add it to src/types.db, and if so what
> do the fields in this file mean & how is it generated?

You don't _need_ to add a new type to there, but you can only use types
defined there. That is, if you need something that's not already there,
you need to add a new type. For network statistics you can probably use
the `if_octets' (and possibly `if_packets') types, IO statistics can
possibly handled using `disk_octets' and `disk_ops'. I'm not sure what
kind of stats you have precisely..

Hope the above was somewhat useful.. If not, please don't hesitate to
ask again :) If you have any pointers where the development
documentation could be improved, please let me know, I'll do my best ;)

Florian octo Forster
Hacker in training
GnuPG: 0x91523C3D
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 2567 bytes
Desc: not available
Url : http://mailman.verplant.org/pipermail/collectd/attachments/20071102/5e29c7b4/attachment.bin 

More information about the collectd mailing list