The Concise guide to plugin authoring¶
First of all you should have read the HOWTO. This page is an attempt to be brief and yet complete rather than helpful to a beginner.
What is a plugin?¶
A plugin is a stand-alone program. In its most common form it is a small perl program or shell script.
The plugins are run by munin-node
and invoked when contacted by the Munin master. When this happens the munin-node
runs each plugin twice. Once with the argument config
to get the graph configuration and once with no argument to get the graph data.
Run Time Arguments¶
A plugin is invoked twice every update-cycle. Once to emit config
information and once to fetch
values. Please see Data exchange between master and node for more information about the over-the-wire transactions.
config¶
This argument is mandatory.
The config
output describes the plugin and the graph it creates. The full set of attributes you can use is found in the config reference.
fetch¶
This argument is mandatory.
When the node receives a fetch
command for a plugin, the plugin is invoked without any arguments on the command line and is expected to emit one or more field.value
attribute values. One for each thing the plugin observes as defined by the config
output. Plotting of graphs may be disabled by the config
output.
Please note the following about plugin values:
- If the plugin - for any reason - has no value to report, then it may send the value
U
for undefined. It should report values for every field it has configured duringconfig
. - In 1.3.4 and later: The plugin may back-date values by reporting them on the format
field.value <epoch>:<value>
, where <epoch> is the number of seconds since 1970/1/1 00:00 (unix epoch) and <value> is the value in the ordinary way. This can be useful for systems where the plugin receives old data and gives the correct time axis on the graph.
Install Time Arguments¶
Install time is managed by one utility: munin-node-configure. It can both auto configure host plugins and (given the right options) it will auto configure snmp plugins for a specific host.
To do this it looks inside the plugins to determine how much plug-and-play ability features have been implemented for the user. For details read the section about magic markers.
An automated installation will run munin-node-configure
and hereby selects the plugins that are ready to run on the specific node. The integration is then done by symlinking them in the service directory (usually /etc/munin/plugins
).
Every plugin with a family=auto magic marker (#%# family=auto
) will be interrogated automatically with the autoconf
and perhaps the suggest
methods. You can change the family list with the --families
option.
Any snmp__*
plugins will be auto configured and installed by munin-node-configure --snmp
with the appropriate arguments.
Every plugin magic marked with family=snmpauto and capabilities=snmpconf will be interrogated - when appropriately run by munin-node-configure
.
autoconf¶
A plugin with a capabilities=autoconf magic marker will first be invoked with autoconf
as the sole argument. When invoked thus the plugin should do one of these two:
- Print “yes” to signal that the plugin thinks it can be useful on this host
- Print “no” to signal that the plugin does not think so.
The plugin should always exit 0, even if the response is “no”.
If the answer was “yes” and it’s not a wildcard plugin, the plugin will be linked into the plugins catalog of munin-node.
Example:
# ./load autoconf
yes
If the answer is “no” the plugin may give a reason in parentheses. This may help the user to troubleshoot why the plugin is not used/does not work.
# ./load autoconf
no (No /proc/loadavg)
Note
If a plugin is autoconf-igurable it SHOULD not terminate in a uncontrolled way during autoconfiguration. Please make sure that whatever happens it ends up printing a “yes” or a “no” with a reasonable reason for why not.
In particular plugins written in Perl, Python and the like SHOULD not require non-core modules without protecting the code section. In perl one would do something like this (from apache_accesses at the time I write this):
if (! eval "require LWP::UserAgent;") {
$ret = "LWP::UserAgent not found";
}
...
if ( defined $ARGV[0] and $ARGV[0] eq "autoconf" ) {
if ($ret) {
print "no ($ret)\n";
exit 0;
}
}
If the plugin is to be distributed with Munin the SHOULDs above are MUSTs.
suggest¶
Munin creates one graph per plugin. To create many graphs from one plugin, you can write a wildcard plugin.
These plugins take one or more bits of configuration from the file name it is run as. The plugin is stored as one file in the directory for available plugins, but is linked as multiple files in the directory for enabled plugins. This creates one graph per link name, using just one plugin as source.
Example:
/etc/munin/plugins/if_eth0 -> /usr/share/munin/plugins/if_
/etc/munin/plugins/if_eth1 -> /usr/share/munin/plugins/if_
As you see: wildcard plugins are easily recognized by their names ending in _.
A wildcard plugin that has a capabilities=suggest magic marker will - after autoconf
- be invoked with suggest
as the sole argument. It then should examine the system and determine which of the similar things it can report on and output a list of these.
# ./if_ suggest
eth0
eth1
This means that the plugin can be run as if_eth0
and if_eth1
. The plugin will then have to examine what’s in C is called ARGV[0]
, and in perl and shell scripts as $0
to determine what exactly the start command was.
snmpconf¶
As stated above a plugin magic marked with family=snmpauto and capabilities=snmpconf will be invoked with snmpconf
as the sole argument. A SNMP plugin is by definition a wildcard plugin, it may examine any host that supports SNMP. The name convention for a SNMP plugin is examplified by the df plugin: snmp__df
. The hostname goes between the two consecutive underlines (_), and when invoked, the plugin may examine $0
, as any wildcard plugin must, to determine the name of the host it is to work with. It may also contain two wildcards as in snmp__if_
. Here the index of the network interface appears after the third underline (_) at the end of the string. e.g. snmp_foo.example.com_if_1
.
On the occasion of being run with snmpconf
the plugin shall output one or more of the following:
For a plugin that is to monitor a number of (enumerated) items: the items have to be counted and indexed in the MIB and the plugin can express this so:
- The word
number
followed by a OID giving the number of items - The word
index
, followed by a OID ending with a trailing dot on to the table of indices
Both the snmp__df
and the snmp__if_
plugins use this. The df plugin because it monitors multiple storage resources and wants to monitor only fixed disks. It expresses this by asking for the index OID for storage be present. The snmp__if_
plugin uses both number
and index
. The number OID gives the number of network interfaces on the device.
For a plugin named in the pattern analogous to snmp__if_
each of the indices will be used at the end of the plugin name, e.g. snmp_switch_if_10
for a device named switch, interface index 10.
- The word
require
followed by an OID or the root of an OID that must exist on a SNMP agent. The OID may optionally be followed by a string or RE-pattern that specifies what sort of response is expected. For a indexed plugin (one that gives “number” and “index” the indecies will be appended to the require OID to check that OID for each indexed item (e.g. a interface)
Example:
# ./snmp__if_ snmpconf
number 1.3.6.1.2.1.2.1.0
index 1.3.6.1.2.1.2.2.1.1.
require 1.3.6.1.2.1.2.2.1.5. [0-9]
require 1.3.6.1.2.1.2.2.1.10. [0-9]
A require supports any perl RE, so for example one could require (6|32) from a OID to filter out only certain kinds of items.
If all the named items require
and number
, index
given are found (and matched if a RE is given) the plugin will be activated by munin-node-configure
.
munin-node-configure will send queries to devices that the user has claimed to be interested in, to see if these OIDs exist and have matching values if required. If so the plugin will be linked into the munin-node
service directory (usually /etc/munin/plugins
).
Configuration¶
Plugins are configured through files on each node.
The munin-node
plugin configuration files reside in /etc/munin/plugin-conf.d/
. These are used by munin-node
to determine which privileges a plugin should get (which user and group runs the plugin) and which settings of environment variables should be done for the plugins. Each file in /etc/munin/plugin-conf.d/
can contain configuration for one or more plugins.
The configuration files are read in alphabetical order and configuration of the last read file overrides earlier configuration.
The format is:
[name or wildcard]
user <username>
group <group>
env.<variable name> <variable content>
Privileges¶
Munin usually runs each plugin as an unprivileged user.
To run the plugin as a specific user:
[example]
user someuser
To run a plugin with an additional group:
[example]
group somegroup
Environment variables¶
To set the variable logfile
to /var/log/example.log
:
[example]
env.logfile /var/log/some.log
When using environment variables in your plugins, the plugin should contain sensible defaults.
Example /bin/sh
code. This adds an environment variable called $LOG
, and sets it to the value of $logfile
(from env.logfile
in the Munin plugin configuration), with a default of /var/log/syslog
if $logfile
is empty:
#!/bin/sh
LOG=${logfile:-/var/log/syslog}
Example configuration¶
This plugin reads from /var/log/example.log
, which is readable by user root
and group adm
. We set an environment variable for the logfile, and we need additional privileges to be able to read it. Choosing the least amount of privileges, we choose to run the plugin with the group adm
instead of user root
.
[example]
group adm
env.logfile /var/log/example.log
Activating a Munin plugin¶
To activate a plugin it needs to be executable and present in the munin plugin directory, commonly /etc/munin/plugins
. It can be copied or symlinked here.
Plugins shipped with munin-node are placed in the directory for available Munin plugins, commonly /usr/share/munin/plugins
. To activate these, make symlinks to the Munin plugin directory, commonly /etc/munin/plugins
.
Running a Munin plugin interactively¶
A munin plugin is often run with modified privileges and with a set of environment variables. To run a plugin within its configured environment, use the munin-run command. It takes a plugins service link name as the first argument and any plugin argument as the next.
Example (with long lines broken):
ssm@mavis:~$ munin-run load config
graph_title Load average
graph_args --base 1000 -l 0
graph_vlabel load
graph_scale no
graph_category system
load.label load
load.warning 10
load.critical 120
graph_info The load average of the machine describes how many processes \
are in the run-queue (scheduled to run "immediately").
load.info Average load for the five minutes.
ssm@mavis:~$ munin-run load
load.value 0.11