[HOWTO] Color coded percent utilization

If you figure out how to do something interesting/cool in Cacti and want to share it with the community, please post your experience here.

Moderators: Moderators, Developers

Post Reply
Cacti User
Posts: 91
Joined: Thu Jan 13, 2005 3:58 pm
Location: College Station, TX - USA

[HOWTO] Color coded percent utilization

#1 Post by jas0420 » Sun Jul 17, 2005 3:24 pm

UPDATE: I failed to mention below that I also had to modify the file rrd.php as documented by "KC" about midway down on this link: http://forums.cacti.net/viewtopic.php?t=3030

I wanted a quick way to skim through a group of similar graphs and have things needing attention jump out at me. I like using auto-scale graphs to see as much detail as possible. With it though, spikes are meaningless unless you take time to look at the scale on the left. OK for a couple of graphs, but if you want to look at the circuit utilization on 40 circuits, it gets to be more time consuming.

After 3 days of pulling my hair out fighting with data sources and CDEF's, I finally got this going. I'm using it for circuit utilization, but it could be massaged into pretty much anything. The example below isn't the most exciting... It's the weekend, so there's not much action on any of the circuits at the moment, but you can get an idea of what I mean.


Ok, so here's what I ultimately did... I've tried to make this as simple as possible so that anyone can follow it regardless of experience. (I've been a noob too!) That said, this is long.............

You need a lot of CDEF's, so let's do those first. It may be common knowledge, but I finally figured out the hard way that instead of hand building big long CDEF statements, you can just copy a string you've put together in Notepad (or wherever) into a single Custom String and shave a LOT of time off of the process. We'll do it that way.

1) Navigate to the CDEF section of Cacti
2) Click "Add"

1) Give the new CDEF a name. We'll call the first one "Bandwidth Percentage - 0 to 10%"
2) Click "Create"

1) We now have a new CDEF, but no formula defined. Click "Add" to enter a new statement.

1) Here's where the shortcut comes in. Change the CDEF Item Type to "Custom String".
2) Copy the string below and paste it into the "CDEF Item Value" field.

Code: Select all

3) Click "Create".

1) Notice that the CDEF formula has now updated.
2) Click "Save".

One down, 12 to go! Repeat the procedure above to create each of the CDEF statements below.

Name: Bandwidth Percentage - 10 to 20%

Code: Select all

Name: Bandwidth Percentage - 20 to 30%

Code: Select all

Name: Bandwidth Percentage - 30 to 40%

Code: Select all

Name: Bandwidth Percentage - 40 to 50%

Code: Select all

Name: Bandwidth Percentage - 50 to 60%

Code: Select all

Name: Bandwidth Percentage - 60 to 70%

Code: Select all

Name: Bandwidth Percentage - 70 to 80%

Code: Select all

Name: Bandwidth Percentage - 80 to 90%

Code: Select all

Name: Bandwidth Percentage - 90 to 100%

Code: Select all

Name: Percentage Bandwidth Utilization

Code: Select all

Name: Percentage Bandwidth Utilization In & Out

Code: Select all

This one may be part of Cacti's general install. Check if you have it first...
Name: Turn Bytes into Bits

Code: Select all


All right. That takes care of entering the CDEF's. Before we leave them completely though, I want to explain a couple of things... I tried hopelessly for many many hours trying to get various combinations of the special "All Data Sources, No Dup's" and "Similar Data Sources, No Dup's" to work. I could get close sometimes, but it never quite worked. I ultimately placed variables in the CDEF (Notice the two sets of "a" and "b" in the code below... That's them).

Code: Select all

These point to the data sources (Traffic_in and Traffic_Out) in the graph template. That in mind, it is important that if you go off and make your own graph template that you keep in mind the order that you enter your data sources. If you do something similar with 3 data sources for example, you will need to modify the CDEF to include a, b, and c. Or if you add a data source first that precedes two that you do want to be calculated, you'll need to change your variables in the CDEF from a & b to b & c. If this makes no sense to you, fear not... The graph template I used is included in this tutorial and it should not matter to you. Just keep this in mind if you venture off on your own!

