decouple the opentsdb data source from core (#113588)

* enable linting rules for opentsdb

* remove core imports

* update plugin.json

* write backend standalone files

* remove frontend core imports

* add yarn workspace

* remove core import for the plugin

* update grafana dependency

* update package.json

* add jest config
This commit is contained in:
Gareth
2025-11-12 22:33:17 +09:00
committed by GitHub
parent ed19a92a2a
commit 4e050267c7
19 changed files with 235 additions and 51 deletions
@@ -1580,7 +1580,7 @@
"keywords": null
},
"dependencies": {
"grafanaDependency": "",
"grafanaDependency": "\u003e=10.3.0-0",
"grafanaVersion": "*",
"plugins": [],
"extensions": {
+40 -37
View File
@@ -15,22 +15,19 @@ import (
"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/httpclient"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/setting"
)
var logger = log.New("tsdb.opentsdb")
var logger = backend.NewLoggerWith("tsdb.opentsdb")
type Service struct {
im instancemgmt.InstanceManager
}
func ProvideService(httpClientProvider httpclient.Provider) *Service {
func ProvideService(httpClientProvider *httpclient.Provider) *Service {
return &Service{
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
}
@@ -52,7 +49,22 @@ type JSONData struct {
LookupLimit int32 `json:"lookupLimit"`
}
func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.InstanceFactoryFunc {
type QueryModel struct {
Metric string `json:"metric"`
Aggregator string `json:"aggregator"`
DownsampleInterval string `json:"downsampleInterval"`
DownsampleAggregator string `json:"downsampleAggregator"`
DownsampleFillPolicy string `json:"downsampleFillPolicy"`
DisableDownsampling bool `json:"disableDownsampling"`
Filters []any `json:"filters"`
Tags map[string]interface{} `json:"tags"`
ShouldComputeRate bool `json:"shouldComputeRate"`
IsCounter bool `json:"isCounter"`
CounterMax float64 `json:"counterMax"`
CounterResetValue float64 `json:"counterResetValue"`
}
func newInstanceSettings(httpClientProvider *httpclient.Provider) datasource.InstanceFactoryFunc {
return func(ctx context.Context, settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
opts, err := settings.HTTPClientOptions(ctx)
if err != nil {
@@ -102,10 +114,6 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
},
}
if setting.Env == setting.Dev {
logger.Debug("OpenTsdb request", "refId", query.RefID, "params", tsdbQuery)
}
httpReq, err := s.createRequest(ctx, logger, dsInfo, tsdbQuery)
if err != nil {
return nil, err
@@ -274,47 +282,44 @@ func (s *Service) parseResponse(logger log.Logger, res *http.Response, refID str
func (s *Service) buildMetric(query backend.DataQuery) map[string]any {
metric := make(map[string]any)
model, err := simplejson.NewJson(query.JSON)
if err != nil {
var model QueryModel
if err := json.Unmarshal(query.JSON, &model); err != nil {
return nil
}
// Setting metric and aggregator
metric["metric"] = model.Get("metric").MustString()
metric["aggregator"] = model.Get("aggregator").MustString()
metric["metric"] = model.Metric
metric["aggregator"] = model.Aggregator
// Setting downsampling options
disableDownsampling := model.Get("disableDownsampling").MustBool()
if !disableDownsampling {
downsampleInterval := model.Get("downsampleInterval").MustString()
if !model.DisableDownsampling {
downsampleInterval := model.DownsampleInterval
if downsampleInterval == "" {
downsampleInterval = "1m" // default value for blank
}
downsample := downsampleInterval + "-" + model.Get("downsampleAggregator").MustString()
if model.Get("downsampleFillPolicy").MustString() != "none" {
metric["downsample"] = downsample + "-" + model.Get("downsampleFillPolicy").MustString()
downsample := downsampleInterval + "-" + model.DownsampleAggregator
if model.DownsampleFillPolicy != "none" {
metric["downsample"] = downsample + "-" + model.DownsampleFillPolicy
} else {
metric["downsample"] = downsample
}
}
// Setting rate options
if model.Get("shouldComputeRate").MustBool() {
if model.ShouldComputeRate {
metric["rate"] = true
rateOptions := make(map[string]any)
rateOptions["counter"] = model.Get("isCounter").MustBool()
rateOptions["counter"] = model.IsCounter
counterMax, counterMaxCheck := model.CheckGet("counterMax")
if counterMaxCheck {
rateOptions["counterMax"] = counterMax.MustFloat64()
if model.CounterMax != 0 {
rateOptions["counterMax"] = model.CounterMax
}
resetValue, resetValueCheck := model.CheckGet("counterResetValue")
if resetValueCheck {
rateOptions["resetValue"] = resetValue.MustFloat64()
if model.CounterResetValue != 0 {
rateOptions["resetValue"] = model.CounterResetValue
}
if !counterMaxCheck && (!resetValueCheck || resetValue.MustFloat64() == 0) {
if model.CounterMax == 0 && (model.CounterResetValue == 0) {
rateOptions["dropResets"] = true
}
@@ -322,15 +327,13 @@ func (s *Service) buildMetric(query backend.DataQuery) map[string]any {
}
// Setting tags
tags, tagsCheck := model.CheckGet("tags")
if tagsCheck && len(tags.MustMap()) > 0 {
metric["tags"] = tags.MustMap()
if len(model.Tags) > 0 {
metric["tags"] = model.Tags
}
// Setting filters
filters, filtersCheck := model.CheckGet("filters")
if filtersCheck && len(filters.MustArray()) > 0 {
metric["filters"] = filters.MustArray()
if len(model.Filters) > 0 {
metric["filters"] = model.Filters
}
return metric
+1 -1
View File
@@ -12,8 +12,8 @@ import (
"github.com/google/go-cmp/cmp"
"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/httpclient"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -0,0 +1,28 @@
package main
import (
"context"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
opentsdb "github.com/grafana/grafana/pkg/tsdb/opentsdb"
)
var (
_ backend.QueryDataHandler = (*Datasource)(nil)
)
type Datasource struct {
Service *opentsdb.Service
}
func NewDatasource(context.Context, backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return &Datasource{
Service: opentsdb.ProvideService(httpclient.NewProvider()),
}, nil
}
func (d *Datasource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
return d.Service.QueryData(ctx, req)
}
+15
View File
@@ -0,0 +1,15 @@
package main
import (
"os"
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
)
func main() {
if err := datasource.Manage("opentsdb", NewDatasource, datasource.ManageOpts{}); err != nil {
log.DefaultLogger.Error(err.Error())
os.Exit(1)
}
}