Click here to Skip to main content
12,546,448 members (55,185 online)
Click here to Skip to main content
Add your own
alternative version


38 bookmarked

"C# Hooks For RRDtool"

, 26 May 2010 GPL3
Rate this:
Please Sign up or sign in to vote.
C# (.NET and Mono) library provider for RRDtool


NHawk is an initiative to provide a thin, complete RRDtool provider for the .NET and Mono framework. The project goal is targeted at providing a C# interface to native RRDtool facilities through appropriate .NET / Mono object model semantics with the intent of retaining an intuitive syntax that fits naturally into the .NET / Mono paradigm and closely resembles that of native RRDtool. In doing so, NHawk seeks to provide a powerful time series analysis toolkit library that fills a big void in the .NET and Mono framework. It is our hope to provide a toolkit that promotes high productively, robustness, and expressiveness; enabling proficient C# developers to build code interchangeably (and intuitively) with native RRDtool script. It is a NHawk goal to promote productive use by allowing clients to refer solely to native RRDtool documentation resources, and thereby carry a very short learning curve (in most cases, if the developer is familiar with both RRDtool and C#). The example code snippets that follow will hopefully illustrate the basic concepts. Please make particular note of syntactic similarities, and pay special attention to the section highlighting serialization, deserialization, and deepcloning, as these comprise powerful architectural utility which include support for web service oriented applications as well as for generation of, and interoperation with existing (native) RRDtool scripts.


The examples that follow are taken from an expanded tutorial which has been included along with the version 1.0 release of the source code and binaries.

Please note that the example material that follows is derived from a tutorial created initially by: Alex van den Bogaerdt which can be viewed at

RRDtool is written by Tobias Oetiker and can be found at

*** See the end of this document for contact details and information pertaining to development and status of the current code revision. ***

Using the Code

RRDtool Syntax for Defining and Creating RRDs

rrdtool create test.rrd --start 920804400