Enough CDEF's. Onward!

Next you need to download the circ_util.xml attachment in this message and save it to a location of your choosing. We need to use it to import the graph template and save you a little work. I'm going to spare the details, but just go to the "Import/Export" section of Cacti's menu bar, select "Import Templates", browse to the folder you saved the file to, select "circ_util.xml", then click the "Save" button. You should see a screen showing the successful import.

Of note here... I have sorted my color pallet as per "byrons" guidelines here: http://forums.cacti.net/about6308.html&highlight=colors

Because of that, you'll probably get some wacky colors if you haven't done the same. It is not necessary to resort your colors, but you probably will want to go back into your new graph template and change the colors of each line into something that makes more sense. Mine looks like this:


If you know what you're doing, you should be able to manually make graphs at this point. I went ahead and made this part of the SNMP Interface Statistics Data Query though so that it is easily reachable when I'm adding new devices. Let's add that...

1) Select "Data Queries" from the menu.
2) Select "SNMP - Interface Statistics" from the options.

1) Select "Add" to add a new Associated Graph Template.

1) Give it a meaningful name. I chose "Circuit Utilization - Summary". This is what will show up in the drop-down menu when making new graphs.
2) Select the graph template. If you've imported mine, it should be called "Interface - Circuit Utilization Summary"
3) Select the "ifInOctets (Bytes In)" option from the drop-down to match this up with the "traffic_in" Data Source.
4) Select the "ifOutOctets (Bytes Out)" option from the drop-down to match this up with the "traffic_out" Data Source.
5) To help keep your Data Sources organized, give it a name here to make it recognizable and unique. I chose:

Code: Select all

|host_description| - Ckt Util - |query_ifName| 
6) Enter the key-word "name" here (no quotes).
7) Click the "Add" button.
8) Along similar lines as above, you will want for your graphs to have a meaningful and unique name. Enter as many titles as you'd like, but take note that Cacti always uses the one at the top of the list when making new graphs, so you may have to come back and re-sort these depending on your needs at the time. I added a ton, but chopped the list down to a couple for the screenshot below. In this case, I would go in and make new graphs from my "Atlanta B" router... Adding 10 - 15 VPN tunnels to this graph template. Each graph would be created called "Circuit Utilization Summary - Dixie to Atlanta "B" SomeTunnelName". I then go back in under Graph Management and change my generic "Dixie" to the appropriate city for each graph. So an example of what I entered here is:

Code: Select all

Circuit Utilization Summary - Dixie to Atlanta "B" |query_ifDescr| 
9) Enter the key-word "title" (again, no quotes) here.
10) Click "Add".
11) Once you have added all of the template names and graph titles that you need, click the "Save" button.

Now when you go to add a new device (or modify an existing one) and choose to "Create Graphs for this Host" you will see "Circuit Utilization - Summary" in your option of graphs to create assuming that you have chosen a Host Template ("Cisco Router", "Windows 2000/XP Host", etc.) that uses the "SNMP - Interface Statistics" Data Query to scan the host for interfaces that it has.

I'm pretty sure that encompasses everything that I did. I do have one last note though... In Cisco-world (and others, I'm sure) if you are doing this graph for tunnel interfaces (or other non-physical ones), you will need to modify the tunnel interface by adding the "bandwidth x" (where "x" is the speed of the circuit in kilobits... 1000 = 1Mb) line to each tunnel. I've used Cacti's |query_ifDescr| command extensively to obtain the bandwidth necessary for the math to calcualte the percentage used. Most physical interfaces should return a value to this request just fine w/o any extra work, but keep it in mind on tunnels and serial sub-interfaces.

I hope that you have found this useful! I need to throw in the disclaimer that this tutorial was written with the assistance of a few beers... I think I covered everything I did, but I will edit it accordingly if need-be.

Best of luck,
Graph template
(36.34 KiB) Downloaded 2682 times
Last edited by jas0420 on Tue Jul 19, 2005 6:19 am, edited 4 times in total.

User avatar
Posts: 14817
Joined: Tue May 14, 2002 5:08 pm
Location: MI, USA

#2 Post by TheWitness » Sun Jul 17, 2005 3:36 pm

kneeling at your feet 8)

True understanding begins only when we realize how little we truly understand...

Life is an adventure, let yours begin with Cacti!

Author of MacTrack, Boost, CLog, SpikeKill, Platform RTM, DSStats, maintainer of Spine, lot's of unpublished work and most of Cacti's bugs.
Official Cacti Documentation
GitHub Repository with Supported Plugins
Central Plugin Repository
Central Templates Repository

I'm still out there people. Getting excited for Cacti 1.2. I think it will be a great release.

User avatar
Posts: 26
Joined: Tue Aug 17, 2004 12:39 pm
Location: London

#3 Post by stevew » Mon Jul 18, 2005 5:36 pm

Awesome - I've just learnt quite a few very cool tricks.
[url=http://www.welham.net/]Steve W[/url]

Cacti User
Posts: 91
Joined: Thu Jan 13, 2005 3:58 pm
Location: College Station, TX - USA

#4 Post by jas0420 » Mon Jul 18, 2005 7:06 pm

Glad you liked it TheWitness & Steve. I learned a lot the past few days myself.

All, please note that I added an update to the instructions above. I'll add it again here too...

Sorry if it caused any grief.

UPDATE: I failed to mention below that I also had to modify the file rrd.php as documented by "KC" about midway down on this link: http://forums.cacti.net/viewtopic.php?t=3030

User avatar
Cacti User
Posts: 256
Joined: Wed Jan 14, 2004 3:23 am
Location: Germany

#5 Post by Pumpi » Tue Jul 19, 2005 2:43 am

Excellent work jas0420 !!!

:P :P :P :P :P

Cacti User
Posts: 142
Joined: Sat Jul 09, 2005 3:13 pm

#6 Post by flipflap » Tue Aug 02, 2005 8:08 am

i love noob guides!!! makes me wanna cry when i read guides like yours. somebody out there really cares for us noobs :P thanks dude

Cacti User
Posts: 91
Joined: Thu Jan 13, 2005 3:58 pm
Location: College Station, TX - USA

#7 Post by jas0420 » Tue Aug 02, 2005 12:36 pm

Heh! Hope it was useful, and glad to be of service...


Posts: 2
Joined: Wed Aug 24, 2005 8:23 am


#8 Post by faded » Wed Aug 24, 2005 8:41 am

I've got the graphing mentioned above working, but it seems to combine the input/output for an aggregate % utilization which ends up going over 100%, and could actually reach 200% since the connection is symmetrical and full duplex.


I haven't looked at the code much yet, but noticed this to be a problem. I will be looking into a way to graph input/output separate.

Posts: 37
Joined: Sun Aug 21, 2005 1:17 am


#9 Post by FPL_NMS » Sun Sep 04, 2005 1:25 am

Dude you rock!! that is all I have to say about your technical writting skills.

Now for some questions.
1.) After creating a graph for an existing device I get an error message under Graph management.
4 [main] rrdtool 1244 handle_exceptions: Exception: STATUS_ACCESS_VIOLATION
and no graph created

I believe I have followed your steps carefully. Please let me know where I may have gone wrong.


User avatar
Posts: 14817
Joined: Tue May 14, 2002 5:08 pm
Location: MI, USA

#10 Post by TheWitness » Sun Sep 04, 2005 7:43 am

What version of RRDtool? Please run a pass of viewing the graph in DEBUG mode from "Graph Management", and also post your CACTI2RRD line from the log file. Also, please TAR your RRD file(s) and attach as well.

Remember to change logging to LOW or NONE afterwards.

True understanding begins only when we realize how little we truly understand...

Life is an adventure, let yours begin with Cacti!

Author of MacTrack, Boost, CLog, SpikeKill, Platform RTM, DSStats, maintainer of Spine, lot's of unpublished work and most of Cacti's bugs.
Official Cacti Documentation
GitHub Repository with Supported Plugins
Central Plugin Repository
Central Templates Repository

I'm still out there people. Getting excited for Cacti 1.2. I think it will be a great release.

Posts: 7
Joined: Fri Jul 29, 2005 10:46 am
Location: MIlton Keynes, UK

#11 Post by SRY » Fri Sep 16, 2005 4:36 pm

I was asked at work to produce a color coded graph for our ops guys so that they could report when utilisation was over a certain level, but we needed to check if it was inbound or outbound traffic. we ended up using a three colour system for 0-50%, 50%-75% and 75%-100% but in keeping with this post I have shown it in 10% increments. The first attachment is what we ended up with for our pilot.

The second attachement is of our graph template, Items 1 to 12 are as per the original post and will show inbound traffic on the positive Y axis. Items 13 to 24 show the outbound on the negative Y axis. The CDEF for item 13 need to be set to negative values so it is.

b 8 * -1 * (negative bytes to bits rather than positive)

This produces the bits per second in the negative plane, and was already defined in my copy of cacti 0.8.6f. The following CDEFs are used to get correct color and values.


Positive Bandwidth Percentage 0-10%

Positive Bandwidth Percentage 10-20%

Positive Bandwidth Percentage 20-30%

Positive Bandwidth Percentage 30-40%

Positive Bandwidth Percentage 40-50%

Positive Bandwidth Percentage 50-60%

Positive Bandwidth Percentage 60-70%

Positive Bandwidth Percentage 70-80%

Positive Bandwidth Percentage 80-90%

Positive Bandwidth Percentage 90-100%


Negative Bandwidth Percentage 0-10%

Negative Bandwidth Percentage 10-20%

Negative Bandwidth Percentage 20-30%

Negative Bandwidth Percentage 30-40%

Negative Bandwidth Percentage 40-50%

Negative Bandwidth Percentage 50-60%

Negative Bandwidth Percentage 60-70%

Negative Bandwidth Percentage 70-80%

Negative Bandwidth Percentage 80-90%

Negative Bandwidth Percentage 90-100%

As an example the last attachement is how the item is defined in my graph template.

I hope this helps and make sense as I have downed several beers trying to work out how to post the graphics. I am a bit of a forum newbie!
Cacti_html_2822ad55.gif (14.53 KiB) Viewed 66721 times
Cacti_html_7a3f437e.gif (20.67 KiB) Viewed 66721 times
The graph is of a 2Mb circuit, you may want to add additional text and detail to the graph but this was our first pass so detail was minimal.
Cacti_html_m2e902751.gif (19.59 KiB) Viewed 66721 times

User avatar
Posts: 20
Joined: Thu Jan 06, 2005 8:09 am

#12 Post by cjennings_cr » Thu Sep 29, 2005 12:02 pm


I am a bit of a NOOB on CDEFs. Can you chug a quick beer and explain what these CDEFs are doing.

Here is what I gleem from CDEF documentation on the Internet, but am lost in the areas that I highlight below in RED:


...First Position: (((((a+B)/|query_ifSpeed|)*100)*8)<=20)
...Second Position: (((((a+B)/|query_ifSpeed|)*100)*8)>10)
...Third Position: NEGINF
...Fourth Position: UNKN
...Fifth Position: IF
...Sixth Position: UNKN
...Seventh Position: IF

My translation of this:

IF ((((a+B)/|query_ifSpeed|)*100)*8) <= 20 THEN
...IF ((((a+B)/|query_ifSpeed|)*100)*8) > 10 THEN

My question is what value are returned in different situations:

1) Both IFs are TRUE
2) Either IF is FALSE

Cacti User
Posts: 91
Joined: Thu Jan 13, 2005 3:58 pm
Location: College Station, TX - USA

#13 Post by jas0420 » Thu Sep 29, 2005 1:48 pm

I may have chugged a few too many beers since I last looked at all of this (I've had to back-burner the monitoring project for a few months), but I have fuzzy memories of wondering the same thing about the NEGINF function. I believe that I tried it without that and found that the graph looked as if you had flipped it vertically... Everything that is colored/plotted became white space, and all of what used to be white space became colored.

by my understanding, (and I'm the first to admit that I don't know much about CDEF's myself) if both IF's are true, it get's plotted (by whatever NEGINF is doing) and of course if either IF is not true, the whole function is false and no action is taken. In theory, the CDEF's are lined up in a way that there can not be a value that one (and only one) CDEF does in fact have both IF's match.

User avatar
Posts: 22375
Joined: Thu Dec 02, 2004 2:46 am
Location: Muenster, Germany

#14 Post by gandalf » Sat Oct 08, 2005 9:26 am

Import of this Graph Template went well. But graphs don't get generated. Graph Statement looks like
/usr/bin/rrdtool graph - \
--imgformat=PNG \
--start=-86400 \
--end=-300 \
--title="gandalf - Ckt Util - eth0" \
--base=1000 \
--height=120 \
--width=500 \
--alt-autoscale-max \
--lower-limit=0 \
--vertical-label="Percent" \
--slope-mode \
--font TITLE:12:/usr/share/fonts/bitstream-vera/VeraMoBI.ttf \
--font AXIS:8:/usr/share/fonts/bitstream-vera/Vera.ttf \
--font LEGEND:7:/usr/share/fonts/bitstream-vera/VeraMono.ttf \
--font UNIT:8:/usr/share/fonts/bitstream-vera/Vera.ttf \
DEF:a="/var/www/html/cacti-0.8.6f/rra/gandalf_traffic_in_82.rrd":traffic_in:LAST \
DEF:b="/var/www/html/cacti-0.8.6f/rra/gandalf_traffic_in_82.rrd":traffic_out:LAST \
CDEF:cdefa=a,100000000,/,100,*,8,* \
CDEF:cdefb=b,100000000,/,100,*,8,* \
CDEF:cdefc=a,b,+,100000000,/,100,*,8,*,10,LE,a,b,+,100000000,/,100,*,8,*,0,GT,NEGINF,UNKN,IF,UNKN,IF \
CDEF:cdefd=a,b,+,100000000,/,100,*,8,*,30,LE,a,b,+,100000000,/,100,*,8,*,20,GT,NEGINF,UNKN,IF,UNKN,IF \
CDEF:cdefe=a,b,+,100000000,/,100,*,8,*,50,LE,a,b,+,100000000,/,100,*,8,*,40,GT,NEGINF,UNKN,IF,UNKN,IF \
CDEF:cdeff=a,b,+,100000000,/,100,*,8,*,70,LE,a,b,+,100000000,/,100,*,8,*,60,GT,NEGINF,UNKN,IF,UNKN,IF \
CDEF:cdefg=a,b,+,100000000,/,100,*,8,*,90,LE,a,b,+,100000000,/,100,*,8,*,80,GT,NEGINF,UNKN,IF,UNKN,IF \
CDEF:cdefh=a,b,+,100000000,/,100,*,8,*,20,LE,a,b,+,100000000,/,100,*,8,*,10,GT,NEGINF,UNKN,IF,UNKN,IF \
CDEF:cdefi=a,b,+,100000000,/,100,*,8,*,40,LE,a,b,+,100000000,/,100,*,8,*,30,GT,NEGINF,UNKN,IF,UNKN,IF \
CDEF:cdefj=a,b,+,100000000,/,100,*,8,*,60,LE,a,b,+,100000000,/,100,*,8,*,50,GT,NEGINF,UNKN,IF,UNKN,IF \
CDEF:cdefba=a,b,+,100000000,/,100,*,8,*,80,LE,a,b,+,100000000,/,100,*,8,*,70,GT,NEGINF,UNKN,IF,UNKN,IF \
CDEF:cdefbb=a,b,+,100000000,/,100,*,8,*,5000,LE,a,b,+,100000000,/,100,*,8,*,90,GT,NEGINF,UNKN,IF,UNKN,IF \
CDEF:cdefbe=a,8,* \
CDEF:cdefce=b,8,* \
:cdefc#3ACE0C:" 0 - 10%":STACK \
:cdefd#99FF99:"20 - 30%":STACK \
:cdefe#FFFF00:"40 - 50%":STACK \
:cdeff#FF8C1A:"60 - 70%":STACK \
:cdefg#FF3333:"80 - 90%\n":STACK \
:cdefh#00FF00:"10 - 20%":STACK \
:cdefi#FFFF80:"30 - 40%":STACK \
:cdefj#FFA54C:"50 - 60%":STACK \
:cdefba#FF5F00:"70 - 80%":STACK \
:cdefbb#FF0000:"90 - 100%\n":STACK \
COMMENT:"CIRCUIT SPEED\: 100000000 bits per second\n" \
GPRINT:cdefbe:AVERAGE:" Avg\:%8.2lf%s" \
GPRINT:cdefbe:MIN:"Min\:%8.2lf%s" \
GPRINT:cdefbe:MAX:"Max\:%8.2lf%s" \
GPRINT:cdefbe:LAST:"Current\:%8.2lf%s\n" \
GPRINT:cdefa:AVERAGE:" Avg\:(%5.2lf %%)" \
GPRINT:cdefa:MIN:"Min\:(%5.2lf %%)" \
GPRINT:cdefa:MAX:"Max\:(%5.2lf %%)" \
GPRINT:cdefa:LAST:"Current\:(%5.2lf %%)\n" \
GPRINT:cdefce:AVERAGE:"Avg\:%8.2lf%s" \
GPRINT:cdefce:MIN:"Min\:%8.2lf%s" \
GPRINT:cdefce:MAX:"Max\:%8.2lf%s" \
GPRINT:cdefce:LAST:"Current\:%8.2lf%s\n" \
GPRINT:cdefb:AVERAGE:" Avg\:(%5.2lf %%)" \
GPRINT:cdefb:MIN:"Min\:(%5.2lf %%)" \
GPRINT:cdefb:MAX:"Max\:(%5.2lf %%)" \
GPRINT:cdefb:LAST:"Current\:(%5.2lf %%)\n" \
COMMENT:" Inbound\: 155.09 KB" \
COMMENT:"Outbound\: 177.04 KB"
and is weird, of course. Graph Debug says
ERROR: Could not make sense out of ':cdefc#3ACE0C: 0 - 10%:STACK'
which is not astonishing. Fiddled around a bit with this graph template, but to no avail.
System data is
Linux 2.6.9-5.EL #1 Wed Jan 5 19:22:18 EST 2005 i686 GNU/Linux
cacti 0.8.6g
CACTID 0.8.6f Copyright 2002-2005 by The Cacti Group
PHP 4.3.9 (cgi) (built: Aug 17 2005 10:22:19)
Copyright (c) 1997-2004 The PHP Group
Zend Engine v1.3.0, Copyright (c) 1998-2004 Zend Technologies
RRDtool 1.2.11 Copyright 1997-2005 by Tobias Oetiker <[email protected]>
mysql Ver 14.7 Distrib 4.1.10a, for redhat-linux-gnu (i386)
gcc (GCC) 3.4.3 20050227 (Red Hat 3.4.3-22.1)
I did not apply the patches you are referring to (kc), because the other thread says, that they are incorporated in this cacti release, or am I not right?

Allen K
Posts: 22
Joined: Sat Oct 15, 2005 9:34 pm

#15 Post by Allen K » Fri Oct 21, 2005 3:14 am

same results. has anyone else had luck with this? I've been playing with it for a while now and can't seem to get it working.

Post Reply