Documentation ¶
Overview ¶
Package simplejson provides a Go implementation for Grafana's SimpleJSON datasource: https://grafana.com/grafana/plugins/grafana-simple-json-datasource
Overview ¶
A simplejson server is an HTTP server that supports one or more handlers. Each handler can support multiple targets, each of which can be supported by a timeseries or table query. Optionally tag can be used to alter the behaviour of the query (e.g. filtering what data should be returned). Finally, a handler can support annotation, i.e. a set of timestamps with associated text.
Server ¶
To create a SimpleJSON server, create a Server and run it:
s := simplejson.Server{ Handlers: map[string]simplejson.Handler{ "my-target": myHandler, }, } err := s.Run(8080)
This starts a server, listening on port 8080, with one target "my-target", served by myHandler.
Handler ¶
A handler serves incoming requests from Grafana, e.g. queries, requests for annotations or tag. The Handler interface contains all functions a handler needs to implement. It contains only one function (Endpoints). This function returns the Grafana SimpleJSON endpoints that the handler supports. Those can be:
- Query() implements the /query endpoint for timeseries targets
- TableQuery() implements the /query endpoint for table targets
- Annotations() implements the /annotation endpoint
- TagKeys() implements the /tag-keys endpoint
- TagValues() implements the /tag-values endpoint
Here's an example of a handler that supports timeseries queries:
type myHandler struct { } func (handler myHandler) Endpoints() simplejson.Endpoints { return simplejson.Endpoints{ Query: handler.Query } } func (handler *myHandler) Query(ctx context.Context, target string, target *simplejson.Args) (response *simplejson.QueryResponse, err error) { // build response return }
Timeseries Queries ¶
Timeseries queries return values as a list of timestamp/value tuples. Here's an example of a timeseries query handler:
func (handler *myHandler) Query(_ context.Context, _ string, _ query.Args) (response *query.TimeSeriesResponse, err error) { response = &query.TimeSeriesResponse{ Target: "A", DataPoints: []query.DataPoint{ {Timestamp: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), Value: 100}, {Timestamp: time.Date(2020, 1, 1, 0, 1, 0, 0, time.UTC), Value: 101}, {Timestamp: time.Date(2020, 1, 1, 0, 2, 0, 0, time.UTC), Value: 103}, }, } return }
Table Queries ¶
Table Queries, on the other hand, return data organized in columns and rows. Each column needs to have the same number of rows:
func (handler *myHandler) TableQuery(_ context.Context, _ string, _ query.Args) (response *query.TableResponse, err error) { response = &query.TableResponse{ Columns: []query.Column{ { Text: "Time", Data: query.TimeColumn{time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), time.Date(2020, 1, 1, 0, 1, 0, 0, time.UTC)} }, { Text: "Label", Data: query.StringColumn{"foo", "bar"}}, { Text: "Series A", Data: query.NumberColumn{42, 43}}, { Text: "Series B", Data: query.NumberColumn{64.5, 100.0}}, }, } return }
Metrics ¶
simplejson exports two Prometheus metrics for performance analytics:
simplejson_query_duration_seconds: duration of query requests by target, in seconds simplejson_query_failed_count: number of failed query requests
Other topics ¶
For information on query arguments, annotations and tags, refer to the documentation for those data structures.
Example ¶
package main import ( "context" "github.com/clambin/simplejson/v2" "github.com/clambin/simplejson/v2/query" "time" ) type handler struct{} func (h handler) Endpoints() simplejson.Endpoints { return simplejson.Endpoints{ Query: h.Query, TableQuery: h.TableQuery, } } func (h *handler) Query(_ context.Context, _ query.Args) (response *query.TimeSeriesResponse, err error) { response = &query.TimeSeriesResponse{ DataPoints: make([]query.DataPoint, 60), } timestamp := time.Now().Add(-1 * time.Hour) for i := 0; i < 60; i++ { response.DataPoints[i] = query.DataPoint{ Timestamp: timestamp, Value: int64(i), } timestamp = timestamp.Add(1 * time.Minute) } return } func (h *handler) TableQuery(_ context.Context, _ query.Args) (response *query.TableResponse, err error) { timestamps := make(query.TimeColumn, 60) seriesA := make(query.NumberColumn, 60) seriesB := make(query.NumberColumn, 60) timestamp := time.Now().Add(-1 * time.Hour) for i := 0; i < 60; i++ { timestamps[i] = timestamp seriesA[i] = float64(i) seriesB[i] = float64(-i) timestamp = timestamp.Add(1 * time.Minute) } response = &query.TableResponse{ Columns: []query.Column{ {Text: "timestamp", Data: timestamps}, {Text: "series A", Data: seriesA}, {Text: "series B", Data: seriesB}, }, } return } func main() { s := simplejson.Server{ Handlers: map[string]simplejson.Handler{ "A": &handler{}, }, } _ = s.Run(8088) }
Output:
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AnnotationsFunc ¶
type AnnotationsFunc func(name, query string, args annotation.Args) ([]annotation.Annotation, error)
AnnotationsFunc handles requests for annotation
type Endpoints ¶
type Endpoints struct { Query TimeSeriesQueryFunc // /query endpoint: handles timeSeries queries TableQuery TableQueryFunc // /query endpoint: handles table queries Annotations AnnotationsFunc // /annotation endpoint: handles requests for annotation TagKeys TagKeysFunc // /tag-keys endpoint: returns all supported tag names TagValues TagValuesFunc // /tag-values endpoint: returns all supported values for the specified tag name }
Endpoints contains the functions that implement each of the SimpleJson endpoints
type Handler ¶
type Handler interface {
Endpoints() Endpoints
}
Handler implements the different Grafana SimpleJSON endpoints. The interface only contains a single Endpoints() function, so that a handler only has to implement the endpoint functions (query, tablequery, annotation, etc.) that it needs.
type Server ¶
type Server struct { Name string Handlers map[string]Handler // contains filtered or unexported fields }
Server receives SimpleJSON requests from Grafana and dispatches them to the handler that serves the specified target.
func (*Server) GetRouter ¶
GetRouter sets up an HTTP router. Useful if you want to hook other handlers to the HTTP Server.
type TableQueryFunc ¶
TableQueryFunc handles for table queries
type TagKeysFunc ¶
TagKeysFunc returns supported tag names
type TagValuesFunc ¶
TagValuesFunc returns supported values for the specified tag name
type TimeSeriesQueryFunc ¶
type TimeSeriesQueryFunc func(ctx context.Context, args query.Args) (*query.TimeSeriesResponse, error)
TimeSeriesQueryFunc handles timeseries queries