Skip to content

Commit b2188d3

Browse files
LasseHelsYing WANG
authored andcommitted
Update mimirtool grafana analyze to support more panel types (#10669)
* add support for custom panel types * add support for bar chart, pie chart, state timeline, status history, histogram, candlestick, canvas, flame graph, geomap, node graph, trend and XY chart panel types * add license header * update CHANGELOG * remove white noise * fix typo
1 parent 9a6226b commit b2188d3

File tree

7 files changed

+612
-393
lines changed

7 files changed

+612
-393
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@
113113

114114
* [BUGFIX] Fix issue where `MIMIR_HTTP_PREFIX` environment variable was ignored and the value from `MIMIR_MIMIR_HTTP_PREFIX` was used instead. #10207
115115
* [ENHANCEMENT] Unify mimirtool authentication options and add extra-headers support for commands that depend on MimirClient. #10178
116+
* [ENHANCEMENT] `mimirtool grafana analyze` now supports custom panels. #10669
117+
* [ENHANCEMENT] `mimirtool grafana analyze` now supports bar chart, pie chart, state timeline, status history,
118+
histogram, candlestick, canvas, flame graph, geomap, node graph, trend, and XY chart panels. #10669
116119

117120
### Mimir Continuous Test
118121

pkg/mimirtool/analyze/grafana.go

Lines changed: 6 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
package analyze
77

88
import (
9-
"encoding/json"
109
"fmt"
1110
"slices"
1211
"strings"
@@ -61,8 +60,8 @@ func ParseMetricsInBoard(mig *MetricsInGrafana, board minisdk.Board) {
6160
// Iterate through all the panels and collect metrics
6261
for _, panel := range board.Panels {
6362
parseErrors = append(parseErrors, metricsFromPanel(*panel, metrics)...)
64-
if panel.RowPanel != nil {
65-
for _, subPanel := range panel.RowPanel.Panels {
63+
if panel.SubPanels != nil {
64+
for _, subPanel := range panel.SubPanels {
6665
parseErrors = append(parseErrors, metricsFromPanel(subPanel, metrics)...)
6766
}
6867
}
@@ -157,48 +156,14 @@ func metricsFromTemplating(templating minisdk.Templating, metrics map[string]str
157156
return parseErrors
158157
}
159158

160-
// Workaround to support Grafana "timeseries" panel. This should
161-
// be implemented in grafana/tools-sdk, and removed from here.
162-
func getCustomPanelTargets(panel minisdk.Panel) *[]minisdk.Target {
163-
if panel.CommonPanel.Type != "timeseries" {
164-
return nil
165-
}
166-
167-
// Heavy handed approach to re-marshal the panel and parse it again
168-
// so that we can extract the 'targets' field in the right format.
169-
170-
bytes, err := json.Marshal(panel.CustomPanel)
171-
if err != nil {
172-
log.Debugln("msg", "panel re-marshalling error", "err", err)
173-
return nil
174-
}
175-
176-
type panelType struct {
177-
Targets []minisdk.Target `json:"targets,omitempty"`
178-
}
179-
180-
var parsedPanel panelType
181-
err = json.Unmarshal(bytes, &parsedPanel)
182-
if err != nil {
183-
log.Debugln("msg", "panel parsing error", "err", err)
184-
return nil
185-
}
186-
187-
return &parsedPanel.Targets
188-
}
189-
190159
func metricsFromPanel(panel minisdk.Panel, metrics map[string]struct{}) []error {
191-
var parseErrors []error
160+
if !panel.SupportsTargets() {
161+
return []error{fmt.Errorf("unsupported panel type: %q", panel.Type)}
162+
}
192163

193164
targets := panel.GetTargets()
194-
if targets == nil {
195-
targets = getCustomPanelTargets(panel)
196-
if targets == nil {
197-
parseErrors = append(parseErrors, fmt.Errorf("unsupported panel type: %q", panel.CommonPanel.Type))
198-
return parseErrors
199-
}
200-
}
201165

166+
var parseErrors []error
202167
for _, target := range *targets {
203168
// Prometheus has this set.
204169
if target.Expr == "" {

pkg/mimirtool/commands/analyse_grafana_test.go

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,29 @@ import (
1919
var dashboardMetrics = []string{
2020
"apiserver_request:availability30d",
2121
"apiserver_request_total",
22+
"bar_chart_metric",
23+
"candlestick_metric",
24+
"canvas_metric",
2225
"cluster_quantile:apiserver_request_duration_seconds:histogram_quantile",
2326
"code_resource:apiserver_request_total:rate5m",
27+
"flame_graph_metric",
28+
"geomap_metric",
2429
"go_goroutines",
30+
"histogram_metric",
2531
"kube_pod_info",
32+
"my_lovely_metric",
33+
"node_graph_metric",
34+
"pie_chart_metric",
35+
"polystat_panel_metric",
2636
"process_cpu_seconds_total",
2737
"process_resident_memory_bytes",
38+
"state_timeline_metric",
39+
"status_history_metric",
40+
"trend_metric",
2841
"workqueue_adds_total",
2942
"workqueue_depth",
3043
"workqueue_queue_duration_seconds_bucket",
44+
"xy_chart_metric",
3145
}
3246

3347
var expectedParseErrors = []string{
@@ -71,18 +85,3 @@ func BenchmarkParseMetricsInBoard(b *testing.B) {
7185
analyze.ParseMetricsInBoard(output, board)
7286
}
7387
}
74-
75-
func TestParseMetricsInBoardWithTimeseriesPanel(t *testing.T) {
76-
var board minisdk.Board
77-
output := &analyze.MetricsInGrafana{}
78-
output.OverallMetrics = make(map[string]struct{})
79-
80-
buf, err := loadFile("testdata/timeseries.json")
81-
require.NoError(t, err)
82-
83-
err = json.Unmarshal(buf, &board)
84-
require.NoError(t, err)
85-
86-
analyze.ParseMetricsInBoard(output, board)
87-
assert.Equal(t, []string{"my_lovely_metric"}, output.Dashboards[0].Metrics)
88-
}

0 commit comments

Comments
 (0)