diff --git a/pkg/analyse/dashboard.go b/pkg/analyse/dashboard.go new file mode 100644 index 000000000..9d39fb47a --- /dev/null +++ b/pkg/analyse/dashboard.go @@ -0,0 +1,36 @@ +package analyse + +type ( + Board struct { + ID uint `json:"id,omitempty"` + UID string `json:"uid,omitempty"` + Slug string `json:"slug"` + Title string `json:"title"` + Panels []*Panel `json:"panels"` + Rows []*Row `json:"rows"` + Templating Templating `json:"templating"` + } + Templating struct { + List []TemplateVar `json:"list"` + } + TemplateVar struct { + Name string `json:"name"` + Query interface{} `json:"query"` + Type string `json:"type"` + } + Panel struct { + Targets []Target `json:"targets,omitempty"` + Title string `json:"title"` + Panels []Panel `json:"panels"` // row panel type + Type string `json:"type"` + } + Target struct { + RefID string `json:"refId"` + Datasource string `json:"datasource,omitempty"` + // For Prometheus + Expr string `json:"expr,omitempty"` + } + Row struct { + Panels []Panel `json:"panels"` + } +) diff --git a/pkg/analyse/grafana.go b/pkg/analyse/grafana.go index 780189e25..08d586389 100644 --- a/pkg/analyse/grafana.go +++ b/pkg/analyse/grafana.go @@ -8,7 +8,6 @@ import ( log "github.com/sirupsen/logrus" - "github.com/grafana-tools/sdk" "github.com/pkg/errors" "github.com/prometheus/prometheus/promql/parser" ) @@ -27,15 +26,16 @@ type DashboardMetrics struct { ParseErrors []string `json:"parse_errors"` } -func ParseMetricsInBoard(mig *MetricsInGrafana, board sdk.Board) { +func ParseMetricsInBoard(mig *MetricsInGrafana, board Board) { var parseErrors []error metrics := make(map[string]struct{}) // Iterate through all the panels and collect metrics for _, panel := range board.Panels { parseErrors = append(parseErrors, metricsFromPanel(*panel, metrics)...) - if panel.RowPanel != nil { - for _, subPanel := range panel.RowPanel.Panels { + // row panel + if panel.Panels != nil { + for _, subPanel := range panel.Panels { parseErrors = append(parseErrors, metricsFromPanel(subPanel, metrics)...) } } @@ -77,7 +77,7 @@ func ParseMetricsInBoard(mig *MetricsInGrafana, board sdk.Board) { } -func metricsFromTemplating(templating sdk.Templating, metrics map[string]struct{}) []error { +func metricsFromTemplating(templating Templating, metrics map[string]struct{}) []error { parseErrors := []error{} for _, templateVar := range templating.List { if templateVar.Type != "query" { @@ -100,8 +100,8 @@ func metricsFromTemplating(templating sdk.Templating, metrics map[string]struct{ } err := parseQuery(query, metrics) if err != nil { - parseErrors = append(parseErrors, errors.Wrapf(err, "query=%v", query)) - log.Debugln("msg", "promql parse error", "err", err, "query", query) + parseErrors = append(parseErrors, errors.Wrapf(err, "error parsing templating query: %v", query)) + log.Debugln("msg", "promql parse error: templating query", "err", err, "query", query) continue } } else { @@ -114,16 +114,16 @@ func metricsFromTemplating(templating sdk.Templating, metrics map[string]struct{ return parseErrors } -func metricsFromPanel(panel sdk.Panel, metrics map[string]struct{}) []error { +// for now, only look at panels with a prometheus datasource/targets +func metricsFromPanel(panel Panel, metrics map[string]struct{}) []error { var parseErrors []error - targets := panel.GetTargets() - if targets == nil { - parseErrors = append(parseErrors, fmt.Errorf("unsupported panel type: %q", panel.CommonPanel.Type)) + if panel.Targets == nil { + parseErrors = append(parseErrors, fmt.Errorf("unsupported panel type (no targets in panel): %q", panel.Type)) return parseErrors } - for _, target := range *targets { + for _, target := range panel.Targets { // Prometheus has this set. if target.Expr == "" { continue diff --git a/pkg/commands/analyse_dashboards.go b/pkg/commands/analyse_dashboards.go index d099ec717..a75585d36 100644 --- a/pkg/commands/analyse_dashboards.go +++ b/pkg/commands/analyse_dashboards.go @@ -5,7 +5,6 @@ import ( "fmt" "os" - "github.com/grafana-tools/sdk" "gopkg.in/alecthomas/kingpin.v2" "github.com/grafana/cortex-tools/pkg/analyse" @@ -21,7 +20,7 @@ func (cmd *DashboardAnalyseCommand) run(k *kingpin.ParseContext) error { output.OverallMetrics = make(map[string]struct{}) for _, file := range cmd.DashFilesList { - var board sdk.Board + var board analyse.Board buf, err := loadFile(file) if err != nil { return err diff --git a/pkg/commands/analyse_grafana.go b/pkg/commands/analyse_grafana.go index aff46068d..a55a2dd07 100644 --- a/pkg/commands/analyse_grafana.go +++ b/pkg/commands/analyse_grafana.go @@ -24,7 +24,13 @@ type GrafanaAnalyseCommand struct { } func (cmd *GrafanaAnalyseCommand) run(k *kingpin.ParseContext) error { - output := &analyse.MetricsInGrafana{} + var ( + boardLinks []sdk.FoundBoard + rawBoard []byte + board analyse.Board + err error + output *analyse.MetricsInGrafana + ) output.OverallMetrics = make(map[string]struct{}) ctx, cancel := context.WithTimeout(context.Background(), cmd.readTimeout) @@ -35,15 +41,20 @@ func (cmd *GrafanaAnalyseCommand) run(k *kingpin.ParseContext) error { return err } - boardLinks, err := c.SearchDashboards(ctx, "", false) + boardLinks, err = c.SearchDashboards(ctx, "", false) if err != nil { return err } for _, link := range boardLinks { - board, _, err := c.GetDashboardByUID(ctx, link.UID) + rawBoard, _, err = c.GetRawDashboardBySlug(ctx, link.URI) if err != nil { - fmt.Fprintf(os.Stderr, "%s for %s %s\n", err, link.UID, link.Title) + fmt.Fprintf(os.Stderr, "%s for %s\n", err, link.URI) + continue + } + + if err = json.Unmarshal(rawBoard, &board); err != nil { + fmt.Fprintf(os.Stderr, "%s for %s\n", err, link.URI) continue } analyse.ParseMetricsInBoard(output, board) diff --git a/pkg/commands/analyse_grafana_test.go b/pkg/commands/analyse_grafana_test.go index 4a82ffc23..4cff3a14e 100644 --- a/pkg/commands/analyse_grafana_test.go +++ b/pkg/commands/analyse_grafana_test.go @@ -4,7 +4,6 @@ import ( "encoding/json" "testing" - "github.com/grafana-tools/sdk" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -25,7 +24,7 @@ var dashboardMetrics = []string{ } func TestParseMetricsInBoard(t *testing.T) { - var board sdk.Board + var board analyse.Board output := &analyse.MetricsInGrafana{} output.OverallMetrics = make(map[string]struct{}) @@ -40,7 +39,7 @@ func TestParseMetricsInBoard(t *testing.T) { } func TestParseMetricsInBoardWithTimeseriesPanel(t *testing.T) { - var board sdk.Board + var board analyse.Board output := &analyse.MetricsInGrafana{} output.OverallMetrics = make(map[string]struct{})