mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			141 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			141 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
| package promlib
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/grafana/grafana-plugin-sdk-go/backend"
 | |
| 	"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
 | |
| 	sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
 | |
| 	"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
 | |
| 	"github.com/grafana/grafana-plugin-sdk-go/backend/log"
 | |
| 
 | |
| 	"github.com/grafana/grafana/pkg/promlib/client"
 | |
| 	"github.com/grafana/grafana/pkg/promlib/instrumentation"
 | |
| 	"github.com/grafana/grafana/pkg/promlib/querydata"
 | |
| 	"github.com/grafana/grafana/pkg/promlib/resource"
 | |
| )
 | |
| 
 | |
| type Service struct {
 | |
| 	im     instancemgmt.InstanceManager
 | |
| 	logger log.Logger
 | |
| }
 | |
| 
 | |
| type instance struct {
 | |
| 	queryData *querydata.QueryData
 | |
| 	resource  *resource.Resource
 | |
| }
 | |
| 
 | |
| type ExtendOptions func(ctx context.Context, settings backend.DataSourceInstanceSettings, clientOpts *sdkhttpclient.Options, log log.Logger) error
 | |
| 
 | |
| func NewService(httpClientProvider *sdkhttpclient.Provider, plog log.Logger, extendOptions ExtendOptions) *Service {
 | |
| 	if httpClientProvider == nil {
 | |
| 		httpClientProvider = sdkhttpclient.NewProvider()
 | |
| 	}
 | |
| 	return &Service{
 | |
| 		im:     datasource.NewInstanceManager(newInstanceSettings(httpClientProvider, plog, extendOptions)),
 | |
| 		logger: plog,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Dispose here tells plugin SDK that plugin wants to clean up resources when a new instance
 | |
| // created. As soon as datasource settings change detected by SDK old datasource instance will
 | |
| // be disposed and a new one will be created using NewSampleDatasource factory function.
 | |
| func (s *Service) Dispose() {
 | |
| 	// Clean up datasource instance resources.
 | |
| 	s.logger.Debug("Disposing the instance...")
 | |
| }
 | |
| 
 | |
| func newInstanceSettings(httpClientProvider *sdkhttpclient.Provider, log log.Logger, extendOptions ExtendOptions) datasource.InstanceFactoryFunc {
 | |
| 	return func(ctx context.Context, settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
 | |
| 		// Creates a http roundTripper.
 | |
| 		opts, err := client.CreateTransportOptions(ctx, settings, log)
 | |
| 		if err != nil {
 | |
| 			return nil, fmt.Errorf("error creating transport options: %v", err)
 | |
| 		}
 | |
| 
 | |
| 		if extendOptions != nil {
 | |
| 			err = extendOptions(ctx, settings, opts, log)
 | |
| 			if err != nil {
 | |
| 				return nil, fmt.Errorf("error extending transport options: %v", err)
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		httpClient, err := httpClientProvider.New(*opts)
 | |
| 		if err != nil {
 | |
| 			return nil, fmt.Errorf("error creating http client: %v", err)
 | |
| 		}
 | |
| 
 | |
| 		featureToggles := backend.GrafanaConfigFromContext(ctx).FeatureToggles()
 | |
| 
 | |
| 		// New version using custom client and better response parsing
 | |
| 		qd, err := querydata.New(httpClient, settings, log, featureToggles)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 		// Resource call management using new custom client same as querydata
 | |
| 		r, err := resource.New(httpClient, settings, log)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 		return instance{
 | |
| 			queryData: qd,
 | |
| 			resource:  r,
 | |
| 		}, nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
 | |
| 	if len(req.Queries) == 0 {
 | |
| 		err := fmt.Errorf("query contains no queries")
 | |
| 		instrumentation.UpdateQueryDataMetrics(err, nil)
 | |
| 		return &backend.QueryDataResponse{}, err
 | |
| 	}
 | |
| 
 | |
| 	i, err := s.getInstance(ctx, req.PluginContext)
 | |
| 	if err != nil {
 | |
| 		instrumentation.UpdateQueryDataMetrics(err, nil)
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	qd, err := i.queryData.Execute(ctx, req)
 | |
| 	instrumentation.UpdateQueryDataMetrics(err, qd)
 | |
| 
 | |
| 	return qd, err
 | |
| }
 | |
| 
 | |
| func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
 | |
| 	i, err := s.getInstance(ctx, req.PluginContext)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	switch {
 | |
| 	case strings.EqualFold(req.Path, "suggestions"):
 | |
| 		resp, err := i.resource.GetSuggestions(ctx, req)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		return sender.Send(resp)
 | |
| 	}
 | |
| 
 | |
| 	resp, err := i.resource.Execute(ctx, req)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	return sender.Send(resp)
 | |
| }
 | |
| 
 | |
| func (s *Service) getInstance(ctx context.Context, pluginCtx backend.PluginContext) (*instance, error) {
 | |
| 	i, err := s.im.Get(ctx, pluginCtx)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	in := i.(instance)
 | |
| 	return &in, nil
 | |
| }
 |