-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathdashboard.go
129 lines (105 loc) · 5.13 KB
/
dashboard.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
Package grada is a simple DIY dashboard based on [Grafana](https://github.com/grafana) and the [Simple JSON Datasource plugin](https://github.com/grafana/simple-json-datasource).
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 and update
Simply run
go get -u github.com/christophberger/grada
*/
package grada
import (
"time"
)
// 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().
type Dashboard struct {
srv *server
}
// 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 GetDashboard() *Dashboard {
d := &Dashboard{}
d.srv = startServer()
return d
}
// 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 (d *Dashboard) CreateMetric(target string, timeRange, interval time.Duration) (*Metric, error) {
return d.CreateMetricWithBufSize(target, d.bufSizeFor(timeRange, interval))
}
// 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 (5*60*1) at least.
//
// Creating a metric for an existing target is an error. To replace a metric
// (which is rarely needed), call DeleteMetric first.
func (d *Dashboard) CreateMetricWithBufSize(target string, size int) (*Metric, error) {
return d.srv.metrics.Create(target, size)
}
// bufSizeFor takes a duration and a rate (number of data points per second)
// and returns the required ring buffer size.
// Used by CreateMetric().
func (d *Dashboard) bufSizeFor(timeRange, interval time.Duration) int {
if interval.Nanoseconds() >= timeRange.Nanoseconds() {
return 1
}
return int(timeRange.Nanoseconds() / interval.Nanoseconds())
}
// DeleteMetric deletes the metric for the given target from the server.
func (d *Dashboard) DeleteMetric(target string) error {
return d.srv.metrics.Delete(target)
}