guys- i just wanted to check in and tell you what i've been up to.
lately, i've been working a bit on the TinyOS project (http://www.tinos.net) building a sensor network monitoring program called TinyMON.
the TinyMON web page is at http://tinymon.cs.berkeley.edu/.i'm using this project to learn more about the right way to handle round-robin databases and graph them. with an emphasis on configurability and easy of use (which we currently don't have) and
minimal disk io.first off, i've learned a lot about how to make more elaborate graphs using rrdtool... that have gradient backgrounds, calculated max, min and last values, etc. you can see a tinymon graph example at
http://tinymon.cs.berkeley.edu/examples/example.gif here is a clip of the PHP code used to create it... ---------------------------- start clip ----------------------------- return array("DEF:min=$rrd_target:min:MIN", "DEF:avg=$rrd_target:avg:AVERAGE", "DEF:max=$rrd_target:max:MAX", "DEF:readings=$rrd_target:readings:AVERAGE", "DEF:missed=$rrd_target:missed:AVERAGE", "CDEF:percent_missed=readings,missed,+,missed,/", "CDEF:10_percent_missed=percent_missed,10,LE,INF,UNKN,IF", "CDEF:20_percent_missed=percent_missed,10,GT,percent_missed,20,LE,+,2,EQ,INF,UNKN,IF", "CDEF:30_percent_missed=percent_missed,20,GT,percent_missed,30,LE,+,2,EQ,INF,UNKN,IF", "CDEF:40_percent_missed=percent_missed,30,GT,percent_missed,40,LE,+,2,EQ,INF,UNKN,IF", "CDEF:50_percent_missed=percent_missed,40,GT,percent_missed,50,LE,+,2,EQ,INF,UNKN,IF", "CDEF:60_percent_missed=percent_missed,50,GT,percent_missed,60,LE,+,2,EQ,INF,UNKN,IF", "CDEF:70_percent_missed=percent_missed,60,GT,percent_missed,70,LE,+,2,EQ,INF,UNKN,IF", "CDEF:80_percent_missed=percent_missed,70,GT,percent_missed,80,LE,+,2,EQ,INF,UNKN,IF", "CDEF:90_percent_missed=percent_missed,80,GT,percent_missed,90,LE,+,2,EQ,INF,UNKN,IF", "CDEF:100_percent_missed=percent_missed,90,GT,INF,UNKN,IF", "CDEF:wipeout=min,avg,max,+,+,UN,INF,UNKN,IF", "AREA:10_percent_missed#ffffff: <10% loss", "AREA:20_percent_missed#eeeeee:10-<20% loss", "AREA:30_percent_missed#dddddd:20-<30% loss", "AREA:40_percent_missed#cccccc:30-<40% loss", "AREA:50_percent_missed#bbbbbb:40-<50% loss", "COMMENT:\\l", "AREA:60_percent_missed#aaaaaa:50-<60% loss", "AREA:70_percent_missed#999999:60-<70% loss", "AREA:80_percent_missed#888888:70-<80% loss", "AREA:90_percent_missed#777777:80-<90% loss", "AREA:100_percent_missed#666666: >90% loss", "AREA:wipeout#ff0000:No data", "COMMENT:\\l", "COMMENT:\\c", "LINE3:max#00ff00:Maximum", "GPRINT:max:MAX:%12.2lf", "COMMENT: $sf_port\\l", "LINE3:avg#000000:Average", "GPRINT:avg:AVERAGE:%12.2lf", "COMMENT: $group_mote\\l", "LINE3:min#0000ff:Minumum", "GPRINT:min:MIN:%12.2lf", "COMMENT: starting $rrd_start ending $rrd_end\\l", "COMMENT:Last value", "GPRINT:avg:LAST:%11.2lf", "COMMENT: TinyMON graph generated $now\\l"); ------------------------ end clip ----------------------------------i looked everywhere (the rrdtool.org gallery had examples but not one had code) for how to do background gradients but i finally figured it out. i'm posting it here in the hope it might be useful to someone else.
the trick is defining some CDEFS to be either UNKN or INF. an infinite value will be graphed to the top of edge of the image and an UNKN will not be graphed in an AREA at all. if you can easily read reverse polish notation you'll see the GT (greater than), LE (less than or equal), + (addition) and IF (condition) operators in action.
for example 90_percent_missed=percent_missed,80,GT,percent_missed,90,LE,+,2,EQ,INF,UNKN,IFjust says if( value <= 90 && value > 80 ) set background to INF otherwise set it to UNKN.
i then set the color of 90_percent_missed values in the AREA option later.another trick that i learned is how to employ apache handlers to handle round-robin databases. this is explained on the tinymon web site.
you just have to drop the following options into apache AddIcon /icons/rrd.png .rrd AddDescription "Round Robin Database" .rrd AddHandler rrd-handler rrd Action rrd-handler /TinyMON/tinymon.phpand anytime that a person wants to view a .rrd file the handler is called (/TinyMON/tinymon.php) to display it. it works great.
the handler gets server variables that express the full path to the rrd that it should handle and the URL it was called from. the URL can be used to express the data partitions (also on the web page).
so the filesystem would be layed out as such... ./sf=localhost ./sf=localhost/port=9001 ./sf=localhost/port=9001/group=36 ./sf=localhost/port=9001/group=36/mote=2 ./sf=localhost/port=9001/group=36/mote=2/adc_channel=0 ./sf=localhost/port=9001/group=36/mote=2/adc_channel=0/data.rrd ./sf=localhost/port=9001/group=36/mote=2/adc_channel=1 ./sf=localhost/port=9001/group=36/mote=2/adc_channel=1/data.rrd ./sf=localhost/port=9001/group=36/mote=2/adc_channel=2 ./sf=localhost/port=9001/group=36/mote=2/adc_channel=2/data.rrd ./sf=localhost/port=9001/group=36/mote=2/adc_channel=3 ./sf=localhost/port=9001/group=36/mote=2/adc_channel=3/data.rrd ./sf=localhost/port=9001/group=36/mote=2/adc_channel=4 ./sf=localhost/port=9001/group=36/mote=2/adc_channel=4/data.rrd ./sf=localhost/port=9001/group=36/mote=2/adc_channel=5 ./sf=localhost/port=9001/group=36/mote=2/adc_channel=5/data.rrd ./sf=localhost/port=9001/group=36/mote=3 ./sf=localhost/port=9001/group=36/mote=3/adc_channel=0 ./sf=localhost/port=9001/group=36/mote=3/adc_channel=0/data.rrd ./sf=localhost/port=9001/group=36/mote=3/adc_channel=1 ./sf=localhost/port=9001/group=36/mote=3/adc_channel=1/data.rrd ./sf=localhost/port=9001/group=36/mote=3/adc_channel=2 ./sf=localhost/port=9001/group=36/mote=3/adc_channel=2/data.rrd ./sf=localhost/port=9001/group=36/mote=3/adc_channel=3 ./sf=localhost/port=9001/group=36/mote=3/adc_channel=3/data.rrd ./sf=localhost/port=9001/group=36/mote=3/adc_channel=4 ./sf=localhost/port=9001/group=36/mote=3/adc_channel=4/data.rrd ./sf=localhost/port=9001/group=36/mote=3/adc_channel=5 ./sf=localhost/port=9001/group=36/mote=3/adc_channel=5/data.rrdso that when the handler is called for a particular round-robin database, it knows exactly what the data refers to.
having this consistent namespace is important for us. you can also specify GET variable to alter the way the data is presented.
for example... ./sf=localhost/port=9001/group=36/mote=3/adc_channel=0/data.rrd?action="xport"will cause the raw data to be expressed in xml instead of an image. this will make it easy for ganglia users to see the real data points that go into creating the graphs.
one last trick i use is that the filename of the rrd denotes the format of the rrd... so the handler can know exactly which graph template to use for different data types.
all the code for this is written and working for tinymon and i plan to incorporate it into ganglia's gmetad in the near future.
however, my main focus for ganglia is getting out 3.0.1 next week which will fix some of the bugs people are seeing. i plan on walking the bugzilla database and incorporating as many fixes as possible (that don't require major changes).
hope you guys have a great weekend. -matt -- PGP fingerprint 'A7C2 3C2F 8445 AD3C 135E F40B 242A 5984 ACBC 91D3' They that can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety. --Benjamin Franklin, Historical Review of Pennsylvania, 1759
signature.asc
Description: OpenPGP digital signature