How to Write a Collectd Plugin with Python

This post was originally published here

Collectd is a system statistics collection daemon. It gathers a lot of information about the system it’s running on, and passes it on to a software that can process and visualize that information, e.g. Grafana.

Collectd already brings along a lot of built-in plugins to gather information about the system load, the network traffic, available entropy, various sensors, etc. But sometimes there’s a value that you want to log which is not covered by an existing plugin.

There’s a generic plugin called Exec, but it has the downside that a new process is spawned for every invocation. That leads to bad performance if a value is queried often.

But there’s another way to include custom scripts, which is the Python plugin. In contrast to Exec, it does not spawn a new process for each invocation. Instead, it loads the specified Python script with an embedded interpreter. This makes it more powerful and efficient.

In this post, we’ll walk through the process of writing a collectd Python plugin for measuring the Raspberry Pi CPU temperature.

Plugin Structure

A Python plugin can register various callbacks:

  • config: You can pass configuration from your collectd.conf to your Python script. In the case of the Raspberry Pi, we could pass in the path to the temperature sensor device.
  • init: This function is called once and can be used to initialize resources, e.g. opening a socket.
  • read: This function collects the actual data. It is called once per interval. If something goes wrong, the exception the plugin will be skipped for an increasing amount of time until it returns normally again.
  • write: This function can be used to process values dispatched by other plugins.
  • flush: This function can be used to flush internal caches.
  • log: This function can be used to log useful information to the collectd log.
  • notification: This function is notified when a previously configured threshold has been exceeded.
  • shutdown: The opposite of the init function. Here you can clean up allocated resources, e.g. sockets.

The callbacks can be registered from Python using the register_* function from the collectd package. In our case we just need the config and read callbacks.

Reading the Raspberry Pi CPU Temperature

Getting the current CPU temperature of the Raspberry Pi is simple: We can query the temperature sensor pseudo-file located at /sys/class/thermal/thermal_zone0/temp.

$ cat /sys/class/thermal/thermal_zone0/temp

The value is returned in millidegrees Celsius.

Writing our Script

In our script, we first import the collectd package that allows us to interface with the daemon.

import collectd

Next, we accept some user configuration. The user should be able to configure the path to the temperature device like this:

Path "/sys/class/thermal/thermal_zone0/temp"

The Python callback is a simple function that accepts a Config object.

PATH = '/sys/class/thermal/thermal_zone0/temp'

def config_func(config):
    path_set = False

    for node in config.children:
        key = node.key.lower()
        val = node.values[0]

        if key == 'path':
            global PATH
            PATH = val
            path_set = True
  'cpu_temp plugin: Unknown config key "%s"' % key)

    if path_set:'cpu_temp plugin: Using overridden path %s' % PATH)
    else:'cpu_temp plugin: Using default path %s' % PATH)

Since we don’t need to allocate any special resources, we don’t need an init function. But we need to read data!

def read_func():
    # Read raw value
    with open(PATH, 'rb') as f:
        temp =

    # Convert to integer
    mdeg = int(temp)

    # Dispatch value to collectd
    val = collectd.Values(type='temperature')
    val.plugin = 'cpu_temp'

Finally, we have to register those two callbacks.


For more information about the Python API, please refer to the corresponding man page.

Installing the Plugin

copy the script to your target system. For this example, let’s assume that the file is named and that it has been copied to /opt/collectd_plugins/. Now you can configure the Python plugin in your collectd.conf:

LoadPlugin python
<Plugin python>
    ModulePath "/opt/collectd_plugins"
    Import "cpu_temp"
    <Module cpu_temp>
        Path "/sys/class/thermal/thermal_zone0/temp"

Restart collectd and take a look at the log. It should contain the following line:

cpu_temp plugin: Using overridden path /sys/class/thermal/thermal_zone0/temp

Looks like everything worked perfectly 🙂 Sit back and enjoy your beautiful temperature graphs.

Graph of the CPU temperature over a duration of 10 minutes

If something goes wrong, add the LogTraces true line to your plugin configuration to be able to see Python stack traces in your log.

Complete Code

You can find the finished plugin source code on Github.

Related Posts

Python’s Instance, Class, and Static Methods Demystified In this tutorial I’ll help demystify what’s behind class methods, static methods, and regular instance methods. If you develop an intuitiv...
How to do Descriptives Statistics in Python using Numpy In this short post we are going to revisit the topic on how to carry out summary/descriptive statistics in Python. In the previous post, I used Pandas...
A Magical Introduction to Classification Algorithms by Bryan Berend | March 23, 2017 About Bryan: Bryan is the Lead Data Scientist at Nielsen. Introduction When you first start learning about data sci...
Turbocharge Your Data Acquisition using the Python Library When working with data, a key part of your workflow is finding and importing data sets. Being able to quickly locate data, understand it and combine i...

Leave a Reply

Be the First to Comment!

Notify of