Fenron

Friday, January 19, 2007

Adding new data sources to an RRD using XSLT

The perl module RRD::Simple includes an add_source() function, which mucks with the XML format of an RRD to add data sources. For stupid reasons, CPAN wasn't working on the system that contained the RRDs I wanted to muck with, so instead of fixing that I decided to figure out what RRD::Simple did and do it with XSLT. (OK, so jab pushed me in this direction, I was going to fix CPAN...)

1. Figure out what the XML declaration of the new sources should look like. The easiest way to do this is to create an RRD and then dump it and look at the <ds> elements of the dumped file.

2. Create an xsl file to add these sources. Here's what I did:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/rrd/ds[position()=last()]">
<xsl:copy-of select="."/>
<ds>
...new ds elements go here...
</ds>
</xsl:template>
<xsl:template match="/rrd/rra/cdp_prep/ds[position()=last()]">
<xsl:copy-of select="."/>
<ds>
<primary_value> 0.0000000000e+00 </primary_value>
<secondary_value> 0.0000000000e+00 </secondary_value>
<value> NaN </value>
<unknown_datapoints> 0 </unknown_datapoints>
</ds>
...one of the above <ds>...</ds> for each new data source...
</xsl:template>
<xsl:template match="/rrd/rra/database/row/v[position()=last()]">
<xsl:copy-of select="."/>
<v> NaN </v>
...one NaN line for each new data source...
</xsl:template>
</xsl:stylesheet>


3. Process each rrd with rrdtool dump, xsltproc, rrdtool restore. Here's my shell script.

#!/bin/sh
cd /opt/local/share/cacti/rra
for i in *_yorkie_*.rrd
do
if [ $i = "bills_yorkie_uptime_26.rrd" ]
then
continue
fi
x=`basename $i .rrd`.xml
x2=`basename $i .rrd`-new.xml
rrdtool dump $i $x
xsltproc /Users/fenner/src/yorkie/add-ds.xsl $x > $x2
mv $i $i.old
rrdtool restore $x2 $i
done

0 Comments:

Post a Comment

<< Home