simplejson

package module
v2.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 23, 2022 License: MIT Imports: 14 Imported by: 0

README

simplejson

GitHub tag (latest by date) Codecov Test Go Report Card GitHub GoDoc

Basic Go implementation of a Grafana SimpleJSON server.

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

func (server *Server) GetRouter() (r *mux.Router)

GetRouter sets up an HTTP router. Useful if you want to hook other handlers to the HTTP Server.

func (*Server) Run

func (server *Server) Run(port int) error

Run starts the SimpleJSon Server.

func (*Server) Shutdown

func (server *Server) Shutdown(ctx context.Context, timeout time.Duration) (err error)

Shutdown stops a running Server.

func (Server) Targets

func (server Server) Targets() (targets []string)

Targets returns a sorted list of supported targets

type TableQueryFunc

type TableQueryFunc func(ctx context.Context, args query.Args) (*query.TableResponse, error)

TableQueryFunc handles for table queries

type TagKeysFunc

type TagKeysFunc func(ctx context.Context) []string

TagKeysFunc returns supported tag names

type TagValuesFunc

type TagValuesFunc func(ctx context.Context, key string) ([]string, error)

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

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL