Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Write a low-cost, ergonomic plugin for collectd

License

NotificationsYou must be signed in to change notification settings

nickbabcock/collectd-rust-plugin

Repository files navigation

ciVersion

Write a Collectd Plugin in Rust

Collectd is a ubiquitous system statistics collectiondaemon. This Rust library leverages collectd's ability to dynamically loadplugins and creates an ergonomic, yet extremely low cost abstraction API tointerface with collectd. Works with collectd 5.7+.

Features:

  • No unnecessary allocations when submitting / receiving values, logging
  • Register multiple plugin instances
  • Automatic deserialization of plugin configs viaSerde (can opt-out)
  • Deployment: compile against collectd version and scp to server
  • Referenced Rust libraries are statically linked
  • Help writing thread safe plugins thanks to the Rust compiler

Usage

Add to yourCargo.toml:

[dependencies]collectd-plugin ="0.15.0"

Serde support is enabled by default for configuration parsing.

Quickstart

See what to add to your project's Cargo file

Below is a complete plugin that dummy reportsload values to collectd, as it registers aREAD hook. For an implementation that reimplements collectd's own load plugin, seeexamples/load

use collectd_plugin::{    collectd_plugin,ConfigItem,Plugin,PluginCapabilities,PluginManager,PluginRegistration,Value,ValueListBuilder,};use std::error;#[derive(Default)]structMyPlugin;// A manager decides the name of the family of plugins and also registers one or more plugins based// on collectd's configuration filesimplPluginManagerforMyPlugin{// A plugin needs a unique name to be referenced by collectdfnname() ->&'staticstr{"myplugin"}// Our plugin might have configuration section in collectd.conf, which will be passed here if// present. Our contrived plugin doesn't care about configuration so it returns only a single// plugin (itself).fnplugins(_config:Option<&[ConfigItem<'_>]>,) ->Result<PluginRegistration,Box<dyn error::Error>>{Ok(PluginRegistration::Single(Box::new(MyPlugin)))}}implPluginforMyPlugin{// We define that our plugin will only be reporting / submitting values to writersfncapabilities(&self) ->PluginCapabilities{PluginCapabilities::READ}fnread_values(&self) ->Result<(),Box<dyn error::Error>>{// Create a list of values to submit to collectd. We'll be sending in a vector representing the// "load" type. Short-term load is first (15.0) followed by mid-term and long-term. The number// of values that you submit at a time depends on types.db in collectd configurationslet values =vec![Value::Gauge(15.0),Value::Gauge(10.0),Value::Gauge(12.0)];// Submit our values to collectd. A plugin can submit any number of times.ValueListBuilder::new(Self::name(),"load").values(&values).submit()?;Ok(())}}// We pass in our plugin manager typecollectd_plugin!(MyPlugin);

Motivation

There are five main ways to extend collectd:

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, adapt the below to your project's Cargo file.

[lib]crate-type = ["cdylib"]name ="<your plugin name>"[features]bindgen = ["collectd-plugin/bindgen"]default = []
  • collectd-rust-plugin assumes a5.7-compatible API (5.7 works up to at least5.12). This can be configured via any of the following:
    • Specify thebindgen feature withCOLLECTD_PATH pointing at theroot git directory for collectd
      • Thebindgen feature also works ifcollectd-dev is installed
    • COLLECTD_VERSION may be used in the future whencollectd-rust-plugin reintroduces support for compiling against different collectd versions that are not API-compatible
    • When collectd is present on the system, the version is derived from executingcollectd -h
  • collectd expects plugins to not be prefixed withlib, socp target/debug/libmyplugin.so /usr/lib/collectd/myplugin.so
  • AddLoadPlugin myplugin to collectd.conf

Plugin Configuration

The load plugin inexamples/loaddemonstrates 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<Plugin loadrust>    ReportRelative true</Plugin>

Benchmarking Overhead

To measure the overhead of adapting collectd's datatypes when writing and reporting values:

cargo bench --features stub

If you'd like to use the timings on my machine:

  • 60ns to create and submit aValueListBuilder
  • 130ns to create aValueList for plugins that write values

Unless you are reporting or writing millions of metrics every interval (in which case you'll most likely hit an earlier bottleneck), you'll be fine.

Plugins

Do you use collectd-rust-plugin? Feel free to add your plugin to the list.

  • pg-collectd: An alternative and opinionated postgres collectd writer

About

Write a low-cost, ergonomic plugin for collectd

Topics

Resources

License

Stars

Watchers

Forks

Contributors6

Languages


[8]ページ先頭

©2009-2025 Movatter.jp