Jaeger: run health check through backend (#99322)

run health check through backend
This commit is contained in:
Gareth Dawson
2025-01-24 19:37:36 +07:00
committed by GitHub
parent e3ba96113c
commit 33d82c43df
10 changed files with 176 additions and 7 deletions

View File

@ -50,7 +50,7 @@ func TestCallResource(t *testing.T) {
cfg.Azure = &azsettings.AzureSettings{}
coreRegistry := coreplugin.ProvideCoreRegistry(tracing.InitializeTracerForTest(), nil, &cloudwatch.CloudWatchService{}, nil, nil, nil, nil,
nil, nil, nil, nil, testdatasource.ProvideService(), nil, nil, nil, nil, nil, nil, nil)
nil, nil, nil, nil, testdatasource.ProvideService(), nil, nil, nil, nil, nil, nil, nil, nil)
testCtx := pluginsintegration.CreateIntegrationTestCtx(t, cfg, coreRegistry)

View File

@ -27,6 +27,7 @@ import (
"github.com/grafana/grafana/pkg/tsdb/grafanads"
"github.com/grafana/grafana/pkg/tsdb/graphite"
"github.com/grafana/grafana/pkg/tsdb/influxdb"
"github.com/grafana/grafana/pkg/tsdb/jaeger"
"github.com/grafana/grafana/pkg/tsdb/loki"
"github.com/grafana/grafana/pkg/tsdb/mssql"
"github.com/grafana/grafana/pkg/tsdb/mysql"
@ -57,6 +58,7 @@ const (
Pyroscope = "grafana-pyroscope-datasource"
Parca = "parca"
Zipkin = "zipkin"
Jaeger = "jaeger"
)
func init() {
@ -95,7 +97,7 @@ func NewRegistry(store map[string]backendplugin.PluginFactoryFunc) *Registry {
func ProvideCoreRegistry(tracer tracing.Tracer, am *azuremonitor.Service, cw *cloudwatch.CloudWatchService, cm *cloudmonitoring.Service,
es *elasticsearch.Service, grap *graphite.Service, idb *influxdb.Service, lk *loki.Service, otsdb *opentsdb.Service,
pr *prometheus.Service, t *tempo.Service, td *testdatasource.Service, pg *postgres.Service, my *mysql.Service,
ms *mssql.Service, graf *grafanads.Service, pyroscope *pyroscope.Service, parca *parca.Service, zipkin *zipkin.Service) *Registry {
ms *mssql.Service, graf *grafanads.Service, pyroscope *pyroscope.Service, parca *parca.Service, zipkin *zipkin.Service, jaeger *jaeger.Service) *Registry {
// Non-optimal global solution to replace plugin SDK default tracer for core plugins.
sdktracing.InitDefaultTracer(tracer)
@ -118,6 +120,7 @@ func ProvideCoreRegistry(tracer tracing.Tracer, am *azuremonitor.Service, cw *cl
Pyroscope: asBackendPlugin(pyroscope),
Parca: asBackendPlugin(parca),
Zipkin: asBackendPlugin(zipkin),
Jaeger: asBackendPlugin(jaeger),
})
}
@ -245,6 +248,8 @@ func NewPlugin(pluginID string, cfg *setting.Cfg, httpClientProvider *httpclient
svc = parca.ProvideService(httpClientProvider)
case Zipkin:
svc = zipkin.ProvideService(httpClientProvider)
case Jaeger:
svc = jaeger.ProvideService(httpClientProvider)
default:
return nil, ErrCorePluginNotFound
}

View File

@ -37,6 +37,7 @@ func TestNewPlugin(t *testing.T) {
{ID: TestData, ExpectedAlias: TestDataAlias},
{ID: TestDataAlias, ExpectedID: TestData, ExpectedAlias: TestDataAlias},
{ID: Zipkin},
{ID: Jaeger},
}
for _, tc := range tcs {

View File

@ -168,6 +168,7 @@ import (
"github.com/grafana/grafana/pkg/tsdb/grafanads"
"github.com/grafana/grafana/pkg/tsdb/graphite"
"github.com/grafana/grafana/pkg/tsdb/influxdb"
"github.com/grafana/grafana/pkg/tsdb/jaeger"
"github.com/grafana/grafana/pkg/tsdb/loki"
"github.com/grafana/grafana/pkg/tsdb/mssql"
"github.com/grafana/grafana/pkg/tsdb/mysql"
@ -269,6 +270,7 @@ var wireBasicSet = wire.NewSet(
pyroscope.ProvideService,
parca.ProvideService,
zipkin.ProvideService,
jaeger.ProvideService,
datasourceservice.ProvideCacheService,
wire.Bind(new(datasources.CacheService), new(*datasourceservice.CacheServiceImpl)),
encryptionservice.ProvideEncryptionService,

View File

@ -34,6 +34,7 @@ import (
"github.com/grafana/grafana/pkg/tsdb/grafanads"
"github.com/grafana/grafana/pkg/tsdb/graphite"
"github.com/grafana/grafana/pkg/tsdb/influxdb"
"github.com/grafana/grafana/pkg/tsdb/jaeger"
"github.com/grafana/grafana/pkg/tsdb/loki"
"github.com/grafana/grafana/pkg/tsdb/mssql"
"github.com/grafana/grafana/pkg/tsdb/mysql"
@ -93,7 +94,8 @@ func TestIntegrationPluginManager(t *testing.T) {
pyroscope := pyroscope.ProvideService(hcp)
parca := parca.ProvideService(hcp)
zipkin := zipkin.ProvideService(hcp)
coreRegistry := coreplugin.ProvideCoreRegistry(tracing.InitializeTracerForTest(), am, cw, cm, es, grap, idb, lk, otsdb, pr, tmpo, td, pg, my, ms, graf, pyroscope, parca, zipkin)
jaeger := jaeger.ProvideService(hcp)
coreRegistry := coreplugin.ProvideCoreRegistry(tracing.InitializeTracerForTest(), am, cw, cm, es, grap, idb, lk, otsdb, pr, tmpo, td, pg, my, ms, graf, pyroscope, parca, zipkin, jaeger)
testCtx := CreateIntegrationTestCtx(t, cfg, coreRegistry)

62
pkg/tsdb/jaeger/client.go Normal file
View File

@ -0,0 +1,62 @@
package jaeger
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
)
type JaegerClient struct {
logger log.Logger
url string
httpClient *http.Client
}
type ServicesResponse struct {
Data []string `json:"data"`
Errors interface{} `json:"errors"`
Limit int `json:"limit"`
Offset int `json:"offset"`
Total int `json:"total"`
}
func New(url string, hc *http.Client, logger log.Logger) (JaegerClient, error) {
client := JaegerClient{
logger: logger,
url: url,
httpClient: hc,
}
return client, nil
}
func (j *JaegerClient) Services() ([]string, error) {
var response ServicesResponse
services := []string{}
u, err := url.JoinPath(j.url, "/api/services")
if err != nil {
return services, backend.DownstreamError(fmt.Errorf("failed to join url: %w", err))
}
res, err := j.httpClient.Get(u)
if err != nil {
return services, err
}
defer func() {
if err = res.Body.Close(); err != nil {
j.logger.Error("Failed to close response body", "error", err)
}
}()
if err := json.NewDecoder(res.Body).Decode(&response); err != nil {
return services, err
}
services = response.Data
return services, err
}

87
pkg/tsdb/jaeger/jaeger.go Normal file
View File

@ -0,0 +1,87 @@
package jaeger
import (
"context"
"errors"
"fmt"
"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/pkg/infra/httpclient"
)
var logger = backend.NewLoggerWith("logger", "tsdb.jaeger")
type Service struct {
im instancemgmt.InstanceManager
}
func ProvideService(httpClientProvider httpclient.Provider) *Service {
return &Service{
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
}
}
type datasourceInfo struct {
JaegerClient JaegerClient
}
func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.InstanceFactoryFunc {
return func(ctx context.Context, settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
httpClientOptions, err := settings.HTTPClientOptions(ctx)
if err != nil {
return nil, backend.DownstreamError(fmt.Errorf("error reading settings: %w", err))
}
httpClient, err := httpClientProvider.New(httpClientOptions)
if err != nil {
return nil, fmt.Errorf("error creating http client: %w", err)
}
if settings.URL == "" {
return nil, backend.DownstreamError(errors.New("error reading settings: url is empty"))
}
logger := logger.FromContext(ctx)
jaegerClient, err := New(settings.URL, httpClient, logger)
return &datasourceInfo{JaegerClient: jaegerClient}, err
}
}
func (s *Service) getDSInfo(ctx context.Context, pluginCtx backend.PluginContext) (*datasourceInfo, error) {
i, err := s.im.Get(ctx, pluginCtx)
if err != nil {
return nil, err
}
instance, ok := i.(*datasourceInfo)
if !ok {
return nil, errors.New("failed to cast datasource info")
}
return instance, nil
}
func (s *Service) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
client, err := s.getDSInfo(ctx, backend.PluginConfigFromContext(ctx))
if err != nil {
return &backend.CheckHealthResult{
Status: backend.HealthStatusError,
Message: err.Error(),
}, nil
}
if _, err = client.JaegerClient.Services(); err != nil {
return &backend.CheckHealthResult{
Status: backend.HealthStatusError,
Message: err.Error(),
}, nil
}
return &backend.CheckHealthResult{
Status: backend.HealthStatusOk,
Message: "Data source is working",
}, nil
}

View File

@ -1 +0,0 @@
package jaeger

View File

@ -5,7 +5,6 @@ import { catchError, map } from 'rxjs/operators';
import {
DataQueryRequest,
DataQueryResponse,
DataSourceApi,
DataSourceInstanceSettings,
DataSourceJsonData,
dateMath,
@ -17,7 +16,14 @@ import {
urlUtil,
} from '@grafana/data';
import { NodeGraphOptions, SpanBarOptions } from '@grafana/o11y-ds-frontend';
import { BackendSrvRequest, getBackendSrv, getTemplateSrv, TemplateSrv } from '@grafana/runtime';
import {
BackendSrvRequest,
config,
DataSourceWithBackend,
getBackendSrv,
getTemplateSrv,
TemplateSrv,
} from '@grafana/runtime';
import { ALL_OPERATIONS_KEY } from './components/SearchForm';
import { TraceIdTimeParamsOptions } from './configuration/TraceIdTimeParams';
@ -32,7 +38,7 @@ export interface JaegerJsonData extends DataSourceJsonData {
traceIdTimeParams?: TraceIdTimeParamsOptions;
}
export class JaegerDatasource extends DataSourceApi<JaegerQuery, JaegerJsonData> {
export class JaegerDatasource extends DataSourceWithBackend<JaegerQuery, JaegerJsonData> {
uploadedJson: string | ArrayBuffer | null = null;
nodeGraph?: NodeGraphOptions;
traceIdTimeParams?: TraceIdTimeParamsOptions;
@ -188,6 +194,10 @@ export class JaegerDatasource extends DataSourceApi<JaegerQuery, JaegerJsonData>
}
async testDatasource() {
if (config.featureToggles.jaegerBackendMigration) {
return await super.testDatasource();
}
return lastValueFrom(
this._request('/api/services').pipe(
map((res) => {

View File

@ -4,6 +4,7 @@
"id": "jaeger",
"category": "tracing",
"backend": true,
"metrics": true,
"alerting": false,
"annotations": false,