mirror of https://github.com/grafana/grafana
Chore: Refactor backend plugin manager/tsdb query data (#34944)
Move QueryData method into backend plugin manager which HandleRequest uses to query data from plugin SDK supported data sources. This allowed us to remove a lot of code no longer needed. Ref #21510 Co-authored-by: Will Browne <wbrowne@users.noreply.github.com>pull/34946/head
parent
56e0efbb56
commit
b3e9087557
@ -1,116 +0,0 @@ |
||||
package coreplugin |
||||
|
||||
import ( |
||||
"context" |
||||
"time" |
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend" |
||||
"github.com/grafana/grafana/pkg/infra/log" |
||||
"github.com/grafana/grafana/pkg/models" |
||||
"github.com/grafana/grafana/pkg/plugins" |
||||
"github.com/grafana/grafana/pkg/plugins/adapters" |
||||
) |
||||
|
||||
// nolint:staticcheck // plugins.DataPlugin deprecated
|
||||
func newQueryEndpointAdapter(pluginID string, logger log.Logger, handler backend.QueryDataHandler) plugins.DataPlugin { |
||||
return &queryEndpointAdapter{ |
||||
pluginID: pluginID, |
||||
logger: logger, |
||||
handler: handler, |
||||
} |
||||
} |
||||
|
||||
type queryEndpointAdapter struct { |
||||
pluginID string |
||||
logger log.Logger |
||||
handler backend.QueryDataHandler |
||||
} |
||||
|
||||
func modelToInstanceSettings(ds *models.DataSource) (*backend.DataSourceInstanceSettings, error) { |
||||
jsonDataBytes, err := ds.JsonData.MarshalJSON() |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return &backend.DataSourceInstanceSettings{ |
||||
ID: ds.Id, |
||||
Name: ds.Name, |
||||
URL: ds.Url, |
||||
Database: ds.Database, |
||||
User: ds.User, |
||||
BasicAuthEnabled: ds.BasicAuth, |
||||
BasicAuthUser: ds.BasicAuthUser, |
||||
JSONData: jsonDataBytes, |
||||
DecryptedSecureJSONData: ds.DecryptedValues(), |
||||
Updated: ds.Updated, |
||||
}, nil |
||||
} |
||||
|
||||
// nolint:staticcheck // plugins.DataQuery deprecated
|
||||
func (a *queryEndpointAdapter) DataQuery(ctx context.Context, ds *models.DataSource, query plugins.DataQuery) ( |
||||
plugins.DataResponse, error) { |
||||
instanceSettings, err := modelToInstanceSettings(ds) |
||||
if err != nil { |
||||
return plugins.DataResponse{}, err |
||||
} |
||||
|
||||
req := &backend.QueryDataRequest{ |
||||
PluginContext: backend.PluginContext{ |
||||
OrgID: ds.OrgId, |
||||
PluginID: a.pluginID, |
||||
User: adapters.BackendUserFromSignedInUser(query.User), |
||||
DataSourceInstanceSettings: instanceSettings, |
||||
}, |
||||
Queries: []backend.DataQuery{}, |
||||
Headers: query.Headers, |
||||
} |
||||
|
||||
for _, q := range query.Queries { |
||||
modelJSON, err := q.Model.MarshalJSON() |
||||
if err != nil { |
||||
return plugins.DataResponse{}, err |
||||
} |
||||
req.Queries = append(req.Queries, backend.DataQuery{ |
||||
RefID: q.RefID, |
||||
Interval: time.Duration(q.IntervalMS) * time.Millisecond, |
||||
MaxDataPoints: q.MaxDataPoints, |
||||
TimeRange: backend.TimeRange{ |
||||
From: query.TimeRange.GetFromAsTimeUTC(), |
||||
To: query.TimeRange.GetToAsTimeUTC(), |
||||
}, |
||||
QueryType: q.QueryType, |
||||
JSON: modelJSON, |
||||
}) |
||||
} |
||||
|
||||
resp, err := a.handler.QueryData(ctx, req) |
||||
if err != nil { |
||||
return plugins.DataResponse{}, err |
||||
} |
||||
|
||||
tR := plugins.DataResponse{ |
||||
Results: make(map[string]plugins.DataQueryResult, len(resp.Responses)), |
||||
} |
||||
|
||||
for refID, r := range resp.Responses { |
||||
qr := plugins.DataQueryResult{ |
||||
RefID: refID, |
||||
} |
||||
|
||||
for _, f := range r.Frames { |
||||
if f.RefID == "" { |
||||
f.RefID = refID |
||||
} |
||||
} |
||||
|
||||
qr.Dataframes = plugins.NewDecodedDataFrames(r.Frames) |
||||
|
||||
if r.Error != nil { |
||||
qr.Error = r.Error |
||||
} |
||||
|
||||
tR.Results[refID] = qr |
||||
} |
||||
|
||||
return tR, nil |
||||
} |
@ -1,99 +0,0 @@ |
||||
package plugins |
||||
|
||||
import ( |
||||
"context" |
||||
"fmt" |
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend" |
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/grpcplugin" |
||||
"github.com/grafana/grafana-plugin-sdk-go/genproto/pluginv2" |
||||
"github.com/grafana/grafana/pkg/components/simplejson" |
||||
"github.com/grafana/grafana/pkg/infra/log" |
||||
"github.com/grafana/grafana/pkg/models" |
||||
"github.com/grafana/grafana/pkg/plugins/adapters" |
||||
"github.com/grafana/grafana/pkg/services/oauthtoken" |
||||
) |
||||
|
||||
func newDataSourcePluginWrapperV2(log log.Logger, pluginId, pluginType string, dataClient grpcplugin.DataClient) *DatasourcePluginWrapperV2 { |
||||
return &DatasourcePluginWrapperV2{DataClient: dataClient, logger: log, pluginId: pluginId, pluginType: pluginType} |
||||
} |
||||
|
||||
type DatasourcePluginWrapperV2 struct { |
||||
grpcplugin.DataClient |
||||
logger log.Logger |
||||
pluginId string |
||||
pluginType string |
||||
} |
||||
|
||||
func (tw *DatasourcePluginWrapperV2) Query(ctx context.Context, ds *models.DataSource, query DataQuery) (DataResponse, error) { |
||||
instanceSettings, err := adapters.ModelToInstanceSettings(ds) |
||||
if err != nil { |
||||
return DataResponse{}, err |
||||
} |
||||
|
||||
if query.Headers == nil { |
||||
query.Headers = make(map[string]string) |
||||
} |
||||
|
||||
if oauthtoken.IsOAuthPassThruEnabled(ds) { |
||||
if token := oauthtoken.GetCurrentOAuthToken(ctx, query.User); token != nil { |
||||
delete(query.Headers, "Authorization") |
||||
query.Headers["Authorization"] = fmt.Sprintf("%s %s", token.Type(), token.AccessToken) |
||||
} |
||||
} |
||||
|
||||
pbQuery := &pluginv2.QueryDataRequest{ |
||||
PluginContext: &pluginv2.PluginContext{ |
||||
OrgId: ds.OrgId, |
||||
PluginId: tw.pluginId, |
||||
User: backend.ToProto().User(adapters.BackendUserFromSignedInUser(query.User)), |
||||
DataSourceInstanceSettings: backend.ToProto().DataSourceInstanceSettings(instanceSettings), |
||||
}, |
||||
Queries: []*pluginv2.DataQuery{}, |
||||
Headers: query.Headers, |
||||
} |
||||
|
||||
for _, q := range query.Queries { |
||||
modelJSON, err := q.Model.MarshalJSON() |
||||
if err != nil { |
||||
return DataResponse{}, err |
||||
} |
||||
pbQuery.Queries = append(pbQuery.Queries, &pluginv2.DataQuery{ |
||||
Json: modelJSON, |
||||
IntervalMS: q.IntervalMS, |
||||
RefId: q.RefID, |
||||
MaxDataPoints: q.MaxDataPoints, |
||||
TimeRange: &pluginv2.TimeRange{ |
||||
ToEpochMS: query.TimeRange.GetToAsMsEpoch(), |
||||
FromEpochMS: query.TimeRange.GetFromAsMsEpoch(), |
||||
}, |
||||
QueryType: q.QueryType, |
||||
}) |
||||
} |
||||
|
||||
pbRes, err := tw.DataClient.QueryData(ctx, pbQuery) |
||||
if err != nil { |
||||
return DataResponse{}, err |
||||
} |
||||
|
||||
tR := DataResponse{ |
||||
Results: make(map[string]DataQueryResult, len(pbRes.Responses)), |
||||
} |
||||
|
||||
for refID, pRes := range pbRes.Responses { |
||||
qr := DataQueryResult{ |
||||
RefID: refID, |
||||
Dataframes: NewEncodedDataFrames(pRes.Frames), |
||||
} |
||||
if len(pRes.JsonMeta) != 0 { |
||||
qr.Meta = simplejson.NewFromAny(pRes.JsonMeta) |
||||
} |
||||
if pRes.Error != "" { |
||||
qr.Error = fmt.Errorf(pRes.Error) |
||||
qr.ErrorString = pRes.Error |
||||
} |
||||
tR.Results[refID] = qr |
||||
} |
||||
|
||||
return tR, nil |
||||
} |
@ -0,0 +1,115 @@ |
||||
package tsdb |
||||
|
||||
import ( |
||||
"context" |
||||
"fmt" |
||||
"time" |
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend" |
||||
"github.com/grafana/grafana/pkg/models" |
||||
"github.com/grafana/grafana/pkg/plugins" |
||||
"github.com/grafana/grafana/pkg/plugins/adapters" |
||||
"github.com/grafana/grafana/pkg/services/oauthtoken" |
||||
) |
||||
|
||||
// nolint:staticcheck // plugins.DataQuery deprecated
|
||||
func dataPluginQueryAdapter(pluginID string, handler backend.QueryDataHandler) plugins.DataPluginFunc { |
||||
return plugins.DataPluginFunc(func(ctx context.Context, ds *models.DataSource, query plugins.DataQuery) (plugins.DataResponse, error) { |
||||
instanceSettings, err := modelToInstanceSettings(ds) |
||||
if err != nil { |
||||
return plugins.DataResponse{}, err |
||||
} |
||||
|
||||
if query.Headers == nil { |
||||
query.Headers = make(map[string]string) |
||||
} |
||||
|
||||
if oauthtoken.IsOAuthPassThruEnabled(ds) { |
||||
if token := oauthtoken.GetCurrentOAuthToken(ctx, query.User); token != nil { |
||||
delete(query.Headers, "Authorization") |
||||
query.Headers["Authorization"] = fmt.Sprintf("%s %s", token.Type(), token.AccessToken) |
||||
} |
||||
} |
||||
|
||||
req := &backend.QueryDataRequest{ |
||||
PluginContext: backend.PluginContext{ |
||||
OrgID: ds.OrgId, |
||||
PluginID: pluginID, |
||||
User: adapters.BackendUserFromSignedInUser(query.User), |
||||
DataSourceInstanceSettings: instanceSettings, |
||||
}, |
||||
Queries: []backend.DataQuery{}, |
||||
Headers: query.Headers, |
||||
} |
||||
|
||||
for _, q := range query.Queries { |
||||
modelJSON, err := q.Model.MarshalJSON() |
||||
if err != nil { |
||||
return plugins.DataResponse{}, err |
||||
} |
||||
req.Queries = append(req.Queries, backend.DataQuery{ |
||||
RefID: q.RefID, |
||||
Interval: time.Duration(q.IntervalMS) * time.Millisecond, |
||||
MaxDataPoints: q.MaxDataPoints, |
||||
TimeRange: backend.TimeRange{ |
||||
From: query.TimeRange.GetFromAsTimeUTC(), |
||||
To: query.TimeRange.GetToAsTimeUTC(), |
||||
}, |
||||
QueryType: q.QueryType, |
||||
JSON: modelJSON, |
||||
}) |
||||
} |
||||
|
||||
resp, err := handler.QueryData(ctx, req) |
||||
if err != nil { |
||||
return plugins.DataResponse{}, err |
||||
} |
||||
|
||||
tR := plugins.DataResponse{ |
||||
Results: make(map[string]plugins.DataQueryResult, len(resp.Responses)), |
||||
} |
||||
|
||||
for refID, r := range resp.Responses { |
||||
qr := plugins.DataQueryResult{ |
||||
RefID: refID, |
||||
} |
||||
|
||||
for _, f := range r.Frames { |
||||
if f.RefID == "" { |
||||
f.RefID = refID |
||||
} |
||||
} |
||||
|
||||
qr.Dataframes = plugins.NewDecodedDataFrames(r.Frames) |
||||
|
||||
if r.Error != nil { |
||||
qr.Error = r.Error |
||||
} |
||||
|
||||
tR.Results[refID] = qr |
||||
} |
||||
|
||||
return tR, nil |
||||
}) |
||||
} |
||||
|
||||
func modelToInstanceSettings(ds *models.DataSource) (*backend.DataSourceInstanceSettings, error) { |
||||
jsonDataBytes, err := ds.JsonData.MarshalJSON() |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return &backend.DataSourceInstanceSettings{ |
||||
ID: ds.Id, |
||||
Name: ds.Name, |
||||
URL: ds.Url, |
||||
Database: ds.Database, |
||||
User: ds.User, |
||||
BasicAuthEnabled: ds.BasicAuth, |
||||
BasicAuthUser: ds.BasicAuthUser, |
||||
JSONData: jsonDataBytes, |
||||
DecryptedSecureJSONData: ds.DecryptedValues(), |
||||
Updated: ds.Updated, |
||||
UID: ds.Uid, |
||||
}, nil |
||||
} |
Loading…
Reference in new issue