simplejson

package module
v0.10.0 Latest Latest
Warning

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

Go to latest
Published: Jan 22, 2022 License: MIT Imports: 12 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 tags 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 tags. 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.TimeSeriesQueryArgs) (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, _ *simplejson.TimeSeriesQueryArgs) (response *simplejson.QueryResponse, err error) {
	response = &simplejson.QueryResponse{
		Target: "A",
		DataPoints: []simplejson.QueryResponseDataPoint{
			{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, _ *simplejson.TableQueryArgs) (response *simplejson.QueryResponse, err error) {
	response = &simplejson.TableQueryResponse{
		Columns: []simplejson.TableQueryResponseColumn{
			{ Text: "Time",     Data: simplejson.TableQueryResponseTimeColumn{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: simplejson.TableQueryResponseStringColumn{"foo", "bar"}},
			{ Text: "Series A", Data: simplejson.TableQueryResponseNumberColumn{42, 43}},
			{ Text: "Series B", Data: simplejson.TableQueryResponseNumberColumn{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, annotation and tags, refer to the documentation for those data structures.

Example
package main

import (
	"context"
	"github.com/clambin/simplejson"
	"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, _ *simplejson.TimeSeriesQueryArgs) (response *simplejson.TimeSeriesResponse, err error) {
	response = &simplejson.TimeSeriesResponse{
		DataPoints: make([]simplejson.DataPoint, 60),
	}

	timestamp := time.Now().Add(-1 * time.Hour)
	for i := 0; i < 60; i++ {
		response.DataPoints[i] = simplejson.DataPoint{
			Timestamp: timestamp,
			Value:     int64(i),
		}
		timestamp = timestamp.Add(1 * time.Minute)
	}
	return
}

func (h *handler) TableQuery(_ context.Context, _ *simplejson.TableQueryArgs) (response *simplejson.TableQueryResponse, err error) {
	timestamps := make(simplejson.TableQueryResponseTimeColumn, 60)
	seriesA := make(simplejson.TableQueryResponseNumberColumn, 60)
	seriesB := make(simplejson.TableQueryResponseNumberColumn, 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 = &simplejson.TableQueryResponse{
		Columns: []simplejson.TableQueryResponseColumn{
			{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 AdHocFilter

type AdHocFilter struct {
	Value     string `json:"value"`
	Operator  string `json:"operator"`
	Condition string `json:"condition"`
	Key       string `json:"key"`
}

AdHocFilter specifies the ad hoc filters, whose keys & values are returned by the /tag-key and /tag-values endpoints.

type Annotation

type Annotation struct {
	Time    time.Time
	Title   string
	Text    string
	Tags    []string
	Request AnnotationRequestDetails
}

Annotation response. The annotation endpoint returns a slice of these.

func (*Annotation) MarshalJSON

func (annotation *Annotation) MarshalJSON() (output []byte, err error)

MarshalJSON converts an Annotation to JSON.

type AnnotationRequest added in v0.10.0

type AnnotationRequest struct {
	AnnotationRequestArgs
	Annotation AnnotationRequestDetails `json:"annotation"`
}

AnnotationRequest is a request for annotation.

type AnnotationRequestArgs added in v0.10.0

type AnnotationRequestArgs struct {
	Args
}

AnnotationRequestArgs contains arguments for the Annotations endpoint.

type AnnotationRequestDetails added in v0.10.0

type AnnotationRequestDetails struct {
	Name       string `json:"name"`
	Datasource string `json:"datasource"`
	Enable     bool   `json:"enable"`
	Query      string `json:"query"`
}

AnnotationRequestDetails specifies which annotation should be returned.

type AnnotationsFunc

type AnnotationsFunc func(name, query string, args *AnnotationRequestArgs) ([]Annotation, error)

AnnotationsFunc handles requests for annotation

type Args

type Args struct {
	Range        Range `json:"range"`
	AdHocFilters []AdHocFilter
}

Args contains common arguments used by endpoints.

type DataPoint

type DataPoint struct {
	Timestamp time.Time
	Value     int64
}

DataPoint contains one entry returned by a Query.

func (*DataPoint) MarshalJSON

func (d *DataPoint) MarshalJSON() ([]byte, error)

MarshalJSON converts a DataPoint to JSON.

func (*DataPoint) UnmarshalJSON

func (d *DataPoint) UnmarshalJSON(input []byte) (err error)

UnmarshalJSON converts a JSON structure to a DataPoint.

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 QueryRequest added in v0.10.0

type QueryRequest struct {
	Targets []RequestTarget `json:"targets"`
	TimeSeriesQueryArgs
}

QueryRequest is a Query request. For each specified RequestTarget, the server will call the Query endpoint with the provided TimeSeriesQueryArgs.

type Range

type Range struct {
	From time.Time `json:"from"`
	To   time.Time `json:"to"`
}

Range specified a start and end time for the data to be returned.

type RequestTarget

type RequestTarget struct {
	Target string `json:"target"` // name of the target.
	Type   string `json:"type"`   // "timeserie" or "" for timeseries. "table" for table queries.
}

RequestTarget specifies the requested target name and type.

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 added in v0.10.0

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

Targets returns a sorted list of supported targets

type TableQueryArgs

type TableQueryArgs struct {
	Args
}

TableQueryArgs contains the arguments for a TableQuery.

type TableQueryFunc

type TableQueryFunc func(ctx context.Context, args *TableQueryArgs) (*TableQueryResponse, error)

TableQueryFunc handles for table queries

type TableQueryResponse

type TableQueryResponse struct {
	Columns []TableQueryResponseColumn
}

TableQueryResponse is returned by a TableQuery, i.e. a slice of TableQueryResponseColumn structures.

func (*TableQueryResponse) MarshalJSON

func (table *TableQueryResponse) MarshalJSON() (output []byte, err error)

MarshalJSON converts a TableQueryResponse to JSON.

type TableQueryResponseColumn

type TableQueryResponseColumn struct {
	Text string
	Data interface{}
}

TableQueryResponseColumn is a column returned by a TableQuery. Text holds the column's header, Data holds the slice of values and should be a TableQueryResponseTimeColumn, a TableQueryResponseStringColumn or a TableQueryResponseNumberColumn.

type TableQueryResponseNumberColumn

type TableQueryResponseNumberColumn []float64

TableQueryResponseNumberColumn holds a slice of number values (one per row).

type TableQueryResponseStringColumn

type TableQueryResponseStringColumn []string

TableQueryResponseStringColumn holds a slice of string values (one per row).

type TableQueryResponseTimeColumn

type TableQueryResponseTimeColumn []time.Time

TableQueryResponseTimeColumn holds a slice of time.Time values (one per row).

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 TimeSeriesQueryArgs

type TimeSeriesQueryArgs struct {
	Args
	// Interval      QueryRequestDuration `json:"interval"`
	MaxDataPoints uint64 `json:"maxDataPoints"`
}

TimeSeriesQueryArgs contains the arguments for a Query.

type TimeSeriesQueryFunc

type TimeSeriesQueryFunc func(ctx context.Context, args *TimeSeriesQueryArgs) (*TimeSeriesResponse, error)

TimeSeriesQueryFunc handles timeseries queries

type TimeSeriesResponse

type TimeSeriesResponse struct {
	Target     string      `json:"target"`     // name of the target
	DataPoints []DataPoint `json:"datapoints"` // values for the target
}

TimeSeriesResponse is returned by a Query.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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