diff --git a/pkg/tsdb/mysql/mysql.go b/pkg/tsdb/mysql/mysql.go index 357663f02b8..6b08adb8491 100644 --- a/pkg/tsdb/mysql/mysql.go +++ b/pkg/tsdb/mysql/mysql.go @@ -31,24 +31,11 @@ const ( dateTimeFormat2 = "2006-01-02T15:04:05Z" ) -type Service struct { - im instancemgmt.InstanceManager - logger log.Logger -} - func characterEscape(s string, escapeChar string) string { return strings.ReplaceAll(s, escapeChar, url.QueryEscape(escapeChar)) } -func ProvideService() *Service { - logger := backend.NewLoggerWith("logger", "tsdb.mysql") - return &Service{ - im: datasource.NewInstanceManager(newInstanceSettings(logger)), - logger: logger, - } -} - -func newInstanceSettings(logger log.Logger) datasource.InstanceFactoryFunc { +func NewInstanceSettings(logger log.Logger) datasource.InstanceFactoryFunc { return func(ctx context.Context, settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { cfg := backend.GrafanaConfigFromContext(ctx) sqlCfg, err := cfg.SQL() @@ -171,42 +158,6 @@ func newInstanceSettings(logger log.Logger) datasource.InstanceFactoryFunc { } } -func (s *Service) getDataSourceHandler(ctx context.Context, pluginCtx backend.PluginContext) (*sqleng.DataSourceHandler, error) { - i, err := s.im.Get(ctx, pluginCtx) - if err != nil { - return nil, err - } - instance := i.(*sqleng.DataSourceHandler) - return instance, nil -} - -// CheckHealth pings the connected SQL database -func (s *Service) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { - dsHandler, err := s.getDataSourceHandler(ctx, req.PluginContext) - if err != nil { - return nil, err - } - - err = dsHandler.Ping() - - if err != nil { - var driverErr *mysql.MySQLError - if errors.As(err, &driverErr) { - return &backend.CheckHealthResult{Status: backend.HealthStatusError, Message: dsHandler.TransformQueryError(s.logger, driverErr).Error()}, nil - } - return &backend.CheckHealthResult{Status: backend.HealthStatusError, Message: dsHandler.TransformQueryError(s.logger, err).Error()}, nil - } - return &backend.CheckHealthResult{Status: backend.HealthStatusOk, Message: "Database Connection OK"}, nil -} - -func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { - dsHandler, err := s.getDataSourceHandler(ctx, req.PluginContext) - if err != nil { - return nil, err - } - return dsHandler.QueryData(ctx, req) -} - type mysqlQueryResultTransformer struct { userError string } diff --git a/pkg/tsdb/mysql/mysql_service.go b/pkg/tsdb/mysql/mysql_service.go new file mode 100644 index 00000000000..439ad3cc220 --- /dev/null +++ b/pkg/tsdb/mysql/mysql_service.go @@ -0,0 +1,53 @@ +package mysql + +import ( + "context" + + "github.com/grafana/grafana-plugin-sdk-go/backend" + "github.com/grafana/grafana-plugin-sdk-go/backend/datasource" + "github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt" + + "github.com/grafana/grafana-plugin-sdk-go/backend/log" + "github.com/grafana/grafana/pkg/tsdb/mysql/sqleng" +) + +type Service struct { + im instancemgmt.InstanceManager + logger log.Logger +} + +func ProvideService() *Service { + logger := backend.NewLoggerWith("logger", "tsdb.mysql") + return &Service{ + im: datasource.NewInstanceManager(NewInstanceSettings(logger)), + logger: logger, + } +} + +func (s *Service) getDataSourceHandler(ctx context.Context, pluginCtx backend.PluginContext) (*sqleng.DataSourceHandler, error) { + i, err := s.im.Get(ctx, pluginCtx) + if err != nil { + return nil, err + } + instance := i.(*sqleng.DataSourceHandler) + return instance, nil +} + +// NOTE: do not put any business logic into this method. it's whole job is to forward the call "inside" +func (s *Service) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { + dsHandler, err := s.getDataSourceHandler(ctx, req.PluginContext) + if err != nil { + return nil, err + } + + return dsHandler.CheckHealth(ctx, req) +} + +// NOTE: do not put any business logic into this method. it's whole job is to forward the call "inside" +func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { + dsHandler, err := s.getDataSourceHandler(ctx, req.PluginContext) + if err != nil { + return nil, err + } + return dsHandler.QueryData(ctx, req) +} diff --git a/pkg/tsdb/mysql/sqleng/sql_engine.go b/pkg/tsdb/mysql/sqleng/sql_engine.go index 060e2bcb02e..455f8e7bd52 100644 --- a/pkg/tsdb/mysql/sqleng/sql_engine.go +++ b/pkg/tsdb/mysql/sqleng/sql_engine.go @@ -14,6 +14,7 @@ import ( "sync" "time" + "github.com/go-sql-driver/mysql" "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/data" "github.com/grafana/grafana-plugin-sdk-go/data/sqlutil" @@ -153,8 +154,17 @@ func (e *DataSourceHandler) Dispose() { e.log.Debug("DB disposed") } -func (e *DataSourceHandler) Ping() error { - return e.db.Ping() +func (e *DataSourceHandler) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { + err := e.db.Ping() + + if err != nil { + var driverErr *mysql.MySQLError + if errors.As(err, &driverErr) { + return &backend.CheckHealthResult{Status: backend.HealthStatusError, Message: e.TransformQueryError(e.log, driverErr).Error()}, nil + } + return &backend.CheckHealthResult{Status: backend.HealthStatusError, Message: e.TransformQueryError(e.log, err).Error()}, nil + } + return &backend.CheckHealthResult{Status: backend.HealthStatusOk, Message: "Database Connection OK"}, nil } func (e *DataSourceHandler) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { diff --git a/pkg/tsdb/mysql/standalone/datasource.go b/pkg/tsdb/mysql/standalone/datasource.go deleted file mode 100644 index 3a2a1e160db..00000000000 --- a/pkg/tsdb/mysql/standalone/datasource.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "context" - - "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt" - mysqlds "github.com/grafana/grafana/pkg/tsdb/mysql" -) - -var ( - _ backend.QueryDataHandler = (*Datasource)(nil) - _ backend.CheckHealthHandler = (*Datasource)(nil) -) - -func NewDatasource(context.Context, backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { - return &Datasource{ - Service: mysqlds.ProvideService(), - }, nil -} - -type Datasource struct { - Service *mysqlds.Service -} - -func (d *Datasource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { - return d.Service.QueryData(ctx, req) -} - -func (d *Datasource) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { - return d.Service.CheckHealth(ctx, req) -} diff --git a/pkg/tsdb/mysql/standalone/main.go b/pkg/tsdb/mysql/standalone/main.go index fd78c834330..35d4552d837 100644 --- a/pkg/tsdb/mysql/standalone/main.go +++ b/pkg/tsdb/mysql/standalone/main.go @@ -3,8 +3,10 @@ package main import ( "os" + "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend/datasource" "github.com/grafana/grafana-plugin-sdk-go/backend/log" + "github.com/grafana/grafana/pkg/tsdb/mysql" ) func main() { @@ -16,7 +18,8 @@ func main() { // from Grafana to create different instances of SampleDatasource (per datasource // ID). When datasource configuration changed Dispose method will be called and // new datasource instance created using NewSampleDatasource factory. - if err := datasource.Manage("mysql", NewDatasource, datasource.ManageOpts{}); err != nil { + logger := backend.NewLoggerWith("logger", "tsdb.mysql") + if err := datasource.Manage("mysql", mysql.NewInstanceSettings(logger), datasource.ManageOpts{}); err != nil { log.DefaultLogger.Error(err.Error()) os.Exit(1) }