A Collectd Plugin Written in Rust
Collectd is a ubiquitous system statistics collection daemon.
collectd_plugin
leverages Collectd's ability to dynamically load plugins and
creates an ergonomic, yet extremely low cost abstraction API to interface with
Collectd.
Features:
- Submit values to Collectd (which are then sent to all write plugins like graphite or rrd)
- Easy plugin configuration via Serde support
- Write values that have been submitted by other plugins
- Receive all log events and their messages
Usage
Add to your Cargo.toml
:
[]
= "0.4"
If you want Serde support (recommended), include: features like this:
[]
= { = "0.3", = ["serde"] }
Then put this in your crate root:
extern crate collectd_plugin;
Rust 1.20 or later is needed to build.
This repo is tested on the following:
- Collectd 5.4 (Ubuntu 14.04)
- Collectd 5.5 (Ubuntu 16.04)
- Collectd 5.7 (Ubuntu 17.04)
Quickstart
Below is a complete plugin that dummy reports load values to collectd, as it registers a READ
hook. For an implementation has the same behavior as Collectd's own load plugin, see plugins/load
extern crate collectd_plugin;
extern crate failure;
use ;
use Error;
;
// A manager decides the name of the family of plugins and also registers one or more plugins based
// on collectd's configuration files
// We pass in our plugin manager type
collectd_plugin!;
Motivation
There are five main ways to extend collectd:
- Write plugin against the C api:
<collectd/core/daemon/plugin.h>
- Write plugin for collectd-python
- Write plugin for collectd-java
- Write a cli for the exec plugin
- Write a service that writes to a unix socket
And my thoughts:
- I'm not confident enough to write C without leaks and there isn't a great package manager for C.
- Python and Java aren't self contained, aren't necessarily deployed on the server, are more heavy weight, and I suspect that maintenance plays second fiddle to the C api.
- The exec plugin is costly as it creates a new process for every collection
- Depending on the circumstances, writing to a unix socket could be good fit, but I enjoy the ease of deployment, and the collectd integration -- there's no need to re-invent logging scheme, configuration, and system init files.
Rust's combination of ecosystem, package manager, C ffi, single file dynamic library, and optimized code made it seem like a natural choice.
To Build
To ensure a successful build, the following steps are needed:
- When building, you must supply the collectd version you'll be deploying:
cargo build --features collectd-54
cargo build --features collectd-55
cargo build --features collectd-57
- Your project crate type must be
cdylib
- If you want to use
bindgen
to generate the ffi functions, use thebindgen
feature (still alongside the desired collectd version). Make sure you have an appropriate version of clang installed andcollectd-dev
- Collectd expects plugins to not be prefixed with
lib
, socp target/debug/libmyplugin.so /usr/lib/collectd/myplugin.so
- Add
LoadPlugin myplugin
to collectd.conf
Plugin Configuration
The load plugin in plugins/load demonstrates how to expose configuration values to Collectd.
# In this example configuration we provide short and long term load and leave
# Mid to the default value. Yes, this is very much contrived
ReportRelative true