package promlib import ( "context" "encoding/json" "errors" "fmt" "net/http" "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend/log" ) const ( KindPrometheus = "Prometheus" KindMimir = "Mimir" ) var ( ErrNoBuildInfo = errors.New("no build info") ) type BuildInfoRequest struct { PluginContext backend.PluginContext } type BuildInfoResponse struct { Status string `json:"status"` Data BuildInfoResponseData `json:"data"` } type BuildInfoResponseData struct { Version string `json:"version"` Revision string `json:"revision"` Branch string `json:"branch"` Features map[string]string `json:"features"` BuildUser string `json:"buildUser"` BuildDate string `json:"buildDate"` GoVersion string `json:"goVersion"` } func (s *Service) GetBuildInfo(ctx context.Context, req BuildInfoRequest) (*BuildInfoResponse, error) { ds, err := s.getInstance(ctx, req.PluginContext) if err != nil { return nil, err } return getBuildInfo(ctx, ds) } // getBuildInfo queries /api/v1/status/buildinfo func getBuildInfo(ctx context.Context, i *instance) (*BuildInfoResponse, error) { resp, err := i.resource.Execute(ctx, &backend.CallResourceRequest{ Path: "api/v1/status/buildinfo", }) if err != nil { return nil, err } if resp.Status == http.StatusNotFound { return nil, ErrNoBuildInfo } if resp.Status != http.StatusOK { return nil, fmt.Errorf("unexpected response %d", resp.Status) } res := BuildInfoResponse{} if err := json.Unmarshal(resp.Body, &res); err != nil { return nil, fmt.Errorf("failed to unmarshal JSON: %w", err) } return &res, nil } type HeuristicsRequest struct { PluginContext backend.PluginContext } type Heuristics struct { Application string `json:"application"` Features Features `json:"features"` } type Features struct { RulerApiEnabled bool `json:"rulerApiEnabled"` } func (s *Service) GetHeuristics(ctx context.Context, req HeuristicsRequest) (*Heuristics, error) { ds, err := s.getInstance(ctx, req.PluginContext) if err != nil { return nil, err } logger := s.logger.FromContext(ctx) return getHeuristics(ctx, ds, logger) } func getHeuristics(ctx context.Context, i *instance, logger log.Logger) (*Heuristics, error) { heuristics := Heuristics{ Application: "unknown", Features: Features{ RulerApiEnabled: false, }, } buildInfo, err := getBuildInfo(ctx, i) if err != nil { logger.Warn("Failed to get prometheus buildinfo", "err", err.Error()) return nil, fmt.Errorf("failed to get buildinfo: %w", err) } if len(buildInfo.Data.Features) == 0 { // If there are no features then this is a Prometheus datasource heuristics.Application = KindPrometheus heuristics.Features.RulerApiEnabled = false } else { heuristics.Application = KindMimir heuristics.Features.RulerApiEnabled = true } return &heuristics, nil }