Using RRDTool in Zenoss
rrdtool is an awesome high performance data logging and graphing tool for time series data. Zenoss Core uses RRDTool to collect, monitor, and graph peformance data for devices.
However Zenoss Core comes with built-in helper wrappers around RRDTool that makes using it within Zenoss much easier. These source code files can be found in $ZENHOME/Products/ZenRRD/
.
RRDUtil
Located in $ZENHOME/Products/ZenRRD/RRDUtil.py
, this Python module contains many wrapper methods around the rrdtool library. These methods can help us write to, create new, and read .rrd
files using Python.
We can easily import this module into our code, using the following import statement:
from Products.ZenRRD.RRDUtil import RRDUtil
Writing to a Device's RRD File
Performance .rrd
files for each device are located in $ZENHOME/perf/Devices/$DEVICE_IP/
. All the RRD files for each graph in our custom monitoring templates will be located here. The values contained within each file is what the graph actually represents in the Zenoss graphic user interface.
Let's assume that we have a custom monitoring template that adds, monitors, and graphs a power usage data point. And that the value for this data point is collected periodically through a ZenPack daemon. This value is then written to the data point's .rrd
file, called Power_Power.rrd
for this example.
We can then use RRDUtil in our daemon's code to write to the RRD file:
def _writeRRD(self, device, rrd_file_name, value):
try:
from Products.ZenRRD.RRDUtil import RRDUtil
path = 'Devices/{0}/{1}'.format(device.id, rrd_file_name)
rrd = RRDUtil('', 300)
rrd_save_val = rrd.save(path, value, "GAUGE", min=0, max=None)
log.info('Wrote to {0} with value {1}'.format(rrd.performancePath(path + '.rrd'), rrd_save_val))
except Exception as e:
summary = "Unable to save data value into RRD file {0} - Exception: {1}".format(rrd.performancePath(path + '.rrd'), e.message)
log.error(summary)
First we need to build a correct path string that points to the dev'ces RRD file we want to modify (Example: $ZENHOME/perf/Devices/$DEVICE_IP/Power_Power.rrd
). So naturally we would pass the RRD file name (Power_Power
) as the rrd_file_name
parameter. We do not need to append the extension because the save
method will do so when it's called.
-> RRD file names for devices are named according to the dataSource_dataPoint
format. As shown in the monitoring template.
Since we are not creating a new file, we do not need to pass a create command to RRDUtil, hence why we pass a blank string as the first parameter.
Finally, the magic then happens in the save
method, where we tell RRDUtil to save the value into the file, specified by the performance path. This performance path is generated using the path string we constructed before, inside the put
(The save
method actually makes a call to put
in order to save the value) method's code:
# $ZENHOME/Products/ZenRRD/RRDUtil.py
def put(self, path, value, rrdType, rrdCommand=None, cycleTime=None,
min='U', max='U', useRRDDaemon=True, timestamp='N', start=None,
allowStaleDatapoint=True):
# ...
filename = self.performancePath(path) + '.rrd'
=> After saving the value into the RRD file, the save
method will fetch the latest value for the data point and return it. We can then use this value in our logs to confirm that the save
method indeed saved the correct value.