NHawk (C#) Syntax for Defining and Creating RRDs

RRD rrd1 = new RRD("test.rrd", 920804400);
rrd1.addDS(new DS("speed",  DS.TYPE.COUNTER, 600, DS.U, DS.U));
rrd1.addRRA(new RRA(RRA.CF.AVERAGE, 0.5, 1, 24));
rrd1.addRRA(new RRA(RRA.CF.AVERAGE, 0.5, 6, 10));

RRDtool Update Syntax

rrdtool update test.rrd 920804700:12345

NHawk (C#) Update Syntax

NHawk provides a means to update an RRD by packing expected DS (data source) arguments into an array of type object or string. One of the following C# method overloads should be used.

Note: The version with type object is explicitly casted (internally) to string as the update command is serialized and sent to rrdtool for processing. The intent is to save you from having to explicitly cast (whenever possible). When not possible, you'll have use the string version. Aside from that, both methods are equivalent.

rrd1.update(920804700, new object[] { 12345 });
rrd1.update(920804700, new string[] { “12345” });
string[] args = new string[1];
args[0] = “12345”;
rrd1.update(920804700, args);

The (current) serialized update string can be retrieved by calling: “rrd1.CurrentUpdateStr” as in the example below:

Console.WriteLine("{0}", rrd1.CurrentUpdateStr); 

Resulting in the following console output…

rrdtool update test.rrd 920804700:12345 

Note: “CurrentUpdateStr” should be called after each call to “rrd1.update(…)” because serialization is done there.

RRDtool Graph Syntax

 rrdtool graph speed4.png                           
--start 920804400 --end 920808000               
--vertical-label km/h                           
HRULE:100#0000FF:"Maximum allowed"              
AREA:good#00FF00:"Good speed"                   
AREA:fast#550000:"Too fast"                     
STACK:over#FF0000:"Over speed"

NHawk(C#) Syntax Graph Syntax

GRAPH gr4 = new GRAPH("speed4.png", "920804400", "920808000");
gr4.yaxislabel = "km/h";
gr4.addDEF(new DEF("myspeed", rrd1, "speed", RRA.CF.AVERAGE));
gr4.addCDEF(new CDEF("kmh", "myspeed,3600,*"));
gr4.addCDEF(new CDEF("fast", "kmh,100,GT,kmh,0,IF"));
gr4.addCDEF(new CDEF("over", "kmh,100,GT,kmh,100,-,0,IF"));
gr4.addCDEF(new CDEF("good", "kmh,100,GT,0,kmh,IF"));
gr4.addGELEM(new HRULE("100", Color.Blue, "Maximum allowed"));
gr4.addGELEM(new AREA("good", Color.Green, "Good speed"));
gr4.addGELEM(new AREA("fast", Color.Brown, "Too fast"));
gr4.addGELEM(new AREA("over", Color.Red, "Over speed",true));


Note: The NHAWK code line:

gr4.addGELEM(new AREA("over", Color.Red, "Over speed",true));

is semantically equivalent to:

STACK:over#FF0000:"Over speed" 

NHAWK is using the newer syntactic constructs, as the STACK construct as a direct graphing element is deprecated as of RRDTool 1.3.

Architectural Features: Serialization and Deserialization and Deepcloning

All NHAWK constructs are built as composite structures, in which a contract states that each construct must be able to serialize, deserialize, and deepclone itself (see the UML architecture diagram available with the source download). In other words, a higher level construct (such as the GRAPH class) would serialize itself by asking all of its composed constructs to serialize themselves. This is a powerful feature in that it opens up a whole new level of functionality. This includes the generation and interoperation with (native) RRDTool script, as well as ease of use with service orientated architectures such as web service applications. Below we illustrate with an example for the GRAPH class.

GRAPH gr5 = new GRAPH(gr4.ToString(), ".\\"); 
Console.WriteLine("{0}", gr5.ToString());

The above code snippet performs the following operations:

  1. graph object g4 is serialized and passed to the GRAPH class deserialization (promotion) constructor.
  2. graph object g5 is instantiated by deserialing the serialized (string) form of object g4.
  3. object g5 is serialized and written to the console as shown below…
    graph speed4.png --start 920804400 --end 920808000 
    --vertical-label "km/h"
    HRULE:100#0000FF:"Maximum allowed" 
    AREA:good#008000:"Good speed" 
    AREA:fast#A52A2A:"Too fast" 
    AREA:over#FF0000:"Over speed" 

DeepCloning and Why NHawk Has It

GRAPH gr6 = GRAPH.DeepClone(gr5);
Console.WriteLine("\n{0}", gr6.ToString());

Above object gr6 is a (new memory) copy of gr5. Essentially, NHawk is really just a whole load of parsing, and therefore every aggregated class member is either a string or a value type. Value types are deep copied by default, and although string is a reference type, NHawk uses temporary StringBuilders to return newly constructed (new memory) string objects. This could prove useful in many circumstances as it provides for limited preservation of object identity in a object model (shallow reference) which works on premise of not having object identity. Finally, just for completeness, the below code snippet illustrates the usual shallow copy.

GRAPH gr7 = gr6;

Current Code Base Progress: Revision: 1.0

DEF (Graph Definitions) == 100%
CDEF (Graph Calc Definitions) == 100%

RRD (Defining, creating, and loading existing Round Robin Database files).
DS (data source) == 100%
RRA (round robin archives) == 100%

LINE == 100%
AREA == 100%
VRULE == 100%
HRULE == 100%
SHIFT == 100%

GRAPH == 90% (approx. needs VDEF, PRINT Elements)

Current TODO List (for features I plan to implement next).
Timeline: 2-4 weeks. Note: Once the list below is completed, tested and added what’s already be done, then the vast majority of the major rrdtool features will be complete. This is a very do-able project.

  • VDEF
  • PRINT Elements
  • RRDFetch

Compilation Instructions and Library Usage

See the user manual included with the source download.

Getting Started

For a quick start, see the tutorial (included with the source) located in: "NHawk\tutorials\rrdtutorial.en.html".
The source code can be compiled and executed from folder: "NHawk\tutorials\rrdtutorial1_code".

RRDtool can be downloaded from
A good site for Windows and Netware Binaries is
(latest ==

Author Contact Details

Michael Corley


  • 22 August 08 -- Posted revision 1.0
  • 26 May 2010 -- No new features yet... fixed CLS compliancy issue


This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


About the Author

Mike Corley
Software Developer (Senior)
United States United States
No Biography provided

You may also be interested in...


Comments and Discussions

QuestionERROR: failed to load /fonts/DejaVuSansMono-Roman.ttf Pin
hesuruio3-Dec-14 5:46
memberhesuruio3-Dec-14 5:46 
QuestionGraph refreshing Pin
Member 1033954520-Oct-13 22:09
memberMember 1033954520-Oct-13 22:09 
GeneralMy vote of 5 Pin
XAOCDOBRA6-Dec-12 3:31
memberXAOCDOBRA6-Dec-12 3:31 
Questionsomeone already found this bug Pin
Andres9012516-Apr-12 8:01
memberAndres9012516-Apr-12 8:01 
AnswerRe: someone already found this bug Pin
hesuruio3-Dec-14 5:41
memberhesuruio3-Dec-14 5:41 
QuestionAlways wrong with project "rrdtutorial1" in VS2008 Pin
zbc1236917-Oct-11 21:54
memberzbc1236917-Oct-11 21:54 
AnswerRe: Always wrong with project "rrdtutorial1" in VS2008 Pin
hesuruio3-Dec-14 5:43
memberhesuruio3-Dec-14 5:43 
QuestionVB.NET 2010 Express ERROR: failed to parse data source 600:Non Pin
Member 766308610-Feb-11 23:46
memberMember 766308610-Feb-11 23:46 
AnswerRe: VB.NET 2010 Express ERROR: failed to parse data source 600:Non Pin
Adel Khalil1-Jul-14 0:14
memberAdel Khalil1-Jul-14 0:14 
GeneralRe: VB.NET 2010 Express ERROR: failed to parse data source 600:Non Pin
Adel Khalil1-Jul-14 0:31
memberAdel Khalil1-Jul-14 0:31 
GeneralFxCop Pin
Daniel D.C.3-Oct-10 17:00
memberDaniel D.C.3-Oct-10 17:00 
QuestionAvoid Averaging in the Graph? Pin
GrossmeisterG3-Aug-10 3:45
memberGrossmeisterG3-Aug-10 3:45 
AnswerRe: Avoid Averaging in the Graph? Pin
Mike Corley4-Aug-10 8:29
memberMike Corley4-Aug-10 8:29 
GeneralUpdate a specific data source within an RRD file Pin
Joss#8-Jun-10 9:50
memberJoss#8-Jun-10 9:50 
GeneralRe: Update a specific data source within an RRD file Pin
Mike Corley8-Jun-10 12:04
memberMike Corley8-Jun-10 12:04 
GeneralRe: Update a specific data source within an RRD file Pin
Joss#8-Jun-10 17:28
memberJoss#8-Jun-10 17:28 
GeneralC# Failed To Parse DataSource.... Pin
aaaaaetetet29-May-10 1:15
memberaaaaaetetet29-May-10 1:15 
GeneralRe: C# Failed To Parse DataSource.... Pin
Mike Corley29-May-10 4:44
memberMike Corley29-May-10 4:44 
GeneralRe: C# Failed To Parse DataSource.... Pin
aaaaaetetet29-May-10 22:42
memberaaaaaetetet29-May-10 22:42 
GeneralRe: C# Failed To Parse DataSource.... Pin
motz198829-May-10 23:04
membermotz198829-May-10 23:04 
well done .. rrdtool is creating png-files Smile | :)

my changes:

DS.cs - Method "ToString()"
// --< serializes the data source to a string >--
public override string ToString()
    string local_min = (min.ToString() != Double.NaN.ToString()) ? min.ToString() : "U";
    string local_max = (max.ToString() != Double.NaN.ToString()) ? max.ToString() : "U";
    return "DS:" + name + ":" + DSType.ToString() + ":" + heartbeat + ":" + local_min + ":" + local_max;

RRD.cs - Method "load(string rrd_filename)" - added 2 if statements after defining min & max while parsing out data source list
public static RRD load(string rrd_filename)
	//rrdtool dump filename.rrd >filename.xml
   if (!File.Exists(rrd_filename))
		throw new RRDFileNotFoundException("The RRD File: " + rrd_filename + " could not be found");
	RRD rrd = null;
	Stream data_stream = null;
	string version = "not determined";
		data_stream = GetRRDFileAsStream(rrd_filename);
		XmlDocument rrd_doc = new XmlDocument();
		version = rrd_doc.DocumentElement.ChildNodes[0].InnerText.Trim();
		rrd = new RRD(rrd_filename, GetStartTimeFromRRD(rrd_filename), long.Parse(rrd_doc.DocumentElement.ChildNodes[1].InnerText.Trim()));
		//parse out data source list
		XmlNodeList ds_list = rrd_doc.GetElementsByTagName("ds");
		foreach (XmlNode ds_node in ds_list)
			if ((ds_node.ChildNodes.Count == 9) && (ds_node.HasChildNodes) && (ds_node.FirstChild.Name == "name"))
				string min = ds_node.ChildNodes[3].InnerText.Trim();
				string max = ds_node.ChildNodes[4].InnerText.Trim();
				if (min.ToLower().Equals("nan")) min = Double.NaN.ToString();
				if (max.ToLower().Equals("nan")) max = Double.NaN.ToString();
				rrd.addDS(new DS(ds_node.ChildNodes[0].InnerText.Trim(),
		//parse of the RRA list
		XmlNodeList rra_list = rrd_doc.GetElementsByTagName("rra");
		foreach (XmlNode rra in rra_list)
			// if (rra.ChildNodes.Count == 5)
			rrd.addRRA(new RRA(RRA.StringToCF(rra.ChildNodes[0].InnerText.Trim()),
	catch (Exception ex)
		if (ex is RRAFormatException || ex is DSFormatException || ex is RRDFormatException)
			throw new RRDFormatException("Could not load RRD file: " + rrd_filename + "version: " + version, ex);
		if (data_stream != null)
   return rrd;

GRAPH.cs - Method "ToString()" - yupperlimit & ylowerlimit
public override string ToString()
    StringBuilder def_list_builder = new StringBuilder();
    StringBuilder cdef_list_builder = new StringBuilder();
    StringBuilder elem_list_builder = new StringBuilder();
    foreach (DEF def in _def_list)
        def_list_builder.Append(" " + def.ToString());
    foreach (CDEF cdef in _cdef_list)
        cdef_list_builder.Append(" " + cdef.ToString());
    foreach (IGRAPH_ELEMENT elem in _elem_list)
        elem_list_builder.Append(" " + elem.ToString());
    string unitslen   = (units_length != int.MaxValue)   ? " --units-length "   + units_length.ToString() : ""; 
    string unitsexp   = (units_exponent != int.MaxValue) ? " --units-exponent " + units_exponent.ToString() : "";
    string z          = (zoom != int.MaxValue)           ? " --zoom " + zoom : "";                  
    string altygrid   = (alt_y_grid)             ? " --alt-y-grid  " : "";
    string un_si      = (units_si)               ? " --units=si " : "";
    string log_scale  = (logarithmic)            ? " --logarithmic " : "";
    string fsize_mode = (full_size_mode)         ? " --full-size-mode " : "";
    string ngrid      = (no_gridfit)             ? " --no-gridfit " : "";
    string only_graph = (onlygraph)              ? " --only-graph "  : "";
    string auto       = (autoscale)              ? " --alt-autoscale " : "";
    string auto_min   = (autoscale_min)          ? " --alt-autoscale-min " : "";
    string auto_max   = (autoscale_max)          ? " --alt-autoscale-max " : "";
    string w          = (width > 0)              ? " --width " + width.ToString() : "";
    string s          = (step > 0)               ? " --step " + step.ToString() : "";
    string yupper     = (yupperlimit.ToString() != Double.NaN.ToString()) ? " --upper-limit " + yupperlimit.ToString() : "";
    string ylower     = (ylowerlimit.ToString() != Double.NaN.ToString()) ? " --lower-limit " + ylowerlimit.ToString() : "";
    string rig        = (rigid)                  ? " --rigid " : "";
    string h          = (height > 0)             ? " --height " + height.ToString() : "";
    string t          = (title != "")            ? " --title " + "\""+ title + "\"" : "";
    string yaxis      = (yaxislabel != "")       ? " --vertical-label " + "\"" + yaxislabel + "\"" : "";
    string xgridstr   = (xgrid_ToString() != "") ? " --x-grid " + xgrid_ToString() : xgrid_ToString();
    string ygridstr   = (ygrid_ToString() != "") ? " --y-grid " + ygrid_ToString() : ygrid_ToString();
    string options = " " + s + t + xgridstr + ygridstr + yaxis + yupper + ylower + rig + w + h + log_scale + un_si + z 
        + unitsexp + unitslen + altygrid + only_graph + auto + auto_min + auto_max + ngrid + fsize_mode;
    return "graph " + filename + " --start " + start + " --end " + end + options + 
        def_list_builder.ToString() + cdef_list_builder.ToString() + elem_list_builder.ToString();

i avoided using static strings in comparisons Smile | :)

hope it's not only useful for me...
in addition i've to say that i dont' use the whole functionallity of the Nhawk project ...

if other errors occour while using it ... i'll post it here Smile | :)
GeneralVB.NET Pin
Nicohutse26-May-10 2:27
memberNicohutse26-May-10 2:27 
GeneralRe: VB.NET Pin
Mike Corley26-May-10 4:09
memberMike Corley26-May-10 4:09 
GeneralRe: VB.NET Pin
Nicohutse26-May-10 20:43
memberNicohutse26-May-10 20:43 
QuestionColor & WPF Pin
heimdm21-Apr-10 8:52
memberheimdm21-Apr-10 8:52 
QuestionWhy not use librrd? Pin
DaveKolb10-Feb-10 11:46
memberDaveKolb10-Feb-10 11:46 
AnswerRe: Why not use librrd? Pin
Mike Corley11-Feb-10 8:05
memberMike Corley11-Feb-10 8:05 
GeneralRe: Why not use librrd? Pin
DaveKolb14-Feb-10 4:00
memberDaveKolb14-Feb-10 4:00 
GeneralRe: Why not use librrd? Pin
DaveKolb14-Feb-10 5:37
memberDaveKolb14-Feb-10 5:37 
GeneralRe: Why not use librrd? Pin
Mike Corley14-Feb-10 9:12
memberMike Corley14-Feb-10 9:12 
AnswerSmall bugfix - step parameter in RRD constructor Pin
red2paul23-Nov-09 23:52
memberred2paul23-Nov-09 23:52 
GeneralRe: Small bugfix - step parameter in RRD constructor Pin
Mike Corley24-Nov-09 9:59
memberMike Corley24-Nov-09 9:59 
GeneralExisting port of rrdtool to c#: rrdsharp (on SourceForge) Pin
I'm Chris18-Nov-09 0:21
memberI'm Chris18-Nov-09 0:21 
GeneralRe: Existing port of rrdtool to c#: rrdsharp (on SourceForge) Pin
Mike Corley24-Nov-09 10:32
memberMike Corley24-Nov-09 10:32 
GeneralRe: Existing port of rrdtool to c#: rrdsharp (on SourceForge) Pin
I'm Chris24-Nov-09 21:59
memberI'm Chris24-Nov-09 21:59 
GeneralRe: Existing port of rrdtool to c#: rrdsharp (on SourceForge) [modified] Pin
DaveKolb10-Feb-10 10:40
memberDaveKolb10-Feb-10 10:40 
GeneralRe: Existing port of rrdtool to c#: rrdsharp (on SourceForge) Pin
I'm Chris11-Feb-10 6:22
memberI'm Chris11-Feb-10 6:22 
GeneralIssues using NHawk under Ubuntu and OpenSuse Pin
ccdr10-Sep-09 4:44
memberccdr10-Sep-09 4:44 
GeneralRe: Issues using NHawk under Ubuntu and OpenSuse Pin
Mike Corley10-Sep-09 5:34
memberMike Corley10-Sep-09 5:34 
AnswerHiding the command prompts Pin
CylindricalMark8-Sep-09 0:10
memberCylindricalMark8-Sep-09 0:10 
GeneralRe: Hiding the command prompts Pin
Mike Corley8-Sep-09 3:02
memberMike Corley8-Sep-09 3:02 
GeneralRe: Hiding the command prompts Pin
CylindricalMark8-Sep-09 4:22
memberCylindricalMark8-Sep-09 4:22 
Generalcouple of newby questions Pin
tbhanson3-Jun-09 6:22
membertbhanson3-Jun-09 6:22 
GeneralRe: couple of newby questions Pin
Mike Corley3-Jun-09 7:28
memberMike Corley3-Jun-09 7:28 
GeneralRe: couple of newby questions Pin
tbhanson4-Jun-09 4:11
membertbhanson4-Jun-09 4:11 
GeneralRe: couple of newby questions Pin
Mike Corley4-Jun-09 7:24
memberMike Corley4-Jun-09 7:24 
GeneralRe: couple of newby questions Pin
tbhanson5-Jun-09 1:18
membertbhanson5-Jun-09 1:18 
GeneralRe: couple of newby questions Pin
Mike Corley5-Jun-09 7:17
memberMike Corley5-Jun-09 7:17 
GeneralRe: couple of newby questions Pin
tbhanson8-Jun-09 3:42
membertbhanson8-Jun-09 3:42 
GeneralRe: couple of newby questions Pin
tbhanson8-Jun-09 3:53
membertbhanson8-Jun-09 3:53 
GeneralRe: couple of newby questions Pin
tbhanson8-Jun-09 4:32
membertbhanson8-Jun-09 4:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.161018.1 | Last Updated 26 May 2010
Article Copyright 2008 by Mike Corley
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid