Cacti is a great tool for time-based visualization of data. Out-of-box functionality can leave something to be desired. Here is a stepwise tutorial for creating custom graphs of web server requests. Most of the instructions can be applied to other scenarios.
From a high-level you need to:
- Create a source of the (time-based) data which exists independent of Cacti
- Create a means of obtaining the data (Data Input Method)
- Assemble outputs of (2) into a Data Template
- Create Graph Template based on the values available in the Data Template
- Apply those to a Device, this creates a Data Source and set of graphs
Then after some time passes you will have some nice graphs to ogle at.
A real world example would be capturing requests-per-second statistics from Nginx. This technique would apply to any web server logs with a little massaging I guess. In this case, our Nginx server was not compiled with stub_status ability which might otherwise be used, so instead we fashion a shell script that can run on (each) web server and determine rps from the access log.
statsnginx is a rudimentary script that captures average rps in ranges of 10s, 1m and 5m ago.
Example of running and the output:
c10s:389 c1m:409 c5m:312
Next step, make this data available to cacti. I choose snmp MIB since snmpd is already running on our Nginx servers.
Just by adding this line to snmpd.conf and restarting can we see the data remotely (wrapped for clarity).
exec 184.108.40.206.4.1.5001.3 statsnginx
(note this exec syntax is broken after net-snmp-5.3.1 on FreeBSD anyway, so YMMV)
$ snmpget -v 1 -On -c public
.220.127.116.11.4.1.5001.3.101.1 = STRING: "c10s:275 c1m:274 c5m:230"
This part can be tricky to figure out the exact OID. Use snmpwalk if necessary, e.g.
$ snmpwalk -v 1 -On -c public
Create the cacti script in /opt/cacti/scripts/statsnginx.sh
OUTPUT=`snmpget -Ov -v 2c -c bitpushsnmp $1
echo $OUTPUT | sed -e 's/STRING: //' | sed -e 's/"//g'
Test it from the cacti server.
$ ./statsnginx.sh 192.168.1.117
c10s:190 c1m:192 c5m:152
Notice how the output has three fields of name:value pairs separated by spaces. These are what cacti likes.
Don’t make the mistake like I did of using name=value because it will make cacti think it’s a PARTIAL result..
Now we can move into cacti to make use of the script and data it provides.
Please see this helpful link to Cacti docs.
Go to the Cacti console and create a Data Input Method to tell Cacti how to call the script …
- Data Input methods
- Name: statsnginx
- Input Type: Script/Command
- Input String: <path_cacti>/scripts/statsnginx.sh <hostname>
Now you have Input Fields and Output Fields
Cacti wants you to provide these.
Since we are gathering data from a remote (to cacti server) host, need to give hostname as input
- Add an Input Field
- Name: hostname
- Field Order: 1
- Friendly Name: Hostname
Add an Output Field for each of the name:value pairs above (c10s, c1m, c5m)
- Field [Output]: c10s
- Friendly Name: Average requests/sec over last 10 seconds
- Update RRD File: checked
- Do this for the other two fields.
- Then Save once more
Now create the Data Template
- Data Template
- – Name: nginx – Requests
- Data Source
- Name: |host_description| – nginx – Requests
- Data Input Method: statsnginx (chosen from list)
- Data Source Items
- Internal Data Source Name: for each data point above (c60s, c1m, c5m) add all (output fields items from above)
This is a tricky part. You want all three data source items listed with appropriate min/max values (left at 0 in this case) and using GAUGE as the Data Source Type. Also make sure to select the appropriate Output Field from the list for each one.
Now create the Graph Template
- Template Name: nginx – Requests
- Title: |host_description| – nginx – Requests
- I changed Upper Limit to 10000 just to be sure.
Now add Graph Template Items one by one
e.g Data Source nginx – requests (c10s)
and so on. Give each one an appropriate type like area, stacked or line1.
You can use the Graph Template for ucd/net – Load Average as a reference since it has similar measures (1, 5 and 15m load average).