transform: add expressions to query editor (w/ feature flag) (#20072)
for use with gel which is not released yet.
This commit is contained in:
committed by
Kyle Brandt
parent
2bb4684741
commit
861eb72113
@@ -328,7 +328,6 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
// metrics
|
||||
apiRoute.Post("/tsdb/query", bind(dtos.MetricRequest{}), Wrap(hs.QueryMetrics))
|
||||
apiRoute.Post("/tsdb/query/v2", bind(dtos.MetricRequest{}), Wrap(hs.QueryMetricsV2))
|
||||
apiRoute.Post("/tsdb/transform", bind(dtos.MetricRequest{}), Wrap(hs.Transform))
|
||||
apiRoute.Get("/tsdb/testdata/scenarios", Wrap(GetTestDataScenarios))
|
||||
apiRoute.Get("/tsdb/testdata/gensql", reqGrafanaAdmin, Wrap(GenerateSQLTestData))
|
||||
apiRoute.Get("/tsdb/testdata/random-walk", Wrap(GetTestDataRandomWalk))
|
||||
|
||||
+38
-24
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"sort"
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
@@ -21,37 +22,40 @@ func (hs *HTTPServer) QueryMetricsV2(c *m.ReqContext, reqDto dtos.MetricRequest)
|
||||
return Error(404, "Expressions feature toggle is not enabled", nil)
|
||||
}
|
||||
|
||||
timeRange := tsdb.NewTimeRange(reqDto.From, reqDto.To)
|
||||
|
||||
if len(reqDto.Queries) == 0 {
|
||||
return Error(400, "No queries found in query", nil)
|
||||
return Error(500, "No queries found in query", nil)
|
||||
}
|
||||
|
||||
var datasourceID int64
|
||||
for _, query := range reqDto.Queries {
|
||||
request := &tsdb.TsdbQuery{
|
||||
TimeRange: tsdb.NewTimeRange(reqDto.From, reqDto.To),
|
||||
Debug: reqDto.Debug,
|
||||
}
|
||||
|
||||
expr := false
|
||||
var ds *m.DataSource
|
||||
for i, query := range reqDto.Queries {
|
||||
name, err := query.Get("datasource").String()
|
||||
if err != nil {
|
||||
return Error(500, "datasource missing name", err)
|
||||
}
|
||||
datasourceID, err = query.Get("datasourceId").Int64()
|
||||
if name == "__expr__" {
|
||||
expr = true
|
||||
}
|
||||
|
||||
datasourceID, err := query.Get("datasourceId").Int64()
|
||||
if err != nil {
|
||||
return Error(400, "GEL datasource missing ID", nil)
|
||||
return Error(500, "datasource missing ID", nil)
|
||||
}
|
||||
if name == "-- GEL --" {
|
||||
break
|
||||
}
|
||||
}
|
||||
ds, err := hs.DatasourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
|
||||
if err != nil {
|
||||
if err == m.ErrDataSourceAccessDenied {
|
||||
return Error(403, "Access denied to datasource", err)
|
||||
}
|
||||
return Error(500, "Unable to load datasource meta data", err)
|
||||
}
|
||||
|
||||
request := &tsdb.TsdbQuery{TimeRange: timeRange, Debug: reqDto.Debug}
|
||||
|
||||
for _, query := range reqDto.Queries {
|
||||
if i == 0 && !expr {
|
||||
ds, err = hs.DatasourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
|
||||
if err != nil {
|
||||
if err == m.ErrDataSourceAccessDenied {
|
||||
return Error(403, "Access denied to datasource", err)
|
||||
}
|
||||
return Error(500, "Unable to load datasource meta data", err)
|
||||
}
|
||||
}
|
||||
request.Queries = append(request.Queries, &tsdb.Query{
|
||||
RefId: query.Get("refId").MustString("A"),
|
||||
MaxDataPoints: query.Get("maxDataPoints").MustInt64(100),
|
||||
@@ -59,11 +63,21 @@ func (hs *HTTPServer) QueryMetricsV2(c *m.ReqContext, reqDto dtos.MetricRequest)
|
||||
Model: query,
|
||||
DataSource: ds,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
resp, err := tsdb.HandleRequest(c.Req.Context(), ds, request)
|
||||
if err != nil {
|
||||
return Error(500, "Metric request error", err)
|
||||
var resp *tsdb.Response
|
||||
var err error
|
||||
if !expr {
|
||||
resp, err = tsdb.HandleRequest(c.Req.Context(), ds, request)
|
||||
if err != nil {
|
||||
return Error(500, "Metric request error", err)
|
||||
}
|
||||
} else {
|
||||
resp, err = plugins.Transform.Transform(c.Req.Context(), request)
|
||||
if err != nil {
|
||||
return Error(500, "Transform request error", err)
|
||||
}
|
||||
}
|
||||
|
||||
statusCode := 200
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
)
|
||||
|
||||
// POST /api/tsdb/transform
|
||||
// This enpoint is tempory, will be part of v2 query endpoint.
|
||||
func (hs *HTTPServer) Transform(c *m.ReqContext, reqDto dtos.MetricRequest) Response {
|
||||
if !setting.IsExpressionsEnabled() {
|
||||
return Error(404, "Expressions feature toggle is not enabled", nil)
|
||||
}
|
||||
if plugins.Transform == nil {
|
||||
return Error(http.StatusServiceUnavailable, "transform plugin is not loaded", nil)
|
||||
}
|
||||
|
||||
timeRange := tsdb.NewTimeRange(reqDto.From, reqDto.To)
|
||||
|
||||
if len(reqDto.Queries) == 0 {
|
||||
return Error(400, "No queries found in query", nil)
|
||||
}
|
||||
|
||||
var datasourceID int64
|
||||
for _, query := range reqDto.Queries {
|
||||
name, err := query.Get("datasource").String()
|
||||
if err != nil {
|
||||
return Error(500, "datasource missing name", err)
|
||||
}
|
||||
datasourceID, err = query.Get("datasourceId").Int64()
|
||||
if err != nil {
|
||||
return Error(400, "GEL datasource missing ID", nil)
|
||||
}
|
||||
if name == "-- GEL --" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
ds, err := hs.DatasourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
|
||||
if err != nil {
|
||||
if err == m.ErrDataSourceAccessDenied {
|
||||
return Error(403, "Access denied to datasource", err)
|
||||
}
|
||||
return Error(500, "Unable to load datasource meta data", err)
|
||||
}
|
||||
|
||||
request := &tsdb.TsdbQuery{TimeRange: timeRange, Debug: reqDto.Debug}
|
||||
|
||||
for _, query := range reqDto.Queries {
|
||||
request.Queries = append(request.Queries, &tsdb.Query{
|
||||
RefId: query.Get("refId").MustString("A"),
|
||||
MaxDataPoints: query.Get("maxDataPoints").MustInt64(100),
|
||||
IntervalMs: query.Get("intervalMs").MustInt64(1000),
|
||||
Model: query,
|
||||
DataSource: ds,
|
||||
})
|
||||
}
|
||||
|
||||
resp, err := plugins.Transform.Transform(c.Req.Context(), ds, request)
|
||||
if err != nil {
|
||||
return Error(500, "Transform request error", err)
|
||||
}
|
||||
|
||||
statusCode := 200
|
||||
for _, res := range resp.Results {
|
||||
if res.Error != nil {
|
||||
res.ErrorString = res.Error.Error()
|
||||
resp.Message = res.ErrorString
|
||||
statusCode = 400
|
||||
}
|
||||
}
|
||||
|
||||
return JSON(statusCode, &resp)
|
||||
}
|
||||
@@ -27,7 +27,6 @@ type TransformPlugin struct {
|
||||
|
||||
Executable string `json:"executable,omitempty"`
|
||||
|
||||
//transform.TransformPlugin
|
||||
*TransformWrapper
|
||||
|
||||
client *plugin.Client
|
||||
@@ -136,22 +135,10 @@ type TransformWrapper struct {
|
||||
api *grafanaAPI
|
||||
}
|
||||
|
||||
func (tw *TransformWrapper) Transform(ctx context.Context, ds *models.DataSource, query *tsdb.TsdbQuery) (*tsdb.Response, error) {
|
||||
jsonData, err := ds.JsonData.MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (tw *TransformWrapper) Transform(ctx context.Context, query *tsdb.TsdbQuery) (*tsdb.Response, error) {
|
||||
pbQuery := &pluginv2.TransformRequest{
|
||||
Datasource: &pluginv2.DatasourceInfo{
|
||||
Name: ds.Name,
|
||||
Type: ds.Type,
|
||||
Url: ds.Url,
|
||||
Id: ds.Id,
|
||||
OrgId: ds.OrgId,
|
||||
JsonData: string(jsonData),
|
||||
DecryptedSecureJsonData: ds.SecureJsonData.Decrypt(),
|
||||
},
|
||||
// TODO Not sure Datasource property needs be on this?
|
||||
Datasource: &pluginv2.DatasourceInfo{},
|
||||
TimeRange: &pluginv2.TimeRange{
|
||||
FromRaw: query.TimeRange.From,
|
||||
ToRaw: query.TimeRange.To,
|
||||
@@ -217,6 +204,7 @@ func (s *grafanaAPI) QueryDatasource(ctx context.Context, req *pluginv2.QueryDat
|
||||
if len(req.Queries) == 0 {
|
||||
return nil, fmt.Errorf("zero queries found in datasource request")
|
||||
}
|
||||
|
||||
getDsInfo := &models.GetDataSourceByIdQuery{
|
||||
Id: req.DatasourceId,
|
||||
OrgId: req.OrgId,
|
||||
|
||||
Reference in New Issue
Block a user