A 10 minutes walk into Grafana & Influxdb
This is a 10 minute tutorial to set up an InfluxDB + Grafana with Go on your Mac, but should work with minor modifcations on your favorite Unix too, it assumes you already have a working Go compiler.
InfluxDB is a database specialized into time series, think store everything associated with a time, makes it perfect for monitoring and graphing values. Grafana is a js frontend capable of reading the data from InfluxDB and graphing it.
brew install influxdb
Start InfluxDB, and then point your browser to http://localhost:8083 default user is root, password is root and default port is 8086.
influxdb -config /usr/local/etc/influxdb.conf
Create a database called test.
Let’s test the connection with the db and Go, first install the InfluxDB driver for Go:
go get github.com/influxdb/influxdb/client
Test your setup with some code:
package main
import (
"fmt"
"github.com/influxdb/influxdb/client"
)
func main() {
c, err := client.NewClient(&client.ClientConfig{
Username: "root",
Password: "root",
Database: "test",
})
if err != nil {
panic(err)
}
dbs, err := c.GetDatabaseList()
if err != nil {
panic(err)
}
fmt.Println(dbs)
}
If you are good you should see a map containing all your created InfluxDB databases.
Now let’s measure something real: the time it takes for your http handler to answer.
package main
import (
"fmt"
"log"
"math/rand"
"net/http"
"time"
"github.com/influxdb/influxdb/client"
)
var c *client.Client
func mySuperFastHandler(rw http.ResponseWriter, r *http.Request) {
start := time.Now()
// sleeping some random time
rand.Seed(time.Now().Unix())
i := rand.Intn(1000)
time.Sleep(time.Duration(time.Duration(i) * time.Millisecond))
fmt.Fprintf(rw, "Waiting %dms", i)
t := time.Since(start)
// sending the serie
s := &client.Series{
Name: "myhostname.nethttp.mySuperFastHandler.resp_time",
Columns: []string{"duration", "code", "url", "method"},
Points: [][]interface{}{
[]interface{}{int64(t / time.Millisecond), 200, r.RequestURI, r.Method},
},
}
err := c.WriteSeries([]*client.Series{s})
if err != nil {
log.Println(err)
}
}
func main() {
var err error
c, err = client.NewClient(&client.ClientConfig{
Username: "root",
Password: "root",
Database: "test",
})
if err != nil {
panic(err)
}
http.HandleFunc("/", mySuperFastHandler)
http.ListenAndServe(":8080", nil)
}
This is not very useful as it’s measuring the time to write to the ResponseWriter that’s why I’ve added some random time but you get the sense. It will save a serie per request as: duration, status code, url, http method, the name of the serie is important as many tools (as Graphite) are using the dots as separator, so think twice before naming your serie. Point your browser to http://localhost:8080 and reload the page several times.
Now that we have data let’s browse them with the InfluxDB browser, go to the InfluxDB admin and hit “explore data” and select with:
SELECT duration FROM myhostname.nethttp.mySuperFastHandler.resp_time WHERE code = 200;
You should be able to see the inserted data points.
Now let’s work with Grafana, download the tar gz, uncompress it somewhere, copy this demo config.js file in the root directory of Grafana. Go to the InfluxDB admin with your browser and add a new database called “grafana”.
In your web browser, open the file index.html in the Grafana directory, you should see a the Grafana interface edit the default graph, enter the query as follow:
- click on series it will complete with myhostname.nethttp.mySuperFastHandler.resp_time
- In alias type $0 $2, it will use the 1st part and the 3rd part of the name (remember the dots) so it will display myhostname mySuperFastHandler
- Finally click on mean and choose duration in the completion, then add code = 200 as where clause.
Hit save and you are done !
There is so much more you can do with InfluxDB & Grafana, it’s really simple to collect and display, hope you want to go further after this. You can look at my [generic net/http handler for InfluxDB on Github](https://github.com/akhenakh/influxhandler) that can be integrated into your code.