Skip to content

Latest commit

 

History

History
205 lines (141 loc) · 6.45 KB

README.md

File metadata and controls

205 lines (141 loc) · 6.45 KB

Grada - A DIY dashboard based on Grafana

Create a DIY dashboard for all metrics generated by your code, using a Grafana dashboard as a frontend.

Whenever you have code that generates time series data (for example, the current CPU load, number of network connections, number of goroutines,...), you can feed this data to a Grafana panel with only a few lines of code.

"Time series data" in this context is nothing more but a floating-point value and a timestamp.

DIY Dashboard

Package grada is a simple DIY dashboard based on Grafana and the Simple JSON Datasource plugin.

The motivation behind Grada

Grada provides an easy way of monitoring any sort of time series data generated by your code. Whether you want to observe the number of active goroutines, the CPU load, the air temperature outside your house, or whatever data source you can think of - Grada makes it easy to turn that data into graphs, gauges, histograms, or tables.

Using Grafana as a dashboard server

I happened to stumble upon Grafana recently. Grafana is a highly configurable dashboard server for time series databases and other data sources. Quickly, an idea came to mind: Why not using this for any sort of data generated by my own code? And this is how Grada was born.

Now whenever you have some data that can be associated with a point in time, Grada can put this data into a dashboard.

How to use Grada

In a very dense overview:

* Create a new dashboard.
	* Set timeRange to the range that Grafana requests.
	* Set interval to the interval (in nanoseconds) in which your app delivers data points.
* Create one or more "Metric", e.g. metric1.
* Call metric1.Add(...) to add new data points as they appear.
* Start your app.
* Install and start Grafana.
* Create a Grafana dashboard.
	* Set the dashboard update interval to the one chosen
* Add a panel (for example, a gauge).
	* Set its datasource to the metrics created by your app. e.g. metric1, metric2, etc.
	* The data of the respective metric(s) should now begin to appear in the panel.

Details and sample code

For more details, see the blog article at https://appliedgo.net/diydashboard as well as the package API documentation below.

The article consists of a step-by-step setup of Grafana and a sample app that produces "fake" time series data.

Installation

  • Create a new project with go mod init
  • Write code that imports github.com/christophberger/grada
  • Run either go mod tidy or go mod download to fetch missing dependencies

Usage

type Count

type Count struct {
	N float64
	T time.Time
}

Count is a single time series data tuple, consisting of a floating-point value N and a timestamp T.

type Dashboard

type Dashboard struct {
}

Dashboard is the central data type of Grada.

Start by creating a new dashboard through GetDashboard().

Then create one or more metrics as needed using CreateMetric() or CreateMetricWithBufSize().

Finally, have your code add data points to the metric by calling Metric.Add() or Metric.AddWithTime().

func GetDashboard

func GetDashboard() *Dashboard

GetDashboard initializes and/or returns the only existing dashboard. This also starts the HTTP server that responds to queries from Grafana. Default port is 3001. Overwrite this port by setting the environment variable GRADA_PORT to the desired port number.

func (*Dashboard) CreateMetric

func (d *Dashboard) CreateMetric(target string, timeRange, interval time.Duration) (*Metric, error)

CreateMetric creates a new metric for the given target name, time range, and data update interval, and stores this metric in the server.

A metric is a named data stream for time series data. A Grafana dashboard panel connects to a data stream based on the metric name selected in the panel settings.

timeRange is the maximum time range the Grafana dashboard will ask for. This depends on the user setting for the dashboard.

interval is the (average) interval in which the data points get delivered.

The quotient of timeRange and interval determines the size of the ring buffer that holds the most recent data points. Typically, the timeRange of a dashboard request should be much larger than the interval for the incoming data.

Creating a metric for an existing target is an error. To replace a metric (which is rarely needed), call DeleteMetric first.

func (*Dashboard) CreateMetricWithBufSize

func (d *Dashboard) CreateMetricWithBufSize(target string, size int) (*Metric, error)

CreateMetricWithBufSize creates a new metric for the given target and with the given buffer size, and stores this metric in the server.

Use this method if you know how large the buffer must be. Otherwise prefer CreateMetric() that calculates the buffer size for you.

Buffer size should be chosen so that the buffer can hold enough items for a given time range that Grafana asks for and the given rate of data point updates.

Example: If the dashboards's time range is 5 minutes and the incoming data arrives every second, the buffer should hold 300 item (5601) at least.

Creating a metric for an existing target is an error. To replace a metric (which is rarely needed), call DeleteMetric first.

func (*Dashboard) DeleteMetric

func (d *Dashboard) DeleteMetric(target string) error

DeleteMetric deletes the metric for the given target from the server.

type Metric

type Metric struct {
}

Metric is a ring buffer of Counts. It collects time series data that a Grafana dashboard panel can request at regular intervals. Each Metric has a name that Grafana uses for selecting the desired data stream. See Dashboard.CreateMetric().

func (*Metric) Add

func (g *Metric) Add(n float64)

Add a single value to the Metric buffer, along with the current time stamp. When the buffer is full, every new value overwrites the oldest one.

func (*Metric) AddCount

func (g *Metric) AddCount(c Count)

AddCount adds a complete Count object to the metric data.

func (*Metric) AddWithTime

func (g *Metric) AddWithTime(n float64, t time.Time)

AddWithTime adds a single (value, timestamp) tuple to the ring buffer.