mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			156 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			156 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
| package expr
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/grafana/grafana-plugin-sdk-go/backend"
 | |
| 	"github.com/prometheus/client_golang/prometheus"
 | |
| 
 | |
| 	"github.com/grafana/grafana/pkg/apimachinery/identity"
 | |
| 	"github.com/grafana/grafana/pkg/components/simplejson"
 | |
| 	"github.com/grafana/grafana/pkg/infra/tracing"
 | |
| 	"github.com/grafana/grafana/pkg/plugins"
 | |
| 	"github.com/grafana/grafana/pkg/services/datasources"
 | |
| 	"github.com/grafana/grafana/pkg/services/featuremgmt"
 | |
| 	"github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext"
 | |
| 	"github.com/grafana/grafana/pkg/setting"
 | |
| )
 | |
| 
 | |
| // DatasourceType is the string constant used as the datasource when the property is in Datasource.Type.
 | |
| // Type in requests is used to identify what type of data source plugin the request belongs to.
 | |
| const DatasourceType = "__expr__"
 | |
| 
 | |
| // DatasourceUID is the string constant used as the datasource name in requests
 | |
| // to identify it as an expression command when use in Datasource.UID.
 | |
| const DatasourceUID = DatasourceType
 | |
| 
 | |
| // DatasourceID is the fake datasource id used in requests to identify it as an
 | |
| // expression command.
 | |
| const DatasourceID = -100
 | |
| 
 | |
| // OldDatasourceUID is the datasource uid used in requests to identify it as an
 | |
| // expression command. It goes with the query root level datasourceUID property. It was accidentally
 | |
| // set to the Id and is now kept for backwards compatibility. The newer Datasource.UID property
 | |
| // should be used instead and should be set to "__expr__".
 | |
| const OldDatasourceUID = "-100"
 | |
| 
 | |
| // IsDataSource checks if the uid points to an expression query
 | |
| func IsDataSource(uid string) bool {
 | |
| 	return uid == DatasourceUID || uid == OldDatasourceUID
 | |
| }
 | |
| 
 | |
| // NodeTypeFromDatasourceUID returns NodeType depending on the UID of the data source: TypeCMDNode if UID is DatasourceUID
 | |
| // or OldDatasourceUID, and TypeDatasourceNode otherwise.
 | |
| func NodeTypeFromDatasourceUID(uid string) NodeType {
 | |
| 	if IsDataSource(uid) {
 | |
| 		return TypeCMDNode
 | |
| 	}
 | |
| 	if uid == MLDatasourceUID {
 | |
| 		return TypeMLNode
 | |
| 	}
 | |
| 	return TypeDatasourceNode
 | |
| }
 | |
| 
 | |
| // Service is service representation for expression handling.
 | |
| type Service struct {
 | |
| 	cfg          *setting.Cfg
 | |
| 	dataService  backend.QueryDataHandler
 | |
| 	pCtxProvider pluginContextProvider
 | |
| 	features     featuremgmt.FeatureToggles
 | |
| 	converter    *ResultConverter
 | |
| 
 | |
| 	pluginsClient backend.CallResourceHandler
 | |
| 
 | |
| 	tracer  tracing.Tracer
 | |
| 	metrics *metrics
 | |
| }
 | |
| 
 | |
| type pluginContextProvider interface {
 | |
| 	Get(ctx context.Context, pluginID string, user identity.Requester, orgID int64) (backend.PluginContext, error)
 | |
| 	GetWithDataSource(ctx context.Context, pluginID string, user identity.Requester, ds *datasources.DataSource) (backend.PluginContext, error)
 | |
| }
 | |
| 
 | |
| func ProvideService(cfg *setting.Cfg, pluginClient plugins.Client, pCtxProvider *plugincontext.Provider,
 | |
| 	features featuremgmt.FeatureToggles, registerer prometheus.Registerer, tracer tracing.Tracer) *Service {
 | |
| 	return &Service{
 | |
| 		cfg:           cfg,
 | |
| 		dataService:   pluginClient,
 | |
| 		pCtxProvider:  pCtxProvider,
 | |
| 		features:      features,
 | |
| 		tracer:        tracer,
 | |
| 		metrics:       newMetrics(registerer),
 | |
| 		pluginsClient: pluginClient,
 | |
| 		converter: &ResultConverter{
 | |
| 			Features: features,
 | |
| 			Tracer:   tracer,
 | |
| 		},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (s *Service) isDisabled() bool {
 | |
| 	if s.cfg == nil {
 | |
| 		return true
 | |
| 	}
 | |
| 	return !s.cfg.ExpressionsEnabled
 | |
| }
 | |
| 
 | |
| // BuildPipeline builds a pipeline from a request.
 | |
| func (s *Service) BuildPipeline(req *Request) (DataPipeline, error) {
 | |
| 	return s.buildPipeline(req)
 | |
| }
 | |
| 
 | |
| // ExecutePipeline executes an expression pipeline and returns all the results.
 | |
| func (s *Service) ExecutePipeline(ctx context.Context, now time.Time, pipeline DataPipeline) (*backend.QueryDataResponse, error) {
 | |
| 	ctx, span := s.tracer.Start(ctx, "SSE.ExecutePipeline")
 | |
| 	defer span.End()
 | |
| 	res := backend.NewQueryDataResponse()
 | |
| 	vars, err := pipeline.execute(ctx, now, s)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	for refID, val := range vars {
 | |
| 		res.Responses[refID] = backend.DataResponse{
 | |
| 			Frames: val.Values.AsDataFrames(refID),
 | |
| 			Error:  val.Error,
 | |
| 		}
 | |
| 	}
 | |
| 	return res, nil
 | |
| }
 | |
| 
 | |
| // Create a datasources.DataSource struct from NodeType. Returns error if kind is TypeDatasourceNode or unknown one.
 | |
| func DataSourceModelFromNodeType(kind NodeType) (*datasources.DataSource, error) {
 | |
| 	switch kind {
 | |
| 	case TypeCMDNode:
 | |
| 		return &datasources.DataSource{
 | |
| 			ID:             DatasourceID,
 | |
| 			UID:            DatasourceUID,
 | |
| 			Name:           DatasourceUID,
 | |
| 			Type:           DatasourceType,
 | |
| 			JsonData:       simplejson.New(),
 | |
| 			SecureJsonData: make(map[string][]byte),
 | |
| 		}, nil
 | |
| 	case TypeMLNode:
 | |
| 		return &datasources.DataSource{
 | |
| 			ID:             mlDatasourceID,
 | |
| 			UID:            MLDatasourceUID,
 | |
| 			Name:           DatasourceUID,
 | |
| 			Type:           mlPluginID,
 | |
| 			JsonData:       simplejson.New(),
 | |
| 			SecureJsonData: make(map[string][]byte),
 | |
| 		}, nil
 | |
| 	case TypeDatasourceNode:
 | |
| 		return nil, errors.New("cannot create expression data source for data source kind")
 | |
| 	default:
 | |
| 		return nil, fmt.Errorf("cannot create expression data source for '%s' kind", kind)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Deprecated. Use DataSourceModelFromNodeType instead
 | |
| func DataSourceModel() *datasources.DataSource {
 | |
| 	d, _ := DataSourceModelFromNodeType(TypeCMDNode)
 | |
| 	return d
 | |
| }
 |