Add a router or multiplexer to query different data types
The QueryData
method in your plugin's backend allows you to query one type of data only. To support different kinds of queries (metrics, logs, and traces) you need to implement query router (also known as a multiplexer).
To do so:
- Populate the
queryType
property of your query model client-side, as shown in theDataQuery
interface. - With
queryType
populated in queries and sent to your plugin backend component, usedatasource.QueryTypeMux
to multiplex or route different query types to separate query handlers. - Each query handler can then
json.Unmarshal
each query JSON field inDataQuery
to a certain Go struct as shown in this example:
package mydatasource
import (
"context"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
)
type MyDatasource struct {
queryHandler backend.QueryDataHandler
}
func New() *MyDatasource {
ds := &MyDatasource{}
queryTypeMux := datasource.NewQueryTypeMux()
queryTypeMux.HandleFunc("metrics", ds.handleMetricsQuery)
queryTypeMux.HandleFunc("logs", ds.handleLogsQuery)
queryTypeMux.HandleFunc("traces", ds.handleTracesQuery)
queryTypeMux.HandleFunc("", ds.handleQueryFallback)
ds.queryHandler := queryTypeMux
return ds
}
func (d *MyDatasource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
return d.queryHandler.QueryData(ctx, req)
}
// handleMetricsQuery handle queries of query type "metrics".
// All queries in backend.QueryDataRequest is guaranteed to only
// include queries with queryType "metrics".
func (d *MyDatasource) handleMetricsQuery(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
// implementation...
}
// handleLogsQuery handle queries of query type "logs".
// All queries in backend.QueryDataRequest is guaranteed to only
// include queries with queryType "logs".
func (d *MyDatasource) handleLogsQuery(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
// implementation...
}
// handleTracesQuery handle queries of query type "logs".
// All queries in backend.QueryDataRequest is guaranteed to only
// include queries with queryType "traces".
func (d *MyDatasource) handleTracesQuery(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
// implementation...
}
// handleQueryFallback handle queries without a matching query type handler registered.
func (d *MyDatasource) handleQueryFallback(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
// implementation...
}
Advanced usage​
You can find an example of using QueryTypeMux
in Grafana's built-in TestData data source code:
- Create a query type multiplexer and call
registerScenarios
. - The
registerScenarios
method uses a helper method to register each query type handler. The latter also shows how you can wrap the actual handler in another handler to apply common functionality or middleware to all handlers, for example logging and traces.