Zipkin: Run health check through backend (#96031)
* Zipkin: Run health check through backend * Mark some errors as downstream * Update pkg/tsdb/zipkin/zipkin.go Co-authored-by: Will Browne <wbrowne@users.noreply.github.com> * Use errors.New where error formatting is not needed * Remove executable in plugin.json * Fix joining the path * Keep logger as global and then create from context * Close the res body --------- Co-authored-by: Will Browne <wbrowne@users.noreply.github.com>
This commit is contained in:
co-authored by
Will Browne
parent
21ba507bcb
commit
4d0a7637b2
@@ -0,0 +1,50 @@
|
||||
package zipkin
|
||||
|
||||
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 ZipkinClient struct {
|
||||
logger log.Logger
|
||||
url string
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
func New(url string, hc *http.Client, logger log.Logger) (ZipkinClient, error) {
|
||||
client := ZipkinClient{
|
||||
logger: logger,
|
||||
url: url,
|
||||
httpClient: hc,
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// Services returns list of services
|
||||
// https://zipkin.io/zipkin-api/#/default/get_services
|
||||
func (z *ZipkinClient) Services() ([]string, error) {
|
||||
services := []string{}
|
||||
u, err := url.JoinPath(z.url, "/api/v2/services")
|
||||
if err != nil {
|
||||
return services, backend.DownstreamError(fmt.Errorf("failed to join url: %w", err))
|
||||
}
|
||||
res, err := z.httpClient.Get(u)
|
||||
if err != nil {
|
||||
return services, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err = res.Body.Close(); err != nil {
|
||||
z.logger.Error("Failed to close response body", "error", err)
|
||||
}
|
||||
}()
|
||||
if err := json.NewDecoder(res.Body).Decode(&services); err != nil {
|
||||
return services, err
|
||||
}
|
||||
return services, err
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package zipkin
|
||||
|
||||
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.zipkin")
|
||||
|
||||
type Service struct {
|
||||
im instancemgmt.InstanceManager
|
||||
}
|
||||
|
||||
func ProvideService(httpClientProvider httpclient.Provider) *Service {
|
||||
return &Service{
|
||||
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
|
||||
}
|
||||
}
|
||||
|
||||
type datasourceInfo struct {
|
||||
ZipkinClient ZipkinClient
|
||||
}
|
||||
|
||||
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)
|
||||
zipkinClient, err := New(settings.URL, httpClient, logger)
|
||||
return &datasourceInfo{ZipkinClient: zipkinClient}, 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.ZipkinClient.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
|
||||
}
|
||||
Reference in New Issue
Block a